{"version":3,"sources":["jsdelivr-header.js","/npm/hapi-auth-keycloak@5.1.2/src/index.js"],"names":[],"mappings":"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","file":"/npm/hapi-auth-keycloak@5.1.2/src/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/hapi-auth-keycloak@5.1.2/src/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","const got = require('got')\nconst GrantManager = require('keycloak-connect/middleware/auth-utils/grant-manager')\nconst KeycloakToken = require('keycloak-connect/middleware/auth-utils/token')\nconst apiKey = require('./apiKey')\nconst cache = require('./cache')\nconst token = require('./token')\nconst { verifyStrategyOptions, verifyPluginOptions } = require('./utils')\nconst { raiseUnauthorized, errorMessages, fakeToolkit } = require('./utils')\nconst pkg = require('../package.json')\n\n/**\n * @type {Object}\n * @private\n *\n * The plugin & strategy related options and instances.\n */\nconst manager = {}\nconst store = {}\nlet options = {}\nlet pluginOptions\n\n/**\n * @function\n * @private\n *\n * Verify the signed token offline with help of the related\n * public key or online with the Keycloak server and JWKS.\n * Both are non-live. Resolve if the verification succeeded.\n *\n * @param {string} tkn The token to be validated\n * @param {string} name The unique name of the strategy\n * @returns {Promise} The error-handled promise\n */\nasync function verifySignedJwt (tkn, name) {\n  const { clientId } = options[name]\n  const kcTkn = new KeycloakToken(tkn, clientId)\n  await manager[name].validateToken(kcTkn, 'Bearer')\n\n  return tkn\n}\n\n/**\n * @function\n * @private\n *\n * Validate the token live with help of the related\n * Keycloak server, the client identifier and its secret.\n * Resolve if the request succeeded and token is valid.\n *\n * @param {string} tkn The token to be validated\n * @param {string} name The unique name of the strategy\n * @returns {Promise} The error-handled promise\n *\n * @throws {Error} If token is invalid or request failed\n */\nasync function introspect (tkn, name) {\n  try {\n    const isValid = await manager[name].validateAccessToken(tkn)\n    if (isValid === false) throw Error(errorMessages.invalid)\n  } catch (err) {\n    throw Error(errorMessages.invalid)\n  }\n\n  return tkn\n}\n\n/**\n * @function\n * @private\n *\n * Retrieve the Requesting Party Token from the Keycloak Server.\n *\n * @param {string} tkn The token to be used for authentication\n * @param {string} name The unique name of the strategy\n * @returns {Promise} The modified, non-error-handling promise\n *\n * @throws {Error} If token is invalid or request failed\n */\nasync function getRpt (tkn, name) {\n  const { realmUrl, clientId } = options[name]\n  let body = {}\n\n  try {\n    ({ body } = await got.get(`${realmUrl}/authz/entitlement/${clientId}`, {\n      headers: { authorization: `bearer ${tkn}` }\n    }))\n  } catch (err) {\n    throw Error(errorMessages.rpt)\n  }\n\n  return body.rpt\n}\n\n/**\n * @function\n * @private\n *\n * Get validation strategy based on the options.\n * If `secret` is set the token gets introspected.\n * If `entitlement` is truthy it retrieves the RPT.\n * Else perform a non-live validation with public keys.\n *\n * @param {string} name The unique name of the strategy\n * @returns {Function} The related validation strategy\n */\nfunction getValidateFn (name) {\n  const { secret, entitlement } = options[name]\n  return secret ? introspect : entitlement ? getRpt : verifySignedJwt\n}\n\n/**\n * @function\n * @public\n *\n * Validate a token either with the help of Keycloak or a\n * related public key. Store the user data in cache if enabled.\n *\n * @param {string} tkn The token to be validated\n * @param {string} name The unique name of the strategy\n * @param {Function} h The toolkit\n *\n * @throws {Boom.unauthorized} If previous validation fails\n */\nasync function handleKeycloakValidation (tkn, name, h) {\n  try {\n    const info = await getValidateFn(name)(tkn, name)\n    const { expiresIn, credentials } = token.getData(info || tkn, options[name])\n    const userData = { credentials }\n\n    await cache.set(store[name], tkn, userData, expiresIn)\n    return h.authenticated(userData)\n  } catch (err) {\n    throw raiseUnauthorized(errorMessages.invalid, err.message, name)\n  }\n}\n\n/**\n * @function\n * @public\n *\n * Expect `Authorization: bearer x.y.z` as header.\n * If the token was sent before and is still cached,\n * return the cached user data as credentials.\n * Otherwise handle validation with help of Keycloak.\n *\n * @param {string} field The authorization field, e.g. the value of `Authorization`\n * @param {string} name The unique name of the strategy\n * @param {Object} [h = (data)  => data] The reply toolkit\n *\n * @throws {Boom.unauthorized} If header is missing or has an invalid format\n */\nasync function validate (field, name, h = (data) => data) {\n  if ((!!name && !(name in options)) || (Object.keys(options).length > 1 && !name)) {\n    throw raiseUnauthorized(errorMessages.missingName)\n  }\n\n  if (Object.keys(options).length === 1 && !name) {\n    name = Object.keys(options)[0]\n  }\n\n  if (!field) {\n    throw raiseUnauthorized(errorMessages.missing, null, name)\n  }\n\n  const tkn = token.create(field)\n  const reply = fakeToolkit(h)\n\n  if (!tkn) {\n    throw raiseUnauthorized(errorMessages.invalid, null, name)\n  }\n\n  const cached = await cache.get(store[name], tkn)\n  return cached ? reply.authenticated(cached) : handleKeycloakValidation(tkn, name, reply)\n}\n\n/**\n * @function\n * @private\n *\n * The authentication strategy based on keycloak.\n * Initialize memory cache, grant manager for keycloak.\n *\n * @param {Hapi.Server} server The created server instance\n * @param {Object} strategyOptions The strategy related options\n * @returns {Object} The authentication scheme\n */\nfunction strategy (server, strategyOptions) {\n  const mergedOptions = { ...pluginOptions, ...strategyOptions }\n  delete mergedOptions.apiKey\n\n  const opts = verifyStrategyOptions(mergedOptions)\n\n  if (process.env.NODE_ENV !== 'test' && opts.name in options) {\n    throw Error(`The passed name '${opts.name}' already exists.`)\n  }\n\n  options[opts.name] = opts\n  manager[opts.name] = new GrantManager(opts)\n  store[opts.name] = cache.create(server, opts.cache)\n\n  return {\n    authenticate (request, h) {\n      return validate(request.raw.req.headers.authorization, opts.name, h)\n    }\n  }\n}\n\n/**\n * @function\n * @public\n *\n * The authentication plugin handler.\n * Initialize api key handler and register auth schemes.\n *\n * @param {Hapi.Server} server The created server instance\n * @param {Object} opts The plugin related options\n */\nfunction register (server, opts) {\n  pluginOptions = verifyPluginOptions(opts)\n  apiKey.init(server, pluginOptions)\n\n  server.auth.scheme('keycloak-jwt', strategy)\n  server.decorate('server', 'kjwt', {\n    validate,\n    getOptions: () => options,\n    resetOptions: () => { options = {} }\n  })\n}\n\nmodule.exports = { register, pkg }\n"]}