import isNativeToken from "./common/is-native-token.js"; import { Users, AccessTokens, Apps } from "../../models/index.js"; import { Cache } from "../../misc/cache.js"; import { localUserByIdCache, localUserByNativeTokenCache } from "../../services/user-cache.js"; const appCache = new Cache("app", 60 * 30); export class AuthenticationError extends Error { constructor(message){ super(message); this.name = "AuthenticationError"; } } export default (async (authorization, bodyToken, bypassUserCache = false)=>{ let token = null; // check if there is an authorization header set if (authorization != null) { if (bodyToken != null) { throw new AuthenticationError("using multiple authorization schemes"); } // check if OAuth 2.0 Bearer tokens are being used // Authorization schemes are case insensitive if (authorization.substring(0, 7).toLowerCase() === "bearer ") { token = authorization.substring(7); } else { throw new AuthenticationError("unsupported authentication scheme"); } } else if (bodyToken != null) { token = bodyToken; } else { return [ null, null ]; } if (isNativeToken(token)) { const user = bypassUserCache ? await Users.findOneBy({ token }) : await localUserByNativeTokenCache.fetch(token, ()=>Users.findOneBy({ token: token ?? undefined }), true); if (user == null) { throw new AuthenticationError("unknown token"); } return [ user, null ]; } else { const accessToken = await AccessTokens.findOne({ where: [ { hash: token.toLowerCase() }, { token: token } ] }); if (accessToken == null) { throw new AuthenticationError("unknown token"); } AccessTokens.update(accessToken.id, { lastUsedAt: new Date() }); const user = bypassUserCache ? await Users.findOneBy({ id: accessToken.userId }) : await localUserByIdCache.fetch(accessToken.userId, ()=>Users.findOneBy({ id: accessToken.userId }), true); if (accessToken.appId) { const app = await appCache.fetch(accessToken.appId, ()=>Apps.findOneByOrFail({ id: accessToken.appId }), true); return [ user, { id: accessToken.id, permission: app.permission } ]; } else { return [ user, accessToken ]; } } });