![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/domains/lavocat.quebec/private_html/node_modules/openid-client/lib/ |
const { inspect } = require('util');
const url = require('url');
const { RPError } = require('./errors');
const getClient = require('./client');
const registry = require('./issuer_registry');
const processResponse = require('./helpers/process_response');
const webfingerNormalize = require('./helpers/webfinger_normalize');
const request = require('./helpers/request');
const clone = require('./helpers/deep_clone');
const { keystore } = require('./helpers/issuer');
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;