Files
erp-system/.next/dev/server/chunks/node_modules_openid-client_0681y5w._.js
T
2026-05-20 18:58:23 +00:00

3392 lines
130 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
module.exports = [
"[project]/node_modules/openid-client/lib/errors.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const { format } = __turbopack_context__.r("[externals]/util [external] (util, cjs)");
class OPError extends Error {
constructor({ error_description, error, error_uri, session_state, state, scope }, response){
super(!error_description ? error : `${error} (${error_description})`);
Object.assign(this, {
error
}, error_description && {
error_description
}, error_uri && {
error_uri
}, state && {
state
}, scope && {
scope
}, session_state && {
session_state
});
if (response) {
Object.defineProperty(this, 'response', {
value: response
});
}
this.name = this.constructor.name;
Error.captureStackTrace(this, this.constructor);
}
}
class RPError extends Error {
constructor(...args){
if (typeof args[0] === 'string') {
super(format(...args));
} else {
const { message, printf, response, ...rest } = args[0];
if (printf) {
super(format(...printf));
} else {
super(message);
}
Object.assign(this, rest);
if (response) {
Object.defineProperty(this, 'response', {
value: response
});
}
}
this.name = this.constructor.name;
Error.captureStackTrace(this, this.constructor);
}
}
module.exports = {
OPError,
RPError
};
}),
"[project]/node_modules/openid-client/lib/helpers/is_key_object.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const util = __turbopack_context__.r("[externals]/util [external] (util, cjs)");
const crypto = __turbopack_context__.r("[externals]/crypto [external] (crypto, cjs)");
module.exports = util.types.isKeyObject || ((obj)=>obj && obj instanceof crypto.KeyObject);
}),
"[project]/node_modules/openid-client/lib/helpers/base64url.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
let encode;
if (Buffer.isEncoding('base64url')) {
encode = (input, encoding = 'utf8')=>Buffer.from(input, encoding).toString('base64url');
} else {
const fromBase64 = (base64)=>base64.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
encode = (input, encoding = 'utf8')=>fromBase64(Buffer.from(input, encoding).toString('base64'));
}
const decode = (input)=>Buffer.from(input, 'base64');
module.exports.decode = decode;
module.exports.encode = encode;
}),
"[project]/node_modules/openid-client/lib/helpers/decode_jwt.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const base64url = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/base64url.js [app-route] (ecmascript)");
module.exports = (token)=>{
if (typeof token !== 'string' || !token) {
throw new TypeError('JWT must be a string');
}
const { 0: header, 1: payload, 2: signature, length } = token.split('.');
if (length === 5) {
throw new TypeError('encrypted JWTs cannot be decoded');
}
if (length !== 3) {
throw new Error('JWTs must have three components');
}
try {
return {
header: JSON.parse(base64url.decode(header)),
payload: JSON.parse(base64url.decode(payload)),
signature
};
} catch (err) {
throw new Error('JWT is malformed');
}
};
}),
"[project]/node_modules/openid-client/lib/helpers/is_plain_object.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
module.exports = (a)=>!!a && a.constructor === Object;
}),
"[project]/node_modules/openid-client/lib/helpers/defaults.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const isPlainObject = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/is_plain_object.js [app-route] (ecmascript)");
function defaults(deep, target, ...sources) {
for (const source of sources){
if (!isPlainObject(source)) {
continue;
}
for (const [key, value] of Object.entries(source)){
/* istanbul ignore if */ if (key === '__proto__' || key === 'constructor') {
continue;
}
if (typeof target[key] === 'undefined' && typeof value !== 'undefined') {
target[key] = value;
}
if (deep && isPlainObject(target[key]) && isPlainObject(value)) {
defaults(true, target[key], value);
}
}
}
return target;
}
module.exports = defaults.bind(undefined, false);
module.exports.deep = defaults.bind(undefined, true);
}),
"[project]/node_modules/openid-client/lib/helpers/www_authenticate_parser.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const REGEXP = /(\w+)=("[^"]*")/g;
module.exports = (wwwAuthenticate)=>{
const params = {};
try {
while(REGEXP.exec(wwwAuthenticate) !== null){
if (RegExp.$1 && RegExp.$2) {
params[RegExp.$1] = RegExp.$2.slice(1, -1);
}
}
} catch (err) {}
return params;
};
}),
"[project]/node_modules/openid-client/lib/helpers/assert.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
function assertSigningAlgValuesSupport(endpoint, issuer, properties) {
if (!issuer[`${endpoint}_endpoint`]) return;
const eam = `${endpoint}_endpoint_auth_method`;
const easa = `${endpoint}_endpoint_auth_signing_alg`;
const easavs = `${endpoint}_endpoint_auth_signing_alg_values_supported`;
if (properties[eam] && properties[eam].endsWith('_jwt') && !properties[easa] && !issuer[easavs]) {
throw new TypeError(`${easavs} must be configured on the issuer if ${easa} is not defined on a client`);
}
}
function assertIssuerConfiguration(issuer, endpoint) {
if (!issuer[endpoint]) {
throw new TypeError(`${endpoint} must be configured on the issuer`);
}
}
module.exports = {
assertSigningAlgValuesSupport,
assertIssuerConfiguration
};
}),
"[project]/node_modules/openid-client/lib/helpers/pick.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
module.exports = function pick(object, ...paths) {
const obj = {};
for (const path of paths){
if (object[path] !== undefined) {
obj[path] = object[path];
}
}
return obj;
};
}),
"[project]/node_modules/openid-client/lib/helpers/process_response.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const { STATUS_CODES } = __turbopack_context__.r("[externals]/http [external] (http, cjs)");
const { format } = __turbopack_context__.r("[externals]/util [external] (util, cjs)");
const { OPError } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/errors.js [app-route] (ecmascript)");
const parseWwwAuthenticate = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/www_authenticate_parser.js [app-route] (ecmascript)");
const throwAuthenticateErrors = (response)=>{
const params = parseWwwAuthenticate(response.headers['www-authenticate']);
if (params.error) {
throw new OPError(params, response);
}
};
const isStandardBodyError = (response)=>{
let result = false;
try {
let jsonbody;
if (typeof response.body !== 'object' || Buffer.isBuffer(response.body)) {
jsonbody = JSON.parse(response.body);
} else {
jsonbody = response.body;
}
result = typeof jsonbody.error === 'string' && jsonbody.error.length;
if (result) Object.defineProperty(response, 'body', {
value: jsonbody,
configurable: true
});
} catch (err) {}
return result;
};
function processResponse(response, { statusCode = 200, body = true, bearer = false } = {}) {
if (response.statusCode !== statusCode) {
if (bearer) {
throwAuthenticateErrors(response);
}
if (isStandardBodyError(response)) {
throw new OPError(response.body, response);
}
throw new OPError({
error: format('expected %i %s, got: %i %s', statusCode, STATUS_CODES[statusCode], response.statusCode, STATUS_CODES[response.statusCode])
}, response);
}
if (body && !response.body) {
throw new OPError({
error: format('expected %i %s with body but no body was returned', statusCode, STATUS_CODES[statusCode])
}, response);
}
return response.body;
}
module.exports = processResponse;
}),
"[project]/node_modules/openid-client/lib/helpers/unix_timestamp.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
module.exports = ()=>Math.floor(Date.now() / 1000);
}),
"[project]/node_modules/openid-client/lib/token_set.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const base64url = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/base64url.js [app-route] (ecmascript)");
const now = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/unix_timestamp.js [app-route] (ecmascript)");
class TokenSet {
constructor(values){
Object.assign(this, values);
const { constructor, ...properties } = Object.getOwnPropertyDescriptors(this.constructor.prototype);
Object.defineProperties(this, properties);
}
set expires_in(value) {
this.expires_at = now() + Number(value);
}
get expires_in() {
return Math.max.apply(null, [
this.expires_at - now(),
0
]);
}
expired() {
return this.expires_in === 0;
}
claims() {
if (!this.id_token) {
throw new TypeError('id_token not present in TokenSet');
}
return JSON.parse(base64url.decode(this.id_token.split('.')[1]));
}
}
module.exports = TokenSet;
}),
"[project]/node_modules/openid-client/lib/helpers/generators.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const { createHash, randomBytes } = __turbopack_context__.r("[externals]/crypto [external] (crypto, cjs)");
const base64url = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/base64url.js [app-route] (ecmascript)");
const random = (bytes = 32)=>base64url.encode(randomBytes(bytes));
module.exports = {
random,
state: random,
nonce: random,
codeVerifier: random,
codeChallenge: (codeVerifier)=>base64url.encode(createHash('sha256').update(codeVerifier).digest())
};
}),
"[project]/node_modules/openid-client/package.json.[json].cjs [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
module.exports = {
"name": "openid-client",
"version": "5.7.1",
"description": "OpenID Connect Relying Party (RP, Client) implementation for Node.js runtime, supports passportjs",
"keywords": [
"auth",
"authentication",
"basic",
"certified",
"client",
"connect",
"dynamic",
"electron",
"hybrid",
"identity",
"implicit",
"oauth",
"oauth2",
"oidc",
"openid",
"passport",
"relying party",
"strategy"
],
"homepage": "https://github.com/panva/openid-client",
"repository": "panva/openid-client",
"funding": {
"url": "https://github.com/sponsors/panva"
},
"license": "MIT",
"author": "Filip Skokan <panva.ip@gmail.com>",
"exports": {
"types": "./types/index.d.ts",
"import": "./lib/index.mjs",
"require": "./lib/index.js"
},
"main": "./lib/index.js",
"types": "./types/index.d.ts",
"files": [
"lib",
"types/index.d.ts"
],
"scripts": {
"format": "npx prettier --loglevel silent --write ./lib ./test ./certification ./types",
"test": "mocha test/**/*.test.js"
},
"dependencies": {
"jose": "^4.15.9",
"lru-cache": "^6.0.0",
"object-hash": "^2.2.0",
"oidc-token-hash": "^5.0.3"
},
"devDependencies": {
"@types/node": "^16.18.106",
"@types/passport": "^1.0.16",
"base64url": "^3.0.1",
"chai": "^4.5.0",
"mocha": "^10.7.3",
"nock": "^13.5.5",
"prettier": "^2.8.8",
"readable-mock-req": "^0.2.2",
"sinon": "^9.2.4",
"timekeeper": "^2.3.1"
},
"standard-version": {
"scripts": {
"postchangelog": "sed -i '' -e 's/### \\[/## [/g' CHANGELOG.md"
},
"types": [
{
"type": "feat",
"section": "Features"
},
{
"type": "fix",
"section": "Fixes"
},
{
"type": "chore",
"hidden": true
},
{
"type": "docs",
"hidden": true
},
{
"type": "style",
"hidden": true
},
{
"type": "refactor",
"section": "Refactor",
"hidden": false
},
{
"type": "perf",
"section": "Performance",
"hidden": false
},
{
"type": "test",
"hidden": true
}
]
}
};
}),
"[project]/node_modules/openid-client/lib/helpers/consts.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const HTTP_OPTIONS = Symbol();
const CLOCK_TOLERANCE = Symbol();
module.exports = {
CLOCK_TOLERANCE,
HTTP_OPTIONS
};
}),
"[project]/node_modules/openid-client/lib/helpers/request.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const assert = __turbopack_context__.r("[externals]/assert [external] (assert, cjs)");
const querystring = __turbopack_context__.r("[externals]/querystring [external] (querystring, cjs)");
const http = __turbopack_context__.r("[externals]/http [external] (http, cjs)");
const https = __turbopack_context__.r("[externals]/https [external] (https, cjs)");
const { once } = __turbopack_context__.r("[externals]/events [external] (events, cjs)");
const { URL } = __turbopack_context__.r("[externals]/url [external] (url, cjs)");
const LRU = __turbopack_context__.r("[project]/node_modules/openid-client/node_modules/lru-cache/index.js [app-route] (ecmascript)");
const pkg = __turbopack_context__.r("[project]/node_modules/openid-client/package.json.[json].cjs [app-route] (ecmascript)");
const { RPError } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/errors.js [app-route] (ecmascript)");
const pick = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/pick.js [app-route] (ecmascript)");
const { deep: defaultsDeep } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/defaults.js [app-route] (ecmascript)");
const { HTTP_OPTIONS } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/consts.js [app-route] (ecmascript)");
let DEFAULT_HTTP_OPTIONS;
const NQCHAR = /^[\x21\x23-\x5B\x5D-\x7E]+$/;
const allowed = [
'agent',
'ca',
'cert',
'crl',
'headers',
'key',
'lookup',
'passphrase',
'pfx',
'timeout'
];
const setDefaults = (props, options)=>{
DEFAULT_HTTP_OPTIONS = defaultsDeep({}, props.length ? pick(options, ...props) : options, DEFAULT_HTTP_OPTIONS);
};
setDefaults([], {
headers: {
'User-Agent': `${pkg.name}/${pkg.version} (${pkg.homepage})`,
'Accept-Encoding': 'identity'
},
timeout: 3500
});
function send(req, body, contentType) {
if (contentType) {
req.removeHeader('content-type');
req.setHeader('content-type', contentType);
}
if (body) {
req.removeHeader('content-length');
req.setHeader('content-length', Buffer.byteLength(body));
req.write(body);
}
req.end();
}
const nonces = new LRU({
max: 100
});
module.exports = async function request(options, { accessToken, mTLS = false, DPoP } = {}) {
let url;
try {
url = new URL(options.url);
delete options.url;
assert(/^(https?:)$/.test(url.protocol));
} catch (err) {
throw new TypeError('only valid absolute URLs can be requested');
}
const optsFn = this[HTTP_OPTIONS];
let opts = options;
const nonceKey = `${url.origin}${url.pathname}`;
if (DPoP && 'dpopProof' in this) {
opts.headers = opts.headers || {};
opts.headers.DPoP = await this.dpopProof({
htu: `${url.origin}${url.pathname}`,
htm: options.method || 'GET',
nonce: nonces.get(nonceKey)
}, DPoP, accessToken);
}
let userOptions;
if (optsFn) {
userOptions = pick(optsFn.call(this, url, defaultsDeep({}, opts, DEFAULT_HTTP_OPTIONS)), ...allowed);
}
opts = defaultsDeep({}, userOptions, opts, DEFAULT_HTTP_OPTIONS);
if (mTLS && !opts.pfx && !(opts.key && opts.cert)) {
throw new TypeError('mutual-TLS certificate and key not set');
}
if (opts.searchParams) {
for (const [key, value] of Object.entries(opts.searchParams)){
url.searchParams.delete(key);
url.searchParams.set(key, value);
}
}
let responseType;
let form;
let json;
let body;
({ form, responseType, json, body, ...opts } = opts);
for (const [key, value] of Object.entries(opts.headers || {})){
if (value === undefined) {
delete opts.headers[key];
}
}
let response;
const req = (url.protocol === 'https:' ? https.request : http.request)(url.href, opts);
return (async ()=>{
if (json) {
send(req, JSON.stringify(json), 'application/json');
} else if (form) {
send(req, querystring.stringify(form), 'application/x-www-form-urlencoded');
} else if (body) {
send(req, body);
} else {
send(req);
}
[response] = await Promise.race([
once(req, 'response'),
once(req, 'timeout')
]);
// timeout reached
if (!response) {
req.destroy();
throw new RPError(`outgoing request timed out after ${opts.timeout}ms`);
}
const parts = [];
for await (const part of response){
parts.push(part);
}
if (parts.length) {
switch(responseType){
case 'json':
{
Object.defineProperty(response, 'body', {
get () {
let value = Buffer.concat(parts);
try {
value = JSON.parse(value);
} catch (err) {
Object.defineProperty(err, 'response', {
value: response
});
throw err;
} finally{
Object.defineProperty(response, 'body', {
value,
configurable: true
});
}
return value;
},
configurable: true
});
break;
}
case undefined:
case 'buffer':
{
Object.defineProperty(response, 'body', {
get () {
const value = Buffer.concat(parts);
Object.defineProperty(response, 'body', {
value,
configurable: true
});
return value;
},
configurable: true
});
break;
}
default:
throw new TypeError('unsupported responseType request option');
}
}
return response;
})().catch((err)=>{
if (response) Object.defineProperty(err, 'response', {
value: response
});
throw err;
}).finally(()=>{
const dpopNonce = response && response.headers['dpop-nonce'];
if (dpopNonce && NQCHAR.test(dpopNonce)) {
nonces.set(nonceKey, dpopNonce);
}
});
};
module.exports.setDefaults = setDefaults.bind(undefined, allowed);
}),
"[project]/node_modules/openid-client/lib/helpers/weak_cache.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
module.exports.keystores = new WeakMap();
}),
"[project]/node_modules/openid-client/lib/helpers/deep_clone.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
module.exports = globalThis.structuredClone || ((obj)=>JSON.parse(JSON.stringify(obj)));
}),
"[project]/node_modules/openid-client/lib/helpers/keystore.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const jose = __turbopack_context__.r("[project]/node_modules/jose/dist/node/cjs/index.js [app-route] (ecmascript)");
const clone = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/deep_clone.js [app-route] (ecmascript)");
const isPlainObject = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/is_plain_object.js [app-route] (ecmascript)");
const internal = Symbol();
const keyscore = (key, { alg, use })=>{
let score = 0;
if (alg && key.alg) {
score++;
}
if (use && key.use) {
score++;
}
return score;
};
function getKtyFromAlg(alg) {
switch(typeof alg === 'string' && alg.slice(0, 2)){
case 'RS':
case 'PS':
return 'RSA';
case 'ES':
return 'EC';
case 'Ed':
return 'OKP';
default:
return undefined;
}
}
function getAlgorithms(use, alg, kty, crv) {
// Ed25519, Ed448, and secp256k1 always have "alg"
// OKP always has "use"
if (alg) {
return new Set([
alg
]);
}
switch(kty){
case 'EC':
{
let algs = [];
if (use === 'enc' || use === undefined) {
algs = algs.concat([
'ECDH-ES',
'ECDH-ES+A128KW',
'ECDH-ES+A192KW',
'ECDH-ES+A256KW'
]);
}
if (use === 'sig' || use === undefined) {
switch(crv){
case 'P-256':
case 'P-384':
algs = algs.concat([
`ES${crv.slice(-3)}`
]);
break;
case 'P-521':
algs = algs.concat([
'ES512'
]);
break;
case 'secp256k1':
if (jose.cryptoRuntime === 'node:crypto') {
algs = algs.concat([
'ES256K'
]);
}
break;
}
}
return new Set(algs);
}
case 'OKP':
{
return new Set([
'ECDH-ES',
'ECDH-ES+A128KW',
'ECDH-ES+A192KW',
'ECDH-ES+A256KW'
]);
}
case 'RSA':
{
let algs = [];
if (use === 'enc' || use === undefined) {
algs = algs.concat([
'RSA-OAEP',
'RSA-OAEP-256',
'RSA-OAEP-384',
'RSA-OAEP-512'
]);
if (jose.cryptoRuntime === 'node:crypto') {
algs = algs.concat([
'RSA1_5'
]);
}
}
if (use === 'sig' || use === undefined) {
algs = algs.concat([
'PS256',
'PS384',
'PS512',
'RS256',
'RS384',
'RS512'
]);
}
return new Set(algs);
}
default:
throw new Error('unreachable');
}
}
module.exports = class KeyStore {
#keys;
constructor(i, keys){
if (i !== internal) throw new Error('invalid constructor call');
this.#keys = keys;
}
toJWKS() {
return {
keys: this.map(({ jwk: { d, p, q, dp, dq, qi, ...jwk } })=>jwk)
};
}
all({ alg, kid, use } = {}) {
if (!use || !alg) {
throw new Error();
}
const kty = getKtyFromAlg(alg);
const search = {
alg,
use
};
return this.filter((key)=>{
let candidate = true;
if (candidate && kty !== undefined && key.jwk.kty !== kty) {
candidate = false;
}
if (candidate && kid !== undefined && key.jwk.kid !== kid) {
candidate = false;
}
if (candidate && use !== undefined && key.jwk.use !== undefined && key.jwk.use !== use) {
candidate = false;
}
if (candidate && key.jwk.alg && key.jwk.alg !== alg) {
candidate = false;
} else if (!key.algorithms.has(alg)) {
candidate = false;
}
return candidate;
}).sort((first, second)=>keyscore(second, search) - keyscore(first, search));
}
get(...args) {
return this.all(...args)[0];
}
static async fromJWKS(jwks, { onlyPublic = false, onlyPrivate = false } = {}) {
if (!isPlainObject(jwks) || !Array.isArray(jwks.keys) || jwks.keys.some((k)=>!isPlainObject(k) || !('kty' in k))) {
throw new TypeError('jwks must be a JSON Web Key Set formatted object');
}
const keys = [];
for (let jwk of jwks.keys){
jwk = clone(jwk);
const { kty, kid, crv } = jwk;
let { alg, use } = jwk;
if (typeof kty !== 'string' || !kty) {
continue;
}
if (use !== undefined && use !== 'sig' && use !== 'enc') {
continue;
}
if (typeof alg !== 'string' && alg !== undefined) {
continue;
}
if (typeof kid !== 'string' && kid !== undefined) {
continue;
}
if (kty === 'EC' && use === 'sig') {
switch(crv){
case 'P-256':
alg = 'ES256';
break;
case 'P-384':
alg = 'ES384';
break;
case 'P-521':
alg = 'ES512';
break;
default:
break;
}
}
if (crv === 'secp256k1') {
use = 'sig';
alg = 'ES256K';
}
if (kty === 'OKP') {
switch(crv){
case 'Ed25519':
case 'Ed448':
use = 'sig';
alg = 'EdDSA';
break;
case 'X25519':
case 'X448':
use = 'enc';
break;
default:
break;
}
}
if (alg && !use) {
switch(true){
case alg.startsWith('ECDH'):
use = 'enc';
break;
case alg.startsWith('RSA'):
use = 'enc';
break;
default:
break;
}
}
if (onlyPrivate && (jwk.kty === 'oct' || !jwk.d)) {
throw new Error('jwks must only contain private keys');
}
if (onlyPublic && (jwk.d || jwk.k)) {
continue;
}
keys.push({
jwk: {
...jwk,
alg,
use
},
async keyObject (alg) {
if (this[alg]) {
return this[alg];
}
const keyObject = await jose.importJWK(this.jwk, alg);
this[alg] = keyObject;
return keyObject;
},
get algorithms () {
Object.defineProperty(this, 'algorithms', {
value: getAlgorithms(this.jwk.use, this.jwk.alg, this.jwk.kty, this.jwk.crv),
enumerable: true,
configurable: false
});
return this.algorithms;
}
});
}
return new this(internal, keys);
}
filter(...args) {
return this.#keys.filter(...args);
}
find(...args) {
return this.#keys.find(...args);
}
every(...args) {
return this.#keys.every(...args);
}
some(...args) {
return this.#keys.some(...args);
}
map(...args) {
return this.#keys.map(...args);
}
forEach(...args) {
return this.#keys.forEach(...args);
}
reduce(...args) {
return this.#keys.reduce(...args);
}
sort(...args) {
return this.#keys.sort(...args);
}
*[Symbol.iterator]() {
for (const key of this.#keys){
yield key;
}
}
};
}),
"[project]/node_modules/openid-client/lib/helpers/merge.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const isPlainObject = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/is_plain_object.js [app-route] (ecmascript)");
function merge(target, ...sources) {
for (const source of sources){
if (!isPlainObject(source)) {
continue;
}
for (const [key, value] of Object.entries(source)){
/* istanbul ignore if */ if (key === '__proto__' || key === 'constructor') {
continue;
}
if (isPlainObject(target[key]) && isPlainObject(value)) {
target[key] = merge(target[key], value);
} else if (typeof value !== 'undefined') {
target[key] = value;
}
}
}
return target;
}
module.exports = merge;
}),
"[project]/node_modules/openid-client/lib/helpers/client.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const jose = __turbopack_context__.r("[project]/node_modules/jose/dist/node/cjs/index.js [app-route] (ecmascript)");
const { RPError } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/errors.js [app-route] (ecmascript)");
const { assertIssuerConfiguration } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/assert.js [app-route] (ecmascript)");
const { random } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/generators.js [app-route] (ecmascript)");
const now = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/unix_timestamp.js [app-route] (ecmascript)");
const request = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/request.js [app-route] (ecmascript)");
const { keystores } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/weak_cache.js [app-route] (ecmascript)");
const merge = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/merge.js [app-route] (ecmascript)");
// TODO: in v6.x additionally encode the `- _ . ! ~ * ' ( )` characters
// https://github.com/panva/node-openid-client/commit/5a2ea80ef5e59ec0c03dbd97d82f551e24a9d348
const formUrlEncode = (value)=>encodeURIComponent(value).replace(/%20/g, '+');
async function clientAssertion(endpoint, payload) {
let alg = this[`${endpoint}_endpoint_auth_signing_alg`];
if (!alg) {
assertIssuerConfiguration(this.issuer, `${endpoint}_endpoint_auth_signing_alg_values_supported`);
}
if (this[`${endpoint}_endpoint_auth_method`] === 'client_secret_jwt') {
if (!alg) {
const supported = this.issuer[`${endpoint}_endpoint_auth_signing_alg_values_supported`];
alg = Array.isArray(supported) && supported.find((signAlg)=>/^HS(?:256|384|512)/.test(signAlg));
}
if (!alg) {
throw new RPError(`failed to determine a JWS Algorithm to use for ${this[`${endpoint}_endpoint_auth_method`]} Client Assertion`);
}
return new jose.CompactSign(Buffer.from(JSON.stringify(payload))).setProtectedHeader({
alg
}).sign(this.secretForAlg(alg));
}
const keystore = await keystores.get(this);
if (!keystore) {
throw new TypeError('no client jwks provided for signing a client assertion with');
}
if (!alg) {
const supported = this.issuer[`${endpoint}_endpoint_auth_signing_alg_values_supported`];
alg = Array.isArray(supported) && supported.find((signAlg)=>keystore.get({
alg: signAlg,
use: 'sig'
}));
}
if (!alg) {
throw new RPError(`failed to determine a JWS Algorithm to use for ${this[`${endpoint}_endpoint_auth_method`]} Client Assertion`);
}
const key = keystore.get({
alg,
use: 'sig'
});
if (!key) {
throw new RPError(`no key found in client jwks to sign a client assertion with using alg ${alg}`);
}
return new jose.CompactSign(Buffer.from(JSON.stringify(payload))).setProtectedHeader({
alg,
kid: key.jwk && key.jwk.kid
}).sign(await key.keyObject(alg));
}
async function authFor(endpoint, { clientAssertionPayload } = {}) {
const authMethod = this[`${endpoint}_endpoint_auth_method`];
switch(authMethod){
case 'self_signed_tls_client_auth':
case 'tls_client_auth':
case 'none':
return {
form: {
client_id: this.client_id
}
};
case 'client_secret_post':
if (typeof this.client_secret !== 'string') {
throw new TypeError('client_secret_post client authentication method requires a client_secret');
}
return {
form: {
client_id: this.client_id,
client_secret: this.client_secret
}
};
case 'private_key_jwt':
case 'client_secret_jwt':
{
const timestamp = now();
const assertion = await clientAssertion.call(this, endpoint, {
iat: timestamp,
exp: timestamp + 60,
jti: random(),
iss: this.client_id,
sub: this.client_id,
aud: this.issuer.issuer,
...clientAssertionPayload
});
return {
form: {
client_id: this.client_id,
client_assertion: assertion,
client_assertion_type: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer'
}
};
}
case 'client_secret_basic':
{
// This is correct behaviour, see https://tools.ietf.org/html/rfc6749#section-2.3.1 and the
// related appendix. (also https://github.com/panva/node-openid-client/pull/91)
// > The client identifier is encoded using the
// > "application/x-www-form-urlencoded" encoding algorithm per
// > Appendix B, and the encoded value is used as the username; the client
// > password is encoded using the same algorithm and used as the
// > password.
if (typeof this.client_secret !== 'string') {
throw new TypeError('client_secret_basic client authentication method requires a client_secret');
}
const encoded = `${formUrlEncode(this.client_id)}:${formUrlEncode(this.client_secret)}`;
const value = Buffer.from(encoded).toString('base64');
return {
headers: {
Authorization: `Basic ${value}`
}
};
}
default:
{
throw new TypeError(`missing, or unsupported, ${endpoint}_endpoint_auth_method`);
}
}
}
function resolveResponseType() {
const { length, 0: value } = this.response_types;
if (length === 1) {
return value;
}
return undefined;
}
function resolveRedirectUri() {
const { length, 0: value } = this.redirect_uris || [];
if (length === 1) {
return value;
}
return undefined;
}
async function authenticatedPost(endpoint, opts, { clientAssertionPayload, endpointAuthMethod = endpoint, DPoP } = {}) {
const auth = await authFor.call(this, endpointAuthMethod, {
clientAssertionPayload
});
const requestOpts = merge(opts, auth);
const mTLS = this[`${endpointAuthMethod}_endpoint_auth_method`].includes('tls_client_auth') || endpoint === 'token' && this.tls_client_certificate_bound_access_tokens;
let targetUrl;
if (mTLS && this.issuer.mtls_endpoint_aliases) {
targetUrl = this.issuer.mtls_endpoint_aliases[`${endpoint}_endpoint`];
}
targetUrl = targetUrl || this.issuer[`${endpoint}_endpoint`];
if ('form' in requestOpts) {
for (const [key, value] of Object.entries(requestOpts.form)){
if (typeof value === 'undefined') {
delete requestOpts.form[key];
}
}
}
return request.call(this, {
...requestOpts,
method: 'POST',
url: targetUrl,
headers: {
...endpoint !== 'revocation' ? {
Accept: 'application/json'
} : undefined,
...requestOpts.headers
}
}, {
mTLS,
DPoP
});
}
module.exports = {
resolveResponseType,
resolveRedirectUri,
authFor,
authenticatedPost
};
}),
"[project]/node_modules/openid-client/lib/helpers/issuer.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const objectHash = __turbopack_context__.r("[project]/node_modules/object-hash/index.js [app-route] (ecmascript)");
const LRU = __turbopack_context__.r("[project]/node_modules/openid-client/node_modules/lru-cache/index.js [app-route] (ecmascript)");
const { RPError } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/errors.js [app-route] (ecmascript)");
const { assertIssuerConfiguration } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/assert.js [app-route] (ecmascript)");
const KeyStore = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/keystore.js [app-route] (ecmascript)");
const { keystores } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/weak_cache.js [app-route] (ecmascript)");
const processResponse = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/process_response.js [app-route] (ecmascript)");
const request = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/request.js [app-route] (ecmascript)");
const inFlight = new WeakMap();
const caches = new WeakMap();
const lrus = (ctx)=>{
if (!caches.has(ctx)) {
caches.set(ctx, new LRU({
max: 100
}));
}
return caches.get(ctx);
};
async function getKeyStore(reload = false) {
assertIssuerConfiguration(this, 'jwks_uri');
const keystore = keystores.get(this);
const cache = lrus(this);
if (reload || !keystore) {
if (inFlight.has(this)) {
return inFlight.get(this);
}
cache.reset();
inFlight.set(this, (async ()=>{
const response = await request.call(this, {
method: 'GET',
responseType: 'json',
url: this.jwks_uri,
headers: {
Accept: 'application/json, application/jwk-set+json'
}
}).finally(()=>{
inFlight.delete(this);
});
const jwks = processResponse(response);
const joseKeyStore = KeyStore.fromJWKS(jwks, {
onlyPublic: true
});
cache.set('throttle', true, 60 * 1000);
keystores.set(this, joseKeyStore);
return joseKeyStore;
})());
return inFlight.get(this);
}
return keystore;
}
async function queryKeyStore({ kid, kty, alg, use }, { allowMulti = false } = {}) {
const cache = lrus(this);
const def = {
kid,
kty,
alg,
use
};
const defHash = objectHash(def, {
algorithm: 'sha256',
ignoreUnknown: true,
unorderedArrays: true,
unorderedSets: true,
respectType: false
});
// refresh keystore on every unknown key but also only upto once every minute
const freshJwksUri = cache.get(defHash) || cache.get('throttle');
const keystore = await getKeyStore.call(this, !freshJwksUri);
const keys = keystore.all(def);
delete def.use;
if (keys.length === 0) {
throw new RPError({
printf: [
"no valid key found in issuer's jwks_uri for key parameters %j",
def
],
jwks: keystore
});
}
if (!allowMulti && keys.length > 1 && !kid) {
throw new RPError({
printf: [
"multiple matching keys found in issuer's jwks_uri for key parameters %j, kid must be provided in this case",
def
],
jwks: keystore
});
}
cache.set(defHash, true);
return keys;
}
module.exports.queryKeyStore = queryKeyStore;
module.exports.keystore = getKeyStore;
}),
"[project]/node_modules/openid-client/lib/device_flow_handle.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const { inspect } = __turbopack_context__.r("[externals]/util [external] (util, cjs)");
const { RPError, OPError } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/errors.js [app-route] (ecmascript)");
const now = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/unix_timestamp.js [app-route] (ecmascript)");
class DeviceFlowHandle {
#aborted;
#client;
#clientAssertionPayload;
#DPoP;
#exchangeBody;
#expires_at;
#interval;
#maxAge;
#response;
constructor({ client, exchangeBody, clientAssertionPayload, response, maxAge, DPoP }){
[
'verification_uri',
'user_code',
'device_code'
].forEach((prop)=>{
if (typeof response[prop] !== 'string' || !response[prop]) {
throw new RPError(`expected ${prop} string to be returned by Device Authorization Response, got %j`, response[prop]);
}
});
if (!Number.isSafeInteger(response.expires_in)) {
throw new RPError('expected expires_in number to be returned by Device Authorization Response, got %j', response.expires_in);
}
this.#expires_at = now() + response.expires_in;
this.#client = client;
this.#DPoP = DPoP;
this.#maxAge = maxAge;
this.#exchangeBody = exchangeBody;
this.#clientAssertionPayload = clientAssertionPayload;
this.#response = response;
this.#interval = response.interval * 1000 || 5000;
}
abort() {
this.#aborted = true;
}
async poll({ signal } = {}) {
if (signal && signal.aborted || this.#aborted) {
throw new RPError('polling aborted');
}
if (this.expired()) {
throw new RPError('the device code %j has expired and the device authorization session has concluded', this.device_code);
}
await new Promise((resolve)=>setTimeout(resolve, this.#interval));
let tokenset;
try {
tokenset = await this.#client.grant({
...this.#exchangeBody,
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
device_code: this.device_code
}, {
clientAssertionPayload: this.#clientAssertionPayload,
DPoP: this.#DPoP
});
} catch (err) {
switch(err instanceof OPError && err.error){
case 'slow_down':
this.#interval += 5000;
case 'authorization_pending':
return this.poll({
signal
});
default:
throw err;
}
}
if ('id_token' in tokenset) {
await this.#client.decryptIdToken(tokenset);
await this.#client.validateIdToken(tokenset, undefined, 'token', this.#maxAge);
}
return tokenset;
}
get device_code() {
return this.#response.device_code;
}
get user_code() {
return this.#response.user_code;
}
get verification_uri() {
return this.#response.verification_uri;
}
get verification_uri_complete() {
return this.#response.verification_uri_complete;
}
get expires_in() {
return Math.max.apply(null, [
this.#expires_at - now(),
0
]);
}
expired() {
return this.expires_in === 0;
}
/* istanbul ignore next */ [inspect.custom]() {
return `${this.constructor.name} ${inspect(this.#response, {
depth: Infinity,
colors: process.stdout.isTTY,
compact: false,
sorted: true
})}`;
}
}
module.exports = DeviceFlowHandle;
}),
"[project]/node_modules/openid-client/lib/client.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const { inspect } = __turbopack_context__.r("[externals]/util [external] (util, cjs)");
const stdhttp = __turbopack_context__.r("[externals]/http [external] (http, cjs)");
const crypto = __turbopack_context__.r("[externals]/crypto [external] (crypto, cjs)");
const { strict: assert } = __turbopack_context__.r("[externals]/assert [external] (assert, cjs)");
const querystring = __turbopack_context__.r("[externals]/querystring [external] (querystring, cjs)");
const url = __turbopack_context__.r("[externals]/url [external] (url, cjs)");
const { URL, URLSearchParams } = __turbopack_context__.r("[externals]/url [external] (url, cjs)");
const jose = __turbopack_context__.r("[project]/node_modules/jose/dist/node/cjs/index.js [app-route] (ecmascript)");
const tokenHash = __turbopack_context__.r("[project]/node_modules/oidc-token-hash/lib/index.js [app-route] (ecmascript)");
const isKeyObject = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/is_key_object.js [app-route] (ecmascript)");
const decodeJWT = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/decode_jwt.js [app-route] (ecmascript)");
const base64url = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/base64url.js [app-route] (ecmascript)");
const defaults = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/defaults.js [app-route] (ecmascript)");
const parseWwwAuthenticate = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/www_authenticate_parser.js [app-route] (ecmascript)");
const { assertSigningAlgValuesSupport, assertIssuerConfiguration } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/assert.js [app-route] (ecmascript)");
const pick = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/pick.js [app-route] (ecmascript)");
const isPlainObject = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/is_plain_object.js [app-route] (ecmascript)");
const processResponse = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/process_response.js [app-route] (ecmascript)");
const TokenSet = __turbopack_context__.r("[project]/node_modules/openid-client/lib/token_set.js [app-route] (ecmascript)");
const { OPError, RPError } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/errors.js [app-route] (ecmascript)");
const now = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/unix_timestamp.js [app-route] (ecmascript)");
const { random } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/generators.js [app-route] (ecmascript)");
const request = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/request.js [app-route] (ecmascript)");
const { CLOCK_TOLERANCE } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/consts.js [app-route] (ecmascript)");
const { keystores } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/weak_cache.js [app-route] (ecmascript)");
const KeyStore = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/keystore.js [app-route] (ecmascript)");
const clone = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/deep_clone.js [app-route] (ecmascript)");
const { authenticatedPost, resolveResponseType, resolveRedirectUri } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/client.js [app-route] (ecmascript)");
const { queryKeyStore } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/issuer.js [app-route] (ecmascript)");
const DeviceFlowHandle = __turbopack_context__.r("[project]/node_modules/openid-client/lib/device_flow_handle.js [app-route] (ecmascript)");
const [major, minor] = process.version.slice(1).split('.').map((str)=>parseInt(str, 10));
const rsaPssParams = major >= 17 || major === 16 && minor >= 9;
const retryAttempt = Symbol();
const skipNonceCheck = Symbol();
const skipMaxAgeCheck = Symbol();
function pickCb(input) {
return pick(input, 'access_token', 'code', 'error_description', 'error_uri', 'error', 'expires_in', 'id_token', 'iss', 'response', 'session_state', 'state', 'token_type');
}
function authorizationHeaderValue(token, tokenType = 'Bearer') {
return `${tokenType} ${token}`;
}
function getSearchParams(input) {
const parsed = url.parse(input);
if (!parsed.search) return {};
return querystring.parse(parsed.search.substring(1));
}
function verifyPresence(payload, jwt, prop) {
if (payload[prop] === undefined) {
throw new RPError({
message: `missing required JWT property ${prop}`,
jwt
});
}
}
function authorizationParams(params) {
const authParams = {
client_id: this.client_id,
scope: 'openid',
response_type: resolveResponseType.call(this),
redirect_uri: resolveRedirectUri.call(this),
...params
};
Object.entries(authParams).forEach(([key, value])=>{
if (value === null || value === undefined) {
delete authParams[key];
} else if (key === 'claims' && typeof value === 'object') {
authParams[key] = JSON.stringify(value);
} else if (key === 'resource' && Array.isArray(value)) {
authParams[key] = value;
} else if (typeof value !== 'string') {
authParams[key] = String(value);
}
});
return authParams;
}
function getKeystore(jwks) {
if (!isPlainObject(jwks) || !Array.isArray(jwks.keys) || jwks.keys.some((k)=>!isPlainObject(k) || !('kty' in k))) {
throw new TypeError('jwks must be a JSON Web Key Set formatted object');
}
return KeyStore.fromJWKS(jwks, {
onlyPrivate: true
});
}
// if an OP doesnt support client_secret_basic but supports client_secret_post, use it instead
// this is in place to take care of most common pitfalls when first using discovered Issuers without
// the support for default values defined by Discovery 1.0
function checkBasicSupport(client, properties) {
try {
const supported = client.issuer.token_endpoint_auth_methods_supported;
if (!supported.includes(properties.token_endpoint_auth_method)) {
if (supported.includes('client_secret_post')) {
properties.token_endpoint_auth_method = 'client_secret_post';
}
}
} catch (err) {}
}
function handleCommonMistakes(client, metadata, properties) {
if (!metadata.token_endpoint_auth_method) {
// if no explicit value was provided
checkBasicSupport(client, properties);
}
// :fp: c'mon people... RTFM
if (metadata.redirect_uri) {
if (metadata.redirect_uris) {
throw new TypeError('provide a redirect_uri or redirect_uris, not both');
}
properties.redirect_uris = [
metadata.redirect_uri
];
delete properties.redirect_uri;
}
if (metadata.response_type) {
if (metadata.response_types) {
throw new TypeError('provide a response_type or response_types, not both');
}
properties.response_types = [
metadata.response_type
];
delete properties.response_type;
}
}
function getDefaultsForEndpoint(endpoint, issuer, properties) {
if (!issuer[`${endpoint}_endpoint`]) return;
const tokenEndpointAuthMethod = properties.token_endpoint_auth_method;
const tokenEndpointAuthSigningAlg = properties.token_endpoint_auth_signing_alg;
const eam = `${endpoint}_endpoint_auth_method`;
const easa = `${endpoint}_endpoint_auth_signing_alg`;
if (properties[eam] === undefined && properties[easa] === undefined) {
if (tokenEndpointAuthMethod !== undefined) {
properties[eam] = tokenEndpointAuthMethod;
}
if (tokenEndpointAuthSigningAlg !== undefined) {
properties[easa] = tokenEndpointAuthSigningAlg;
}
}
}
class BaseClient {
#metadata;
#issuer;
#aadIssValidation;
#additionalAuthorizedParties;
constructor(issuer, aadIssValidation, metadata = {}, jwks, options){
this.#metadata = new Map();
this.#issuer = issuer;
this.#aadIssValidation = aadIssValidation;
if (typeof metadata.client_id !== 'string' || !metadata.client_id) {
throw new TypeError('client_id is required');
}
const properties = {
grant_types: [
'authorization_code'
],
id_token_signed_response_alg: 'RS256',
authorization_signed_response_alg: 'RS256',
response_types: [
'code'
],
token_endpoint_auth_method: 'client_secret_basic',
...this.fapi1() ? {
grant_types: [
'authorization_code',
'implicit'
],
id_token_signed_response_alg: 'PS256',
authorization_signed_response_alg: 'PS256',
response_types: [
'code id_token'
],
tls_client_certificate_bound_access_tokens: true,
token_endpoint_auth_method: undefined
} : undefined,
...this.fapi2() ? {
id_token_signed_response_alg: 'PS256',
authorization_signed_response_alg: 'PS256',
token_endpoint_auth_method: undefined
} : undefined,
...metadata
};
if (this.fapi()) {
switch(properties.token_endpoint_auth_method){
case 'self_signed_tls_client_auth':
case 'tls_client_auth':
break;
case 'private_key_jwt':
if (!jwks) {
throw new TypeError('jwks is required');
}
break;
case undefined:
throw new TypeError('token_endpoint_auth_method is required');
default:
throw new TypeError('invalid or unsupported token_endpoint_auth_method');
}
}
if (this.fapi2()) {
if (properties.tls_client_certificate_bound_access_tokens && properties.dpop_bound_access_tokens) {
throw new TypeError('either tls_client_certificate_bound_access_tokens or dpop_bound_access_tokens must be set to true');
}
if (!properties.tls_client_certificate_bound_access_tokens && !properties.dpop_bound_access_tokens) {
throw new TypeError('either tls_client_certificate_bound_access_tokens or dpop_bound_access_tokens must be set to true');
}
}
handleCommonMistakes(this, metadata, properties);
assertSigningAlgValuesSupport('token', this.issuer, properties);
[
'introspection',
'revocation'
].forEach((endpoint)=>{
getDefaultsForEndpoint(endpoint, this.issuer, properties);
assertSigningAlgValuesSupport(endpoint, this.issuer, properties);
});
Object.entries(properties).forEach(([key, value])=>{
this.#metadata.set(key, value);
if (!this[key]) {
Object.defineProperty(this, key, {
get () {
return this.#metadata.get(key);
},
enumerable: true
});
}
});
if (jwks !== undefined) {
const keystore = getKeystore.call(this, jwks);
keystores.set(this, keystore);
}
if (options != null && options.additionalAuthorizedParties) {
this.#additionalAuthorizedParties = clone(options.additionalAuthorizedParties);
}
this[CLOCK_TOLERANCE] = 0;
}
authorizationUrl(params = {}) {
if (!isPlainObject(params)) {
throw new TypeError('params must be a plain object');
}
assertIssuerConfiguration(this.issuer, 'authorization_endpoint');
const target = new URL(this.issuer.authorization_endpoint);
for (const [name, value] of Object.entries(authorizationParams.call(this, params))){
if (Array.isArray(value)) {
target.searchParams.delete(name);
for (const member of value){
target.searchParams.append(name, member);
}
} else {
target.searchParams.set(name, value);
}
}
// TODO: is the replace needed?
return target.href.replace(/\+/g, '%20');
}
authorizationPost(params = {}) {
if (!isPlainObject(params)) {
throw new TypeError('params must be a plain object');
}
const inputs = authorizationParams.call(this, params);
const formInputs = Object.keys(inputs).map((name)=>`<input type="hidden" name="${name}" value="${inputs[name]}"/>`).join('\n');
return `<!DOCTYPE html>
<head>
<title>Requesting Authorization</title>
</head>
<body onload="javascript:document.forms[0].submit()">
<form method="post" action="${this.issuer.authorization_endpoint}">
${formInputs}
</form>
</body>
</html>`;
}
endSessionUrl(params = {}) {
assertIssuerConfiguration(this.issuer, 'end_session_endpoint');
const { 0: postLogout, length } = this.post_logout_redirect_uris || [];
const { post_logout_redirect_uri = length === 1 ? postLogout : undefined } = params;
let id_token_hint;
({ id_token_hint, ...params } = params);
if (id_token_hint instanceof TokenSet) {
if (!id_token_hint.id_token) {
throw new TypeError('id_token not present in TokenSet');
}
id_token_hint = id_token_hint.id_token;
}
const target = url.parse(this.issuer.end_session_endpoint);
const query = defaults(getSearchParams(this.issuer.end_session_endpoint), params, {
post_logout_redirect_uri,
client_id: this.client_id
}, {
id_token_hint
});
Object.entries(query).forEach(([key, value])=>{
if (value === null || value === undefined) {
delete query[key];
}
});
target.search = null;
target.query = query;
return url.format(target);
}
callbackParams(input) {
const isIncomingMessage = input instanceof stdhttp.IncomingMessage || input && input.method && input.url;
const isString = typeof input === 'string';
if (!isString && !isIncomingMessage) {
throw new TypeError('#callbackParams only accepts string urls, http.IncomingMessage or a lookalike');
}
if (isIncomingMessage) {
switch(input.method){
case 'GET':
return pickCb(getSearchParams(input.url));
case 'POST':
if (input.body === undefined) {
throw new TypeError('incoming message body missing, include a body parser prior to this method call');
}
switch(typeof input.body){
case 'object':
case 'string':
if (Buffer.isBuffer(input.body)) {
return pickCb(querystring.parse(input.body.toString('utf-8')));
}
if (typeof input.body === 'string') {
return pickCb(querystring.parse(input.body));
}
return pickCb(input.body);
default:
throw new TypeError('invalid IncomingMessage body object');
}
default:
throw new TypeError('invalid IncomingMessage method');
}
} else {
return pickCb(getSearchParams(input));
}
}
async callback(redirectUri, parameters, checks = {}, { exchangeBody, clientAssertionPayload, DPoP } = {}) {
let params = pickCb(parameters);
if (checks.jarm && !('response' in parameters)) {
throw new RPError({
message: 'expected a JARM response',
checks,
params
});
} else if ('response' in parameters) {
const decrypted = await this.decryptJARM(params.response);
params = await this.validateJARM(decrypted);
}
if (this.default_max_age && !checks.max_age) {
checks.max_age = this.default_max_age;
}
if (params.state && !checks.state) {
throw new TypeError('checks.state argument is missing');
}
if (!params.state && checks.state) {
throw new RPError({
message: 'state missing from the response',
checks,
params
});
}
if (checks.state !== params.state) {
throw new RPError({
printf: [
'state mismatch, expected %s, got: %s',
checks.state,
params.state
],
checks,
params
});
}
if ('iss' in params) {
assertIssuerConfiguration(this.issuer, 'issuer');
if (params.iss !== this.issuer.issuer) {
throw new RPError({
printf: [
'iss mismatch, expected %s, got: %s',
this.issuer.issuer,
params.iss
],
params
});
}
} else if (this.issuer.authorization_response_iss_parameter_supported && !('id_token' in params) && !('response' in parameters)) {
throw new RPError({
message: 'iss missing from the response',
params
});
}
if (params.error) {
throw new OPError(params);
}
const RESPONSE_TYPE_REQUIRED_PARAMS = {
code: [
'code'
],
id_token: [
'id_token'
],
token: [
'access_token',
'token_type'
]
};
if (checks.response_type) {
for (const type of checks.response_type.split(' ')){
if (type === 'none') {
if (params.code || params.id_token || params.access_token) {
throw new RPError({
message: 'unexpected params encountered for "none" response',
checks,
params
});
}
} else {
for (const param of RESPONSE_TYPE_REQUIRED_PARAMS[type]){
if (!params[param]) {
throw new RPError({
message: `${param} missing from response`,
checks,
params
});
}
}
}
}
}
if (params.id_token) {
const tokenset = new TokenSet(params);
await this.decryptIdToken(tokenset);
await this.validateIdToken(tokenset, checks.nonce, 'authorization', checks.max_age, checks.state);
if (!params.code) {
return tokenset;
}
}
if (params.code) {
const tokenset = await this.grant({
...exchangeBody,
grant_type: 'authorization_code',
code: params.code,
redirect_uri: redirectUri,
code_verifier: checks.code_verifier
}, {
clientAssertionPayload,
DPoP
});
await this.decryptIdToken(tokenset);
await this.validateIdToken(tokenset, checks.nonce, 'token', checks.max_age);
if (params.session_state) {
tokenset.session_state = params.session_state;
}
return tokenset;
}
return new TokenSet(params);
}
async oauthCallback(redirectUri, parameters, checks = {}, { exchangeBody, clientAssertionPayload, DPoP } = {}) {
let params = pickCb(parameters);
if (checks.jarm && !('response' in parameters)) {
throw new RPError({
message: 'expected a JARM response',
checks,
params
});
} else if ('response' in parameters) {
const decrypted = await this.decryptJARM(params.response);
params = await this.validateJARM(decrypted);
}
if (params.state && !checks.state) {
throw new TypeError('checks.state argument is missing');
}
if (!params.state && checks.state) {
throw new RPError({
message: 'state missing from the response',
checks,
params
});
}
if (checks.state !== params.state) {
throw new RPError({
printf: [
'state mismatch, expected %s, got: %s',
checks.state,
params.state
],
checks,
params
});
}
if ('iss' in params) {
assertIssuerConfiguration(this.issuer, 'issuer');
if (params.iss !== this.issuer.issuer) {
throw new RPError({
printf: [
'iss mismatch, expected %s, got: %s',
this.issuer.issuer,
params.iss
],
params
});
}
} else if (this.issuer.authorization_response_iss_parameter_supported && !('id_token' in params) && !('response' in parameters)) {
throw new RPError({
message: 'iss missing from the response',
params
});
}
if (params.error) {
throw new OPError(params);
}
if (typeof params.id_token === 'string' && params.id_token.length) {
throw new RPError({
message: 'id_token detected in the response, you must use client.callback() instead of client.oauthCallback()',
params
});
}
delete params.id_token;
const RESPONSE_TYPE_REQUIRED_PARAMS = {
code: [
'code'
],
token: [
'access_token',
'token_type'
]
};
if (checks.response_type) {
for (const type of checks.response_type.split(' ')){
if (type === 'none') {
if (params.code || params.id_token || params.access_token) {
throw new RPError({
message: 'unexpected params encountered for "none" response',
checks,
params
});
}
}
if (RESPONSE_TYPE_REQUIRED_PARAMS[type]) {
for (const param of RESPONSE_TYPE_REQUIRED_PARAMS[type]){
if (!params[param]) {
throw new RPError({
message: `${param} missing from response`,
checks,
params
});
}
}
}
}
}
if (params.code) {
const tokenset = await this.grant({
...exchangeBody,
grant_type: 'authorization_code',
code: params.code,
redirect_uri: redirectUri,
code_verifier: checks.code_verifier
}, {
clientAssertionPayload,
DPoP
});
if (typeof tokenset.id_token === 'string' && tokenset.id_token.length) {
throw new RPError({
message: 'id_token detected in the response, you must use client.callback() instead of client.oauthCallback()',
params
});
}
delete tokenset.id_token;
return tokenset;
}
return new TokenSet(params);
}
async decryptIdToken(token) {
if (!this.id_token_encrypted_response_alg) {
return token;
}
let idToken = token;
if (idToken instanceof TokenSet) {
if (!idToken.id_token) {
throw new TypeError('id_token not present in TokenSet');
}
idToken = idToken.id_token;
}
const expectedAlg = this.id_token_encrypted_response_alg;
const expectedEnc = this.id_token_encrypted_response_enc;
const result = await this.decryptJWE(idToken, expectedAlg, expectedEnc);
if (token instanceof TokenSet) {
token.id_token = result;
return token;
}
return result;
}
async validateJWTUserinfo(body) {
const expectedAlg = this.userinfo_signed_response_alg;
return this.validateJWT(body, expectedAlg, []);
}
async decryptJARM(response) {
if (!this.authorization_encrypted_response_alg) {
return response;
}
const expectedAlg = this.authorization_encrypted_response_alg;
const expectedEnc = this.authorization_encrypted_response_enc;
return this.decryptJWE(response, expectedAlg, expectedEnc);
}
async decryptJWTUserinfo(body) {
if (!this.userinfo_encrypted_response_alg) {
return body;
}
const expectedAlg = this.userinfo_encrypted_response_alg;
const expectedEnc = this.userinfo_encrypted_response_enc;
return this.decryptJWE(body, expectedAlg, expectedEnc);
}
async decryptJWE(jwe, expectedAlg, expectedEnc = 'A128CBC-HS256') {
const header = JSON.parse(base64url.decode(jwe.split('.')[0]));
if (header.alg !== expectedAlg) {
throw new RPError({
printf: [
'unexpected JWE alg received, expected %s, got: %s',
expectedAlg,
header.alg
],
jwt: jwe
});
}
if (header.enc !== expectedEnc) {
throw new RPError({
printf: [
'unexpected JWE enc received, expected %s, got: %s',
expectedEnc,
header.enc
],
jwt: jwe
});
}
const getPlaintext = (result)=>new TextDecoder().decode(result.plaintext);
let plaintext;
if (expectedAlg.match(/^(?:RSA|ECDH)/)) {
const keystore = await keystores.get(this);
const protectedHeader = jose.decodeProtectedHeader(jwe);
for (const key of keystore.all({
...protectedHeader,
use: 'enc'
})){
plaintext = await jose.compactDecrypt(jwe, await key.keyObject(protectedHeader.alg)).then(getPlaintext, ()=>{});
if (plaintext) break;
}
} else {
plaintext = await jose.compactDecrypt(jwe, this.secretForAlg(expectedAlg === 'dir' ? expectedEnc : expectedAlg)).then(getPlaintext, ()=>{});
}
if (!plaintext) {
throw new RPError({
message: 'failed to decrypt JWE',
jwt: jwe
});
}
return plaintext;
}
async validateIdToken(tokenSet, nonce, returnedBy, maxAge, state) {
let idToken = tokenSet;
const expectedAlg = this.id_token_signed_response_alg;
const isTokenSet = idToken instanceof TokenSet;
if (isTokenSet) {
if (!idToken.id_token) {
throw new TypeError('id_token not present in TokenSet');
}
idToken = idToken.id_token;
}
idToken = String(idToken);
const timestamp = now();
const { protected: header, payload, key } = await this.validateJWT(idToken, expectedAlg);
if (typeof maxAge === 'number' || maxAge !== skipMaxAgeCheck && this.require_auth_time) {
if (!payload.auth_time) {
throw new RPError({
message: 'missing required JWT property auth_time',
jwt: idToken
});
}
if (typeof payload.auth_time !== 'number') {
throw new RPError({
message: 'JWT auth_time claim must be a JSON numeric value',
jwt: idToken
});
}
}
if (typeof maxAge === 'number' && payload.auth_time + maxAge < timestamp - this[CLOCK_TOLERANCE]) {
throw new RPError({
printf: [
'too much time has elapsed since the last End-User authentication, max_age %i, auth_time: %i, now %i',
maxAge,
payload.auth_time,
timestamp - this[CLOCK_TOLERANCE]
],
now: timestamp,
tolerance: this[CLOCK_TOLERANCE],
auth_time: payload.auth_time,
jwt: idToken
});
}
if (nonce !== skipNonceCheck && (payload.nonce || nonce !== undefined) && payload.nonce !== nonce) {
throw new RPError({
printf: [
'nonce mismatch, expected %s, got: %s',
nonce,
payload.nonce
],
jwt: idToken
});
}
if (returnedBy === 'authorization') {
if (!payload.at_hash && tokenSet.access_token) {
throw new RPError({
message: 'missing required property at_hash',
jwt: idToken
});
}
if (!payload.c_hash && tokenSet.code) {
throw new RPError({
message: 'missing required property c_hash',
jwt: idToken
});
}
if (this.fapi1()) {
if (!payload.s_hash && (tokenSet.state || state)) {
throw new RPError({
message: 'missing required property s_hash',
jwt: idToken
});
}
}
if (payload.s_hash) {
if (!state) {
throw new TypeError('cannot verify s_hash, "checks.state" property not provided');
}
try {
tokenHash.validate({
claim: 's_hash',
source: 'state'
}, payload.s_hash, state, header.alg, key.jwk && key.jwk.crv);
} catch (err) {
throw new RPError({
message: err.message,
jwt: idToken
});
}
}
}
if (this.fapi() && payload.iat < timestamp - 3600) {
throw new RPError({
printf: [
'JWT issued too far in the past, now %i, iat %i',
timestamp,
payload.iat
],
now: timestamp,
tolerance: this[CLOCK_TOLERANCE],
iat: payload.iat,
jwt: idToken
});
}
if (tokenSet.access_token && payload.at_hash !== undefined) {
try {
tokenHash.validate({
claim: 'at_hash',
source: 'access_token'
}, payload.at_hash, tokenSet.access_token, header.alg, key.jwk && key.jwk.crv);
} catch (err) {
throw new RPError({
message: err.message,
jwt: idToken
});
}
}
if (tokenSet.code && payload.c_hash !== undefined) {
try {
tokenHash.validate({
claim: 'c_hash',
source: 'code'
}, payload.c_hash, tokenSet.code, header.alg, key.jwk && key.jwk.crv);
} catch (err) {
throw new RPError({
message: err.message,
jwt: idToken
});
}
}
return tokenSet;
}
async validateJWT(jwt, expectedAlg, required = [
'iss',
'sub',
'aud',
'exp',
'iat'
]) {
const isSelfIssued = this.issuer.issuer === 'https://self-issued.me';
const timestamp = now();
let header;
let payload;
try {
({ header, payload } = decodeJWT(jwt, {
complete: true
}));
} catch (err) {
throw new RPError({
printf: [
'failed to decode JWT (%s: %s)',
err.name,
err.message
],
jwt
});
}
if (header.alg !== expectedAlg) {
throw new RPError({
printf: [
'unexpected JWT alg received, expected %s, got: %s',
expectedAlg,
header.alg
],
jwt
});
}
if (isSelfIssued) {
required = [
...required,
'sub_jwk'
];
}
required.forEach(verifyPresence.bind(undefined, payload, jwt));
if (payload.iss !== undefined) {
let expectedIss = this.issuer.issuer;
if (this.#aadIssValidation) {
expectedIss = this.issuer.issuer.replace('{tenantid}', payload.tid);
}
if (payload.iss !== expectedIss) {
throw new RPError({
printf: [
'unexpected iss value, expected %s, got: %s',
expectedIss,
payload.iss
],
jwt
});
}
}
if (payload.iat !== undefined) {
if (typeof payload.iat !== 'number') {
throw new RPError({
message: 'JWT iat claim must be a JSON numeric value',
jwt
});
}
}
if (payload.nbf !== undefined) {
if (typeof payload.nbf !== 'number') {
throw new RPError({
message: 'JWT nbf claim must be a JSON numeric value',
jwt
});
}
if (payload.nbf > timestamp + this[CLOCK_TOLERANCE]) {
throw new RPError({
printf: [
'JWT not active yet, now %i, nbf %i',
timestamp + this[CLOCK_TOLERANCE],
payload.nbf
],
now: timestamp,
tolerance: this[CLOCK_TOLERANCE],
nbf: payload.nbf,
jwt
});
}
}
if (payload.exp !== undefined) {
if (typeof payload.exp !== 'number') {
throw new RPError({
message: 'JWT exp claim must be a JSON numeric value',
jwt
});
}
if (timestamp - this[CLOCK_TOLERANCE] >= payload.exp) {
throw new RPError({
printf: [
'JWT expired, now %i, exp %i',
timestamp - this[CLOCK_TOLERANCE],
payload.exp
],
now: timestamp,
tolerance: this[CLOCK_TOLERANCE],
exp: payload.exp,
jwt
});
}
}
if (payload.aud !== undefined) {
if (Array.isArray(payload.aud)) {
if (payload.aud.length > 1 && !payload.azp) {
throw new RPError({
message: 'missing required JWT property azp',
jwt
});
}
if (!payload.aud.includes(this.client_id)) {
throw new RPError({
printf: [
'aud is missing the client_id, expected %s to be included in %j',
this.client_id,
payload.aud
],
jwt
});
}
} else if (payload.aud !== this.client_id) {
throw new RPError({
printf: [
'aud mismatch, expected %s, got: %s',
this.client_id,
payload.aud
],
jwt
});
}
}
if (payload.azp !== undefined) {
let additionalAuthorizedParties = this.#additionalAuthorizedParties;
if (typeof additionalAuthorizedParties === 'string') {
additionalAuthorizedParties = [
this.client_id,
additionalAuthorizedParties
];
} else if (Array.isArray(additionalAuthorizedParties)) {
additionalAuthorizedParties = [
this.client_id,
...additionalAuthorizedParties
];
} else {
additionalAuthorizedParties = [
this.client_id
];
}
if (!additionalAuthorizedParties.includes(payload.azp)) {
throw new RPError({
printf: [
'azp mismatch, got: %s',
payload.azp
],
jwt
});
}
}
let keys;
if (isSelfIssued) {
try {
assert(isPlainObject(payload.sub_jwk));
const key = await jose.importJWK(payload.sub_jwk, header.alg);
assert.equal(key.type, 'public');
keys = [
{
keyObject () {
return key;
}
}
];
} catch (err) {
throw new RPError({
message: 'failed to use sub_jwk claim as an asymmetric JSON Web Key',
jwt
});
}
if (await jose.calculateJwkThumbprint(payload.sub_jwk) !== payload.sub) {
throw new RPError({
message: 'failed to match the subject with sub_jwk',
jwt
});
}
} else if (header.alg.startsWith('HS')) {
keys = [
this.secretForAlg(header.alg)
];
} else if (header.alg !== 'none') {
keys = await queryKeyStore.call(this.issuer, {
...header,
use: 'sig'
});
}
if (!keys && header.alg === 'none') {
return {
protected: header,
payload
};
}
for (const key of keys){
const verified = await jose.compactVerify(jwt, key instanceof Uint8Array ? key : await key.keyObject(header.alg)).catch(()=>{});
if (verified) {
return {
payload,
protected: verified.protectedHeader,
key
};
}
}
throw new RPError({
message: 'failed to validate JWT signature',
jwt
});
}
async refresh(refreshToken, { exchangeBody, clientAssertionPayload, DPoP } = {}) {
let token = refreshToken;
if (token instanceof TokenSet) {
if (!token.refresh_token) {
throw new TypeError('refresh_token not present in TokenSet');
}
token = token.refresh_token;
}
const tokenset = await this.grant({
...exchangeBody,
grant_type: 'refresh_token',
refresh_token: String(token)
}, {
clientAssertionPayload,
DPoP
});
if (tokenset.id_token) {
await this.decryptIdToken(tokenset);
await this.validateIdToken(tokenset, skipNonceCheck, 'token', skipMaxAgeCheck);
if (refreshToken instanceof TokenSet && refreshToken.id_token) {
const expectedSub = refreshToken.claims().sub;
const actualSub = tokenset.claims().sub;
if (actualSub !== expectedSub) {
throw new RPError({
printf: [
'sub mismatch, expected %s, got: %s',
expectedSub,
actualSub
],
jwt: tokenset.id_token
});
}
}
}
return tokenset;
}
async requestResource(resourceUrl, accessToken, { method, headers, body, DPoP, tokenType = DPoP ? 'DPoP' : accessToken instanceof TokenSet ? accessToken.token_type : 'Bearer' } = {}, retry) {
if (accessToken instanceof TokenSet) {
if (!accessToken.access_token) {
throw new TypeError('access_token not present in TokenSet');
}
accessToken = accessToken.access_token;
}
if (!accessToken) {
throw new TypeError('no access token provided');
} else if (typeof accessToken !== 'string') {
throw new TypeError('invalid access token provided');
}
const requestOpts = {
headers: {
Authorization: authorizationHeaderValue(accessToken, tokenType),
...headers
},
body
};
const mTLS = !!this.tls_client_certificate_bound_access_tokens;
const response = await request.call(this, {
...requestOpts,
responseType: 'buffer',
method,
url: resourceUrl
}, {
accessToken,
mTLS,
DPoP
});
const wwwAuthenticate = response.headers['www-authenticate'];
if (retry !== retryAttempt && wwwAuthenticate && wwwAuthenticate.toLowerCase().startsWith('dpop ') && parseWwwAuthenticate(wwwAuthenticate).error === 'use_dpop_nonce') {
return this.requestResource(resourceUrl, accessToken, {
method,
headers,
body,
DPoP,
tokenType
});
}
return response;
}
async userinfo(accessToken, { method = 'GET', via = 'header', tokenType, params, DPoP } = {}) {
assertIssuerConfiguration(this.issuer, 'userinfo_endpoint');
const options = {
tokenType,
method: String(method).toUpperCase(),
DPoP
};
if (options.method !== 'GET' && options.method !== 'POST') {
throw new TypeError('#userinfo() method can only be POST or a GET');
}
if (via === 'body' && options.method !== 'POST') {
throw new TypeError('can only send body on POST');
}
const jwt = !!(this.userinfo_signed_response_alg || this.userinfo_encrypted_response_alg);
if (jwt) {
options.headers = {
Accept: 'application/jwt'
};
} else {
options.headers = {
Accept: 'application/json'
};
}
const mTLS = !!this.tls_client_certificate_bound_access_tokens;
let targetUrl;
if (mTLS && this.issuer.mtls_endpoint_aliases) {
targetUrl = this.issuer.mtls_endpoint_aliases.userinfo_endpoint;
}
targetUrl = new URL(targetUrl || this.issuer.userinfo_endpoint);
if (via === 'body') {
options.headers.Authorization = undefined;
options.headers['Content-Type'] = 'application/x-www-form-urlencoded';
options.body = new URLSearchParams();
options.body.append('access_token', accessToken instanceof TokenSet ? accessToken.access_token : accessToken);
}
// handle additional parameters, GET via querystring, POST via urlencoded body
if (params) {
if (options.method === 'GET') {
Object.entries(params).forEach(([key, value])=>{
targetUrl.searchParams.append(key, value);
});
} else if (options.body) {
// POST && via body
Object.entries(params).forEach(([key, value])=>{
options.body.append(key, value);
});
} else {
// POST && via header
options.body = new URLSearchParams();
options.headers['Content-Type'] = 'application/x-www-form-urlencoded';
Object.entries(params).forEach(([key, value])=>{
options.body.append(key, value);
});
}
}
if (options.body) {
options.body = options.body.toString();
}
const response = await this.requestResource(targetUrl, accessToken, options);
let parsed = processResponse(response, {
bearer: true
});
if (jwt) {
if (!/^application\/jwt/.test(response.headers['content-type'])) {
throw new RPError({
message: 'expected application/jwt response from the userinfo_endpoint',
response
});
}
const body = response.body.toString();
const userinfo = await this.decryptJWTUserinfo(body);
if (!this.userinfo_signed_response_alg) {
try {
parsed = JSON.parse(userinfo);
assert(isPlainObject(parsed));
} catch (err) {
throw new RPError({
message: 'failed to parse userinfo JWE payload as JSON',
jwt: userinfo
});
}
} else {
({ payload: parsed } = await this.validateJWTUserinfo(userinfo));
}
} else {
try {
parsed = JSON.parse(response.body);
} catch (err) {
Object.defineProperty(err, 'response', {
value: response
});
throw err;
}
}
if (accessToken instanceof TokenSet && accessToken.id_token) {
const expectedSub = accessToken.claims().sub;
if (parsed.sub !== expectedSub) {
throw new RPError({
printf: [
'userinfo sub mismatch, expected %s, got: %s',
expectedSub,
parsed.sub
],
body: parsed,
jwt: accessToken.id_token
});
}
}
return parsed;
}
encryptionSecret(len) {
const hash = len <= 256 ? 'sha256' : len <= 384 ? 'sha384' : len <= 512 ? 'sha512' : false;
if (!hash) {
throw new Error('unsupported symmetric encryption key derivation');
}
return crypto.createHash(hash).update(this.client_secret).digest().slice(0, len / 8);
}
secretForAlg(alg) {
if (!this.client_secret) {
throw new TypeError('client_secret is required');
}
if (/^A(\d{3})(?:GCM)?KW$/.test(alg)) {
return this.encryptionSecret(parseInt(RegExp.$1, 10));
}
if (/^A(\d{3})(?:GCM|CBC-HS(\d{3}))$/.test(alg)) {
return this.encryptionSecret(parseInt(RegExp.$2 || RegExp.$1, 10));
}
return new TextEncoder().encode(this.client_secret);
}
async grant(body, { clientAssertionPayload, DPoP } = {}, retry) {
assertIssuerConfiguration(this.issuer, 'token_endpoint');
const response = await authenticatedPost.call(this, 'token', {
form: body,
responseType: 'json'
}, {
clientAssertionPayload,
DPoP
});
let responseBody;
try {
responseBody = processResponse(response);
} catch (err) {
if (retry !== retryAttempt && err instanceof OPError && err.error === 'use_dpop_nonce') {
return this.grant(body, {
clientAssertionPayload,
DPoP
}, retryAttempt);
}
throw err;
}
return new TokenSet(responseBody);
}
async deviceAuthorization(params = {}, { exchangeBody, clientAssertionPayload, DPoP } = {}) {
assertIssuerConfiguration(this.issuer, 'device_authorization_endpoint');
assertIssuerConfiguration(this.issuer, 'token_endpoint');
const body = authorizationParams.call(this, {
client_id: this.client_id,
redirect_uri: null,
response_type: null,
...params
});
const response = await authenticatedPost.call(this, 'device_authorization', {
responseType: 'json',
form: body
}, {
clientAssertionPayload,
endpointAuthMethod: 'token'
});
const responseBody = processResponse(response);
return new DeviceFlowHandle({
client: this,
exchangeBody,
clientAssertionPayload,
response: responseBody,
maxAge: params.max_age,
DPoP
});
}
async revoke(token, hint, { revokeBody, clientAssertionPayload } = {}) {
assertIssuerConfiguration(this.issuer, 'revocation_endpoint');
if (hint !== undefined && typeof hint !== 'string') {
throw new TypeError('hint must be a string');
}
const form = {
...revokeBody,
token
};
if (hint) {
form.token_type_hint = hint;
}
const response = await authenticatedPost.call(this, 'revocation', {
form
}, {
clientAssertionPayload
});
processResponse(response, {
body: false
});
}
async introspect(token, hint, { introspectBody, clientAssertionPayload } = {}) {
assertIssuerConfiguration(this.issuer, 'introspection_endpoint');
if (hint !== undefined && typeof hint !== 'string') {
throw new TypeError('hint must be a string');
}
const form = {
...introspectBody,
token
};
if (hint) {
form.token_type_hint = hint;
}
const response = await authenticatedPost.call(this, 'introspection', {
form,
responseType: 'json'
}, {
clientAssertionPayload
});
const responseBody = processResponse(response);
return responseBody;
}
static async register(metadata, options = {}) {
const { initialAccessToken, jwks, ...clientOptions } = options;
assertIssuerConfiguration(this.issuer, 'registration_endpoint');
if (jwks !== undefined && !(metadata.jwks || metadata.jwks_uri)) {
const keystore = await getKeystore.call(this, jwks);
metadata.jwks = keystore.toJWKS();
}
const response = await request.call(this, {
headers: {
Accept: 'application/json',
...initialAccessToken ? {
Authorization: authorizationHeaderValue(initialAccessToken)
} : undefined
},
responseType: 'json',
json: metadata,
url: this.issuer.registration_endpoint,
method: 'POST'
});
const responseBody = processResponse(response, {
statusCode: 201,
bearer: true
});
return new this(responseBody, jwks, clientOptions);
}
get metadata() {
return clone(Object.fromEntries(this.#metadata.entries()));
}
static async fromUri(registrationClientUri, registrationAccessToken, jwks, clientOptions) {
const response = await request.call(this, {
method: 'GET',
url: registrationClientUri,
responseType: 'json',
headers: {
Authorization: authorizationHeaderValue(registrationAccessToken),
Accept: 'application/json'
}
});
const responseBody = processResponse(response, {
bearer: true
});
return new this(responseBody, jwks, clientOptions);
}
async requestObject(requestObject = {}, { sign: signingAlgorithm = this.request_object_signing_alg || 'none', encrypt: { alg: eKeyManagement = this.request_object_encryption_alg, enc: eContentEncryption = this.request_object_encryption_enc || 'A128CBC-HS256' } = {} } = {}) {
if (!isPlainObject(requestObject)) {
throw new TypeError('requestObject must be a plain object');
}
let signed;
let key;
const unix = now();
const header = {
alg: signingAlgorithm,
typ: 'oauth-authz-req+jwt'
};
const payload = JSON.stringify(defaults({}, requestObject, {
iss: this.client_id,
aud: this.issuer.issuer,
client_id: this.client_id,
jti: random(),
iat: unix,
exp: unix + 300,
...this.fapi() ? {
nbf: unix
} : undefined
}));
if (signingAlgorithm === 'none') {
signed = [
base64url.encode(JSON.stringify(header)),
base64url.encode(payload),
''
].join('.');
} else {
const symmetric = signingAlgorithm.startsWith('HS');
if (symmetric) {
key = this.secretForAlg(signingAlgorithm);
} else {
const keystore = await keystores.get(this);
if (!keystore) {
throw new TypeError(`no keystore present for client, cannot sign using alg ${signingAlgorithm}`);
}
key = keystore.get({
alg: signingAlgorithm,
use: 'sig'
});
if (!key) {
throw new TypeError(`no key to sign with found for alg ${signingAlgorithm}`);
}
}
signed = await new jose.CompactSign(new TextEncoder().encode(payload)).setProtectedHeader({
...header,
kid: symmetric ? undefined : key.jwk.kid
}).sign(symmetric ? key : await key.keyObject(signingAlgorithm));
}
if (!eKeyManagement) {
return signed;
}
const fields = {
alg: eKeyManagement,
enc: eContentEncryption,
cty: 'oauth-authz-req+jwt'
};
if (fields.alg.match(/^(RSA|ECDH)/)) {
[key] = await queryKeyStore.call(this.issuer, {
alg: fields.alg,
use: 'enc'
}, {
allowMulti: true
});
} else {
key = this.secretForAlg(fields.alg === 'dir' ? fields.enc : fields.alg);
}
return new jose.CompactEncrypt(new TextEncoder().encode(signed)).setProtectedHeader({
...fields,
kid: key instanceof Uint8Array ? undefined : key.jwk.kid
}).encrypt(key instanceof Uint8Array ? key : await key.keyObject(fields.alg));
}
async pushedAuthorizationRequest(params = {}, { clientAssertionPayload } = {}) {
assertIssuerConfiguration(this.issuer, 'pushed_authorization_request_endpoint');
const body = {
...'request' in params ? params : authorizationParams.call(this, params),
client_id: this.client_id
};
const response = await authenticatedPost.call(this, 'pushed_authorization_request', {
responseType: 'json',
form: body
}, {
clientAssertionPayload,
endpointAuthMethod: 'token'
});
const responseBody = processResponse(response, {
statusCode: 201
});
if (!('expires_in' in responseBody)) {
throw new RPError({
message: 'expected expires_in in Pushed Authorization Successful Response',
response
});
}
if (typeof responseBody.expires_in !== 'number') {
throw new RPError({
message: 'invalid expires_in value in Pushed Authorization Successful Response',
response
});
}
if (!('request_uri' in responseBody)) {
throw new RPError({
message: 'expected request_uri in Pushed Authorization Successful Response',
response
});
}
if (typeof responseBody.request_uri !== 'string') {
throw new RPError({
message: 'invalid request_uri value in Pushed Authorization Successful Response',
response
});
}
return responseBody;
}
get issuer() {
return this.#issuer;
}
/* istanbul ignore next */ [inspect.custom]() {
return `${this.constructor.name} ${inspect(this.metadata, {
depth: Infinity,
colors: process.stdout.isTTY,
compact: false,
sorted: true
})}`;
}
fapi() {
return this.fapi1() || this.fapi2();
}
fapi1() {
return this.constructor.name === 'FAPI1Client';
}
fapi2() {
return this.constructor.name === 'FAPI2Client';
}
async validateJARM(response) {
const expectedAlg = this.authorization_signed_response_alg;
const { payload } = await this.validateJWT(response, expectedAlg, [
'iss',
'exp',
'aud'
]);
return pickCb(payload);
}
/**
* @name dpopProof
* @api private
*/ async dpopProof(payload, privateKeyInput, accessToken) {
if (!isPlainObject(payload)) {
throw new TypeError('payload must be a plain object');
}
let privateKey;
if (isKeyObject(privateKeyInput)) {
privateKey = privateKeyInput;
} else if (privateKeyInput[Symbol.toStringTag] === 'CryptoKey') {
privateKey = privateKeyInput;
} else if (jose.cryptoRuntime === 'node:crypto') {
privateKey = crypto.createPrivateKey(privateKeyInput);
} else {
throw new TypeError('unrecognized crypto runtime');
}
if (privateKey.type !== 'private') {
throw new TypeError('"DPoP" option must be a private key');
}
let alg = determineDPoPAlgorithm.call(this, privateKey, privateKeyInput);
if (!alg) {
throw new TypeError('could not determine DPoP JWS Algorithm');
}
return new jose.SignJWT({
ath: accessToken ? base64url.encode(crypto.createHash('sha256').update(accessToken).digest()) : undefined,
...payload
}).setProtectedHeader({
alg,
typ: 'dpop+jwt',
jwk: await getJwk(privateKey, privateKeyInput)
}).setIssuedAt().setJti(random()).sign(privateKey);
}
}
function determineDPoPAlgorithmFromCryptoKey(cryptoKey) {
switch(cryptoKey.algorithm.name){
case 'Ed25519':
case 'Ed448':
return 'EdDSA';
case 'ECDSA':
{
switch(cryptoKey.algorithm.namedCurve){
case 'P-256':
return 'ES256';
case 'P-384':
return 'ES384';
case 'P-521':
return 'ES512';
default:
break;
}
break;
}
case 'RSASSA-PKCS1-v1_5':
return `RS${cryptoKey.algorithm.hash.name.slice(4)}`;
case 'RSA-PSS':
return `PS${cryptoKey.algorithm.hash.name.slice(4)}`;
default:
throw new TypeError('unsupported DPoP private key');
}
}
let determineDPoPAlgorithm;
if (jose.cryptoRuntime === 'node:crypto') {
determineDPoPAlgorithm = function(privateKey, privateKeyInput) {
if (privateKeyInput[Symbol.toStringTag] === 'CryptoKey') {
return determineDPoPAlgorithmFromCryptoKey(privateKey);
}
switch(privateKey.asymmetricKeyType){
case 'ed25519':
case 'ed448':
return 'EdDSA';
case 'ec':
return determineEcAlgorithm(privateKey, privateKeyInput);
case 'rsa':
case rsaPssParams && 'rsa-pss':
return determineRsaAlgorithm(privateKey, privateKeyInput, this.issuer.dpop_signing_alg_values_supported);
default:
throw new TypeError('unsupported DPoP private key');
}
};
const RSPS = /^(?:RS|PS)(?:256|384|512)$/;
function determineRsaAlgorithm(privateKey, privateKeyInput, valuesSupported) {
if (typeof privateKeyInput === 'object' && privateKeyInput.format === 'jwk' && privateKeyInput.key && privateKeyInput.key.alg) {
return privateKeyInput.key.alg;
}
if (Array.isArray(valuesSupported)) {
let candidates = valuesSupported.filter(RegExp.prototype.test.bind(RSPS));
if (privateKey.asymmetricKeyType === 'rsa-pss') {
candidates = candidates.filter((value)=>value.startsWith('PS'));
}
return [
'PS256',
'PS384',
'PS512',
'RS256',
'RS384',
'RS384'
].find((preferred)=>candidates.includes(preferred));
}
return 'PS256';
}
const p256 = Buffer.from([
42,
134,
72,
206,
61,
3,
1,
7
]);
const p384 = Buffer.from([
43,
129,
4,
0,
34
]);
const p521 = Buffer.from([
43,
129,
4,
0,
35
]);
const secp256k1 = Buffer.from([
43,
129,
4,
0,
10
]);
function determineEcAlgorithm(privateKey, privateKeyInput) {
// If input was a JWK
switch(typeof privateKeyInput === 'object' && typeof privateKeyInput.key === 'object' && privateKeyInput.key.crv){
case 'P-256':
return 'ES256';
case 'secp256k1':
return 'ES256K';
case 'P-384':
return 'ES384';
case 'P-512':
return 'ES512';
default:
break;
}
const buf = privateKey.export({
format: 'der',
type: 'pkcs8'
});
const i = buf[1] < 128 ? 17 : 18;
const len = buf[i];
const curveOid = buf.slice(i + 1, i + 1 + len);
if (curveOid.equals(p256)) {
return 'ES256';
}
if (curveOid.equals(p384)) {
return 'ES384';
}
if (curveOid.equals(p521)) {
return 'ES512';
}
if (curveOid.equals(secp256k1)) {
return 'ES256K';
}
throw new TypeError('unsupported DPoP private key curve');
}
} else {
determineDPoPAlgorithm = determineDPoPAlgorithmFromCryptoKey;
}
const jwkCache = new WeakMap();
async function getJwk(keyObject, privateKeyInput) {
if (jose.cryptoRuntime === 'node:crypto' && typeof privateKeyInput === 'object' && typeof privateKeyInput.key === 'object' && privateKeyInput.format === 'jwk') {
return pick(privateKeyInput.key, 'kty', 'crv', 'x', 'y', 'e', 'n');
}
if (jwkCache.has(privateKeyInput)) {
return jwkCache.get(privateKeyInput);
}
const jwk = pick(await jose.exportJWK(keyObject), 'kty', 'crv', 'x', 'y', 'e', 'n');
if (isKeyObject(privateKeyInput) || jose.cryptoRuntime === 'WebCryptoAPI') {
jwkCache.set(privateKeyInput, jwk);
}
return jwk;
}
module.exports = (issuer, aadIssValidation = false)=>class Client extends BaseClient {
constructor(...args){
super(issuer, aadIssValidation, ...args);
}
static get issuer() {
return issuer;
}
};
module.exports.BaseClient = BaseClient;
}),
"[project]/node_modules/openid-client/lib/issuer_registry.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const LRU = __turbopack_context__.r("[project]/node_modules/openid-client/node_modules/lru-cache/index.js [app-route] (ecmascript)");
module.exports = new LRU({
max: 100
});
}),
"[project]/node_modules/openid-client/lib/helpers/webfinger_normalize.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
// Credit: https://github.com/rohe/pyoidc/blob/master/src/oic/utils/webfinger.py
// -- Normalization --
// A string of any other type is interpreted as a URI either the form of scheme
// "://" authority path-abempty [ "?" query ] [ "#" fragment ] or authority
// path-abempty [ "?" query ] [ "#" fragment ] per RFC 3986 [RFC3986] and is
// normalized according to the following rules:
//
// If the user input Identifier does not have an RFC 3986 [RFC3986] scheme
// portion, the string is interpreted as [userinfo "@"] host [":" port]
// path-abempty [ "?" query ] [ "#" fragment ] per RFC 3986 [RFC3986].
// If the userinfo component is present and all of the path component, query
// component, and port component are empty, the acct scheme is assumed. In this
// case, the normalized URI is formed by prefixing acct: to the string as the
// scheme. Per the 'acct' URI Scheme [ID.ietfappsawgaccturi], if there is an
// at-sign character ('@') in the userinfo component, it needs to be
// percent-encoded as described in RFC 3986 [RFC3986].
// For all other inputs without a scheme portion, the https scheme is assumed,
// and the normalized URI is formed by prefixing https:// to the string as the
// scheme.
// If the resulting URI contains a fragment portion, it MUST be stripped off
// together with the fragment delimiter character "#".
// The WebFinger [ID.ietfappsawgwebfinger] Resource in this case is the
// resulting URI, and the WebFinger Host is the authority component.
//
// Note: Since the definition of authority in RFC 3986 [RFC3986] is
// [ userinfo "@" ] host [ ":" port ], it is legal to have a user input
// identifier like userinfo@host:port, e.g., alice@example.com:8080.
const PORT = /^\d+$/;
function hasScheme(input) {
if (input.includes('://')) return true;
const authority = input.replace(/(\/|\?)/g, '#').split('#')[0];
if (authority.includes(':')) {
const index = authority.indexOf(':');
const hostOrPort = authority.slice(index + 1);
if (!PORT.test(hostOrPort)) {
return true;
}
}
return false;
}
function acctSchemeAssumed(input) {
if (!input.includes('@')) return false;
const parts = input.split('@');
const host = parts[parts.length - 1];
return !(host.includes(':') || host.includes('/') || host.includes('?'));
}
function normalize(input) {
if (typeof input !== 'string') {
throw new TypeError('input must be a string');
}
let output;
if (hasScheme(input)) {
output = input;
} else if (acctSchemeAssumed(input)) {
output = `acct:${input}`;
} else {
output = `https://${input}`;
}
return output.split('#')[0];
}
module.exports = normalize;
}),
"[project]/node_modules/openid-client/lib/issuer.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const { inspect } = __turbopack_context__.r("[externals]/util [external] (util, cjs)");
const url = __turbopack_context__.r("[externals]/url [external] (url, cjs)");
const { RPError } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/errors.js [app-route] (ecmascript)");
const getClient = __turbopack_context__.r("[project]/node_modules/openid-client/lib/client.js [app-route] (ecmascript)");
const registry = __turbopack_context__.r("[project]/node_modules/openid-client/lib/issuer_registry.js [app-route] (ecmascript)");
const processResponse = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/process_response.js [app-route] (ecmascript)");
const webfingerNormalize = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/webfinger_normalize.js [app-route] (ecmascript)");
const request = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/request.js [app-route] (ecmascript)");
const clone = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/deep_clone.js [app-route] (ecmascript)");
const { keystore } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/issuer.js [app-route] (ecmascript)");
const AAD_MULTITENANT_DISCOVERY = [
'https://login.microsoftonline.com/common/.well-known/openid-configuration',
'https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration',
'https://login.microsoftonline.com/organizations/v2.0/.well-known/openid-configuration',
'https://login.microsoftonline.com/consumers/v2.0/.well-known/openid-configuration'
];
const AAD_MULTITENANT = Symbol();
const ISSUER_DEFAULTS = {
claim_types_supported: [
'normal'
],
claims_parameter_supported: false,
grant_types_supported: [
'authorization_code',
'implicit'
],
request_parameter_supported: false,
request_uri_parameter_supported: true,
require_request_uri_registration: false,
response_modes_supported: [
'query',
'fragment'
],
token_endpoint_auth_methods_supported: [
'client_secret_basic'
]
};
class Issuer {
#metadata;
constructor(meta = {}){
const aadIssValidation = meta[AAD_MULTITENANT];
delete meta[AAD_MULTITENANT];
[
'introspection',
'revocation'
].forEach((endpoint)=>{
// if intro/revocation endpoint auth specific meta is missing use the token ones if they
// are defined
if (meta[`${endpoint}_endpoint`] && meta[`${endpoint}_endpoint_auth_methods_supported`] === undefined && meta[`${endpoint}_endpoint_auth_signing_alg_values_supported`] === undefined) {
if (meta.token_endpoint_auth_methods_supported) {
meta[`${endpoint}_endpoint_auth_methods_supported`] = meta.token_endpoint_auth_methods_supported;
}
if (meta.token_endpoint_auth_signing_alg_values_supported) {
meta[`${endpoint}_endpoint_auth_signing_alg_values_supported`] = meta.token_endpoint_auth_signing_alg_values_supported;
}
}
});
this.#metadata = new Map();
Object.entries(meta).forEach(([key, value])=>{
this.#metadata.set(key, value);
if (!this[key]) {
Object.defineProperty(this, key, {
get () {
return this.#metadata.get(key);
},
enumerable: true
});
}
});
registry.set(this.issuer, this);
const Client = getClient(this, aadIssValidation);
Object.defineProperties(this, {
Client: {
value: Client,
enumerable: true
},
FAPI1Client: {
value: class FAPI1Client extends Client {
},
enumerable: true
},
FAPI2Client: {
value: class FAPI2Client extends Client {
},
enumerable: true
}
});
}
get metadata() {
return clone(Object.fromEntries(this.#metadata.entries()));
}
static async webfinger(input) {
const resource = webfingerNormalize(input);
const { host } = url.parse(resource);
const webfingerUrl = `https://${host}/.well-known/webfinger`;
const response = await request.call(this, {
method: 'GET',
url: webfingerUrl,
responseType: 'json',
searchParams: {
resource,
rel: 'http://openid.net/specs/connect/1.0/issuer'
},
headers: {
Accept: 'application/json'
}
});
const body = processResponse(response);
const location = Array.isArray(body.links) && body.links.find((link)=>typeof link === 'object' && link.rel === 'http://openid.net/specs/connect/1.0/issuer' && link.href);
if (!location) {
throw new RPError({
message: 'no issuer found in webfinger response',
body
});
}
if (typeof location.href !== 'string' || !location.href.startsWith('https://')) {
throw new RPError({
printf: [
'invalid issuer location %s',
location.href
],
body
});
}
const expectedIssuer = location.href;
if (registry.has(expectedIssuer)) {
return registry.get(expectedIssuer);
}
const issuer = await this.discover(expectedIssuer);
if (issuer.issuer !== expectedIssuer) {
registry.del(issuer.issuer);
throw new RPError('discovered issuer mismatch, expected %s, got: %s', expectedIssuer, issuer.issuer);
}
return issuer;
}
static async discover(uri) {
const wellKnownUri = resolveWellKnownUri(uri);
const response = await request.call(this, {
method: 'GET',
responseType: 'json',
url: wellKnownUri,
headers: {
Accept: 'application/json'
}
});
const body = processResponse(response);
return new Issuer({
...ISSUER_DEFAULTS,
...body,
[AAD_MULTITENANT]: !!AAD_MULTITENANT_DISCOVERY.find((discoveryURL)=>wellKnownUri.startsWith(discoveryURL))
});
}
async reloadJwksUri() {
await keystore.call(this, true);
}
/* istanbul ignore next */ [inspect.custom]() {
return `${this.constructor.name} ${inspect(this.metadata, {
depth: Infinity,
colors: process.stdout.isTTY,
compact: false,
sorted: true
})}`;
}
}
function resolveWellKnownUri(uri) {
const parsed = url.parse(uri);
if (parsed.pathname.includes('/.well-known/')) {
return uri;
} else {
let pathname;
if (parsed.pathname.endsWith('/')) {
pathname = `${parsed.pathname}.well-known/openid-configuration`;
} else {
pathname = `${parsed.pathname}/.well-known/openid-configuration`;
}
return url.format({
...parsed,
pathname
});
}
}
module.exports = Issuer;
}),
"[project]/node_modules/openid-client/lib/passport_strategy.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const url = __turbopack_context__.r("[externals]/url [external] (url, cjs)");
const { format } = __turbopack_context__.r("[externals]/util [external] (util, cjs)");
const cloneDeep = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/deep_clone.js [app-route] (ecmascript)");
const { RPError, OPError } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/errors.js [app-route] (ecmascript)");
const { BaseClient } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/client.js [app-route] (ecmascript)");
const { random, codeChallenge } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/generators.js [app-route] (ecmascript)");
const pick = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/pick.js [app-route] (ecmascript)");
const { resolveResponseType, resolveRedirectUri } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/client.js [app-route] (ecmascript)");
function verified(err, user, info = {}) {
if (err) {
this.error(err);
} else if (!user) {
this.fail(info);
} else {
this.success(user, info);
}
}
function OpenIDConnectStrategy({ client, params = {}, passReqToCallback = false, sessionKey, usePKCE = true, extras = {} } = {}, verify) {
if (!(client instanceof BaseClient)) {
throw new TypeError('client must be an instance of openid-client Client');
}
if (typeof verify !== 'function') {
throw new TypeError('verify callback must be a function');
}
if (!client.issuer || !client.issuer.issuer) {
throw new TypeError('client must have an issuer with an identifier');
}
this._client = client;
this._issuer = client.issuer;
this._verify = verify;
this._passReqToCallback = passReqToCallback;
this._usePKCE = usePKCE;
this._key = sessionKey || `oidc:${url.parse(this._issuer.issuer).hostname}`;
this._params = cloneDeep(params);
// state and nonce are handled in authenticate()
delete this._params.state;
delete this._params.nonce;
this._extras = cloneDeep(extras);
if (!this._params.response_type) this._params.response_type = resolveResponseType.call(client);
if (!this._params.redirect_uri) this._params.redirect_uri = resolveRedirectUri.call(client);
if (!this._params.scope) this._params.scope = 'openid';
if (this._usePKCE === true) {
const supportedMethods = Array.isArray(this._issuer.code_challenge_methods_supported) ? this._issuer.code_challenge_methods_supported : false;
if (supportedMethods && supportedMethods.includes('S256')) {
this._usePKCE = 'S256';
} else if (supportedMethods && supportedMethods.includes('plain')) {
this._usePKCE = 'plain';
} else if (supportedMethods) {
throw new TypeError('neither code_challenge_method supported by the client is supported by the issuer');
} else {
this._usePKCE = 'S256';
}
} else if (typeof this._usePKCE === 'string' && ![
'plain',
'S256'
].includes(this._usePKCE)) {
throw new TypeError(`${this._usePKCE} is not valid/implemented PKCE code_challenge_method`);
}
this.name = url.parse(client.issuer.issuer).hostname;
}
OpenIDConnectStrategy.prototype.authenticate = function authenticate(req, options) {
(async ()=>{
const client = this._client;
if (!req.session) {
throw new TypeError('authentication requires session support');
}
const reqParams = client.callbackParams(req);
const sessionKey = this._key;
const { 0: parameter, length } = Object.keys(reqParams);
/**
* Start authentication request if this has no authorization response parameters or
* this might a login initiated from a third party as per
* https://openid.net/specs/openid-connect-core-1_0.html#ThirdPartyInitiatedLogin.
*/ if (length === 0 || length === 1 && parameter === 'iss') {
// provide options object with extra authentication parameters
const params = {
state: random(),
...this._params,
...options
};
if (!params.nonce && params.response_type.includes('id_token')) {
params.nonce = random();
}
req.session[sessionKey] = pick(params, 'nonce', 'state', 'max_age', 'response_type');
if (this._usePKCE && params.response_type.includes('code')) {
const verifier = random();
req.session[sessionKey].code_verifier = verifier;
switch(this._usePKCE){
case 'S256':
params.code_challenge = codeChallenge(verifier);
params.code_challenge_method = 'S256';
break;
case 'plain':
params.code_challenge = verifier;
break;
}
}
this.redirect(client.authorizationUrl(params));
return;
}
/* end authentication request */ /* start authentication response */ const session = req.session[sessionKey];
if (Object.keys(session || {}).length === 0) {
throw new Error(format('did not find expected authorization request details in session, req.session["%s"] is %j', sessionKey, session));
}
const { state, nonce, max_age: maxAge, code_verifier: codeVerifier, response_type: responseType } = session;
try {
delete req.session[sessionKey];
} catch (err) {}
const opts = {
redirect_uri: this._params.redirect_uri,
...options
};
const checks = {
state,
nonce,
max_age: maxAge,
code_verifier: codeVerifier,
response_type: responseType
};
const tokenset = await client.callback(opts.redirect_uri, reqParams, checks, this._extras);
const passReq = this._passReqToCallback;
const loadUserinfo = this._verify.length > (passReq ? 3 : 2) && client.issuer.userinfo_endpoint;
const args = [
tokenset,
verified.bind(this)
];
if (loadUserinfo) {
if (!tokenset.access_token) {
throw new RPError({
message: 'expected access_token to be returned when asking for userinfo in verify callback',
tokenset
});
}
const userinfo = await client.userinfo(tokenset);
args.splice(1, 0, userinfo);
}
if (passReq) {
args.unshift(req);
}
this._verify(...args);
/* end authentication response */ })().catch((error)=>{
if (error instanceof OPError && error.error !== 'server_error' && !error.error.startsWith('invalid') || error instanceof RPError) {
this.fail(error);
} else {
this.error(error);
}
});
};
module.exports = OpenIDConnectStrategy;
}),
"[project]/node_modules/openid-client/lib/index.js [app-route] (ecmascript)", ((__turbopack_context__, module, exports) => {
const Issuer = __turbopack_context__.r("[project]/node_modules/openid-client/lib/issuer.js [app-route] (ecmascript)");
const { OPError, RPError } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/errors.js [app-route] (ecmascript)");
const Strategy = __turbopack_context__.r("[project]/node_modules/openid-client/lib/passport_strategy.js [app-route] (ecmascript)");
const TokenSet = __turbopack_context__.r("[project]/node_modules/openid-client/lib/token_set.js [app-route] (ecmascript)");
const { CLOCK_TOLERANCE, HTTP_OPTIONS } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/consts.js [app-route] (ecmascript)");
const generators = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/generators.js [app-route] (ecmascript)");
const { setDefaults } = __turbopack_context__.r("[project]/node_modules/openid-client/lib/helpers/request.js [app-route] (ecmascript)");
module.exports = {
Issuer,
Strategy,
TokenSet,
errors: {
OPError,
RPError
},
custom: {
setHttpOptionsDefaults: setDefaults,
http_options: HTTP_OPTIONS,
clock_tolerance: CLOCK_TOLERANCE
},
generators
};
}),
];
//# sourceMappingURL=node_modules_openid-client_0681y5w._.js.map