UNPKG

@backstage/backend-defaults

Version:

Backend defaults used by Backstage backend apps

135 lines (131 loc) 4.61 kB
'use strict'; var errors = require('@backstage/errors'); var jose = require('jose'); var helpers = require('./helpers.cjs.js'); class DefaultAuthService { constructor(userTokenHandler, pluginTokenHandler, externalTokenHandler, pluginId, disableDefaultAuthPolicy, pluginKeySource) { this.userTokenHandler = userTokenHandler; this.pluginTokenHandler = pluginTokenHandler; this.externalTokenHandler = externalTokenHandler; this.pluginId = pluginId; this.disableDefaultAuthPolicy = disableDefaultAuthPolicy; this.pluginKeySource = pluginKeySource; } async authenticate(token, options) { const pluginResult = await this.pluginTokenHandler.verifyToken(token); if (pluginResult) { if (pluginResult.limitedUserToken) { const userResult2 = await this.userTokenHandler.verifyToken( pluginResult.limitedUserToken ); if (!userResult2) { throw new errors.AuthenticationError( "Invalid user token in plugin token obo claim" ); } return helpers.createCredentialsWithUserPrincipal( userResult2.userEntityRef, pluginResult.limitedUserToken, this.#getJwtExpiration(pluginResult.limitedUserToken), pluginResult.subject ); } return helpers.createCredentialsWithServicePrincipal(pluginResult.subject); } const userResult = await this.userTokenHandler.verifyToken(token); if (userResult) { if (!options?.allowLimitedAccess && this.userTokenHandler.isLimitedUserToken(token)) { throw new errors.AuthenticationError("Illegal limited user token"); } return helpers.createCredentialsWithUserPrincipal( userResult.userEntityRef, token, this.#getJwtExpiration(token) ); } const externalResult = await this.externalTokenHandler.verifyToken(token); if (externalResult) { return helpers.createCredentialsWithServicePrincipal( externalResult.subject, void 0, externalResult.accessRestrictions ); } throw new errors.AuthenticationError("Illegal token"); } isPrincipal(credentials, type) { const principal = credentials.principal; if (type === "unknown") { return true; } if (principal.type !== type) { return false; } return true; } async getNoneCredentials() { return helpers.createCredentialsWithNonePrincipal(); } async getOwnServiceCredentials() { return helpers.createCredentialsWithServicePrincipal(`plugin:${this.pluginId}`); } async getPluginRequestToken(options) { const { targetPluginId } = options; const internalForward = helpers.toInternalBackstageCredentials(options.onBehalfOf); const { type } = internalForward.principal; if (type === "none" && this.disableDefaultAuthPolicy) { return { token: "" }; } switch (type) { // TODO: Check whether the principal is ourselves case "service": return this.pluginTokenHandler.issueToken({ pluginId: this.pluginId, targetPluginId }); case "user": { const { token } = internalForward; if (!token) { throw new Error("User credentials is unexpectedly missing token"); } const onBehalfOf = await this.userTokenHandler.createLimitedUserToken( token ); return this.pluginTokenHandler.issueToken({ pluginId: this.pluginId, targetPluginId, onBehalfOf: { limitedUserToken: onBehalfOf.token, expiresAt: onBehalfOf.expiresAt } }); } default: throw new errors.AuthenticationError( `Refused to issue service token for credential type '${type}'` ); } } async getLimitedUserToken(credentials) { const { token: backstageToken } = helpers.toInternalBackstageCredentials(credentials); if (!backstageToken) { throw new errors.AuthenticationError( "User credentials is unexpectedly missing token" ); } return this.userTokenHandler.createLimitedUserToken(backstageToken); } async listPublicServiceKeys() { const { keys } = await this.pluginKeySource.listKeys(); return { keys: keys.map(({ key }) => key) }; } #getJwtExpiration(token) { const { exp } = jose.decodeJwt(token); if (!exp) { throw new errors.AuthenticationError("User token is missing expiration"); } return new Date(exp * 1e3); } } exports.DefaultAuthService = DefaultAuthService; //# sourceMappingURL=DefaultAuthService.cjs.js.map