UNPKG

realm-object-server

Version:

Realm Object Server

96 lines 4.58 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const AuthProvider_1 = require("../AuthProvider"); const _ = require("lodash"); const errors = require("../../errors"); const jwt = require("jsonwebtoken"); const jsonpath = require("jsonpath"); class JwtAuthProvider extends AuthProvider_1.AuthProvider { constructor(config) { super(); this.publicKey = config.publicKey; this.userIdFieldName = config.userIdFieldName || "userId"; this.isAdminQuery = config.isAdminQuery || { path: "$.isAdmin", value: true }; this.requiredClaims = config.requiredClaims || {}; this.name = config.providerName || "jwt"; this.charactersToEscape = (config.charactersToEscape || ["|", "@"]).map(c => new RegExp(_.escapeRegExp(c), "g")); this.clockTolerance = config.clockTolerance || 5; if (config.requiredAttributes) { if (config.requiredClaims) { throw new Error("Cannot set both requiredClaims and requiredAttributes"); } for (const key in config.requiredAttributes) { this.requiredClaims[`$["${key}"]`] = config.requiredAttributes[key]; } } if (config.isAdminFieldName) { if (config.isAdminQuery) { throw new Error("Cannot set both isAdminFieldName/isAdminValue and isAdminQuery"); } this.isAdminQuery = { path: `$["${config.isAdminFieldName}"]`, value: config.isAdminValue === undefined || config.isAdminValue }; } } authenticateOrCreateUser(body) { return __awaiter(this, void 0, void 0, function* () { const accessToken = body.data; if (accessToken === undefined) { throw new errors.realm.MissingParameters("access token"); } const payload = yield this.verifyAndDecode(accessToken); if (!payload || !payload[this.userIdFieldName]) { throw new errors.realm.InvalidCredentials({ detail: `The payload is missing or it doesn't contain the field ${this.userIdFieldName}` }); } for (const rc in this.requiredClaims) { if (jsonpath.value(payload, rc) !== this.requiredClaims[rc]) { throw new errors.realm.InvalidCredentials({ detail: "The payload does not contain the required claims", }); } } const isAdmin = this.isAdminQuery ? (jsonpath.value(payload, this.isAdminQuery.path) === this.isAdminQuery.value) : false; const userId = this.escapeUserId(payload[this.userIdFieldName]); const foundUser = this.service.getUserByProviderId(this.name, userId); if (foundUser && foundUser.isAdmin === isAdmin) { return foundUser; } return this.service.createOrUpdateUser(userId, this.name, isAdmin, null, userId); }); } escapeUserId(userId) { let escaped = userId; if (this.charactersToEscape) { for (const character of this.charactersToEscape) { escaped = escaped.replace(character, "_"); } } return escaped; } verifyAndDecode(token) { return new Promise((resolve, reject) => { jwt.verify(token, this.publicKey, { algorithms: ["RS256"], clockTolerance: this.clockTolerance }, (err, decoded) => { if (err) { this.service.logger.error("Error verifying JWT token", { error: err }); reject(new errors.realm.InvalidCredentials({ detail: err.message })); } else { resolve(decoded); } }); }); } } exports.JwtAuthProvider = JwtAuthProvider; //# sourceMappingURL=JwtAuthProvider.js.map