# Local HedgeDoc authentication fix

HedgeDoc 1.12.2, AGPL-3.0. Original source: https://github.com/hedgedoc/hedgedoc/blob/1.12.2/lib/web/auth/utils.js

Local change: resolve models inside the OAuth callback after initialization to avoid a circular module reference. All other logic is unchanged. Complete modified file:

```javascript
'use strict'
import Scrypt from 'scrypt-kdf'
import { createRequire } from 'module'

const require = createRequire(import.meta.url)
const { Op } = require('sequelize')
const logger = require('../../logger')

export const passportGeneralCallback = (providerName) => function callback (accessToken, refreshToken, profile, done) {
  // Resolve after model initialization to avoid the user/auth ESM require cycle.
  const models = require('../../models')
  const stringifiedProfile = JSON.stringify(profile)
  models.User.findOrCreate({
    where: {
      [Op.and]: [
        {
          profileid: profile.id.toString()
        },
        {
          profileProvider: {
            [Op.or]: [
              {
                [Op.eq]: providerName
              },
              {
                [Op.eq]: null
              }
            ]
          }
        }
      ]
    },
    defaults:
      {
        profile: stringifiedProfile,
        profileProvider: providerName,
        accessToken,
        refreshToken
      }
  }).spread(function (user, created) {
    if (user) {
      let needSave = false
      if (user.profile !== stringifiedProfile) {
        user.profile = stringifiedProfile
        needSave = true
      }
      if (user.accessToken !== accessToken) {
        user.accessToken = accessToken
        needSave = true
      }
      if (user.refreshToken !== refreshToken) {
        user.refreshToken = refreshToken
        needSave = true
      }
      if (user.profileProvider === null) {
        user.profileProvider = providerName
        needSave = true
      }
      if (needSave) {
        user.save().then(function () {
          logger.debug(`user login: ${user.id}`)
          return done(null, user)
        })
      } else {
        logger.debug(`user login: ${user.id}`)
        return done(null, user)
      }
    }
  }).catch(function (err) {
    logger.error('auth callback failed: ' + err)
    return done(err, null)
  })
}

export async function verifyPassword (input, hashed) {
  try {
    return (await Scrypt.verify(Buffer.from(hashed, 'hex'), input))
  } catch (error) {
    logger.error(`Error during login: ${error}`)
    return false
  }
}

```


## Permission compatibility fix

Original source: https://github.com/hedgedoc/hedgedoc/blob/1.12.2/lib/permissions.js

Preserve authentication checks for both Passport HTTP requests and realtime requests; normalize the model owner field. Complete modified file:

```javascript
export const allowedPermissionValues = ['freely', 'editable', 'limited', 'locked', 'protected', 'private']

export function checkViewPermission (req, note) {
  const permission = note.permission
  // Passport HTTP users and realtime users have different authentication shapes.
  const loggedIn = req.user && (typeof req.isAuthenticated === 'function'
    ? req.isAuthenticated()
    : req.user.logged_in)
  const ownerId = note.ownerId || (note.owner && typeof note.owner === 'object' ? note.owner.id : note.owner)

  // Private notes should only be readable to their owner
  if (permission === 'private') {
    return loggedIn && req.user.id === ownerId
  }

  // Limited and protected notes should be readable by all logged-in users
  if (permission === 'limited' || permission === 'protected') {
    return loggedIn
  }

  // Freely, Editable and Locked notes should be readable by everyone
  if (permission === 'freely' || permission === 'editable' || permission === 'locked') {
    return true
  }

  // Invalid permission
  return false
}

```
