UNPKG

@solid/community-server

Version:

Community Solid Server: an open and modular implementation of the Solid specifications

63 lines 3.32 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PermissionBasedAuthorizer = void 0; const global_logger_factory_1 = require("global-logger-factory"); const ForbiddenHttpError_1 = require("../util/errors/ForbiddenHttpError"); const UnauthorizedHttpError_1 = require("../util/errors/UnauthorizedHttpError"); const Authorizer_1 = require("./Authorizer"); /** * Authorizer that bases its decision on the output it gets from its PermissionReader. * For each permission it checks if the reader allows that for at least one credential type, * if yes, authorization is granted. * `undefined` values for reader results are interpreted as `false`. */ class PermissionBasedAuthorizer extends Authorizer_1.Authorizer { logger = (0, global_logger_factory_1.getLoggerFor)(this); async handle(input) { const { credentials, requestedModes, availablePermissions } = input; // Ensure all required modes are within the agent's permissions. for (const [identifier, modes] of requestedModes.entrySets()) { const modeString = [...modes].join(','); this.logger.debug(`Checking if ${JSON.stringify(credentials)} has ${modeString} permissions for ${identifier.path}`); const permissionSet = availablePermissions.get(identifier) ?? {}; for (const mode of modes) { this.requireModePermission(credentials, permissionSet, mode); } this.logger.debug(`${JSON.stringify(credentials)} has ${modeString} permissions for ${identifier.path}`); } } /** * Ensures that at least one of the credentials provides permissions for the given mode. * Throws a {@link ForbiddenHttpError} or {@link UnauthorizedHttpError} depending on the credentials * if access is not allowed. * * @param credentials - Credentials that require access. * @param permissionMap - PermissionMap describing the available permissions of the credentials. * @param mode - Which mode is requested. */ requireModePermission(credentials, permissionMap, mode) { if (!permissionMap[mode]) { if (this.isAuthenticated(credentials)) { this.logger.warn(`Agent ${JSON.stringify(credentials)} has no ${mode} permissions`); throw new ForbiddenHttpError_1.ForbiddenHttpError(); } else { // Solid, §2.1: "When a client does not provide valid credentials when requesting a resource that requires it, // the data pod MUST send a response with a 401 status code (unless 404 is preferred for security reasons)." // https://solid.github.io/specification/protocol#http-server this.logger.warn(`Unauthenticated agent has no ${mode} permissions`); throw new UnauthorizedHttpError_1.UnauthorizedHttpError(); } } } /** * Checks whether the agent is authenticated (logged in) or not (public/anonymous). * * @param credentials - Credentials to check. */ isAuthenticated(credentials) { return Object.values(credentials).some((cred) => cred !== undefined); } } exports.PermissionBasedAuthorizer = PermissionBasedAuthorizer; //# sourceMappingURL=PermissionBasedAuthorizer.js.map