@connectid-tools/rp-nodejs-sdk 4.2.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +284 -237
- package/package.json +7 -5
- package/{config.js → src/config.js} +2 -31
- package/src/conformance/api/conformance-api.d.ts +38 -0
- package/src/conformance/api/conformance-api.js +53 -0
- package/src/conformance/config.json +60 -0
- package/src/conformance/conformance-config.d.ts +2 -0
- package/src/conformance/conformance-config.js +34 -0
- package/src/conformance/conformance.test.js +101 -0
- package/src/conformance/variant.json +1 -0
- package/src/crypto/crypto-loader.d.ts +32 -0
- package/src/crypto/crypto-loader.js +49 -0
- package/src/crypto/jwt-helper.d.ts +61 -0
- package/src/crypto/jwt-helper.js +92 -0
- package/src/crypto/pkce-helper.d.ts +43 -0
- package/src/crypto/pkce-helper.js +75 -0
- package/src/endpoints/participants-endpoint.d.ts +55 -0
- package/src/endpoints/participants-endpoint.js +137 -0
- package/src/endpoints/pushed-authorisation-request-endpoint.d.ts +87 -0
- package/src/endpoints/pushed-authorisation-request-endpoint.js +192 -0
- package/src/endpoints/retrieve-token-endpoint.d.ts +66 -0
- package/src/endpoints/retrieve-token-endpoint.js +159 -0
- package/src/endpoints/userinfo-endpoint.d.ts +24 -0
- package/src/endpoints/userinfo-endpoint.js +50 -0
- package/src/fapi/fapi-utils.d.ts +6 -0
- package/src/fapi/fapi-utils.js +9 -0
- package/src/http/http-client-extensions.d.ts +60 -0
- package/src/http/http-client-extensions.js +106 -0
- package/src/http/http-client-factory.d.ts +27 -0
- package/src/http/http-client-factory.js +45 -0
- package/src/integration/integration.test.d.ts +1 -0
- package/src/integration/integration.test.js +30 -0
- package/src/model/callback-params.d.ts +31 -0
- package/src/model/callback-params.js +1 -0
- package/src/model/claims.d.ts +100 -0
- package/src/model/claims.js +1 -0
- package/src/model/consolidated-token-set.d.ts +74 -0
- package/src/model/consolidated-token-set.js +100 -0
- package/src/model/discovery-service.d.ts +46 -0
- package/src/model/discovery-service.js +112 -0
- package/src/model/issuer-metadata.d.ts +165 -0
- package/src/model/issuer-metadata.js +1 -0
- package/src/model/jwks.d.ts +12 -0
- package/src/model/jwks.js +1 -0
- package/src/model/token-response.d.ts +31 -0
- package/src/model/token-response.js +1 -0
- package/src/model/token-set.d.ts +73 -0
- package/src/model/token-set.js +179 -0
- package/src/relying-party-client-sdk.d.ts +68 -0
- package/src/relying-party-client-sdk.js +150 -0
- package/src/test-data/large-participants-test-data.d.ts +865 -0
- package/src/test-data/large-participants-test-data.js +18907 -0
- package/src/test-data/participants-test-data.d.ts +149 -0
- package/src/test-data/participants-test-data.js +458 -0
- package/src/test-data/sandbox-participants-test-data.d.ts +865 -0
- package/src/test-data/sandbox-participants-test-data.js +3794 -0
- package/src/tests/cert-utils.test.d.ts +1 -0
- package/src/tests/cert-utils.test.js +13 -0
- package/src/tests/functional-utils.test.d.ts +1 -0
- package/src/tests/functional-utils.test.js +13 -0
- package/src/tests/participant-filters.test.d.ts +1 -0
- package/src/tests/participant-filters.test.js +151 -0
- package/src/tests/pushed-authorisation-request-endpoint.test.d.ts +1 -0
- package/src/tests/pushed-authorisation-request-endpoint.test.js +159 -0
- package/src/tests/relying-party-client-sdk.test.d.ts +1 -0
- package/src/tests/relying-party-client-sdk.test.js +313 -0
- package/src/tests/request-utils.test.d.ts +1 -0
- package/src/tests/request-utils.test.js +16 -0
- package/src/tests/system-information.test.d.ts +1 -0
- package/src/tests/system-information.test.js +16 -0
- package/src/tests/user-agent.test.d.ts +1 -0
- package/src/tests/user-agent.test.js +23 -0
- package/src/tests/validator.test.d.ts +1 -0
- package/src/tests/validator.test.js +38 -0
- package/{types.d.ts → src/types.d.ts} +61 -32
- package/src/types.js +1 -0
- package/{utils → src/utils}/request-utils.d.ts +1 -1
- package/src/utils/request-utils.js +8 -0
- package/{utils → src/utils}/user-agent.d.ts +1 -1
- package/src/utils/user-agent.js +4 -0
- package/relying-party-client-sdk.d.ts +0 -37
- package/relying-party-client-sdk.js +0 -364
- package/utils/request-utils.js +0 -8
- package/utils/user-agent.js +0 -6
- /package/{config.d.ts → src/config.d.ts} +0 -0
- /package/{types.js → src/conformance/conformance.test.d.ts} +0 -0
- /package/{filter → src/filter}/participant-filters.d.ts +0 -0
- /package/{filter → src/filter}/participant-filters.js +0 -0
- /package/{logger.d.ts → src/logger.d.ts} +0 -0
- /package/{logger.js → src/logger.js} +0 -0
- /package/{utils → src/utils}/cert-utils.d.ts +0 -0
- /package/{utils → src/utils}/cert-utils.js +0 -0
- /package/{utils → src/utils}/functional-utils.d.ts +0 -0
- /package/{utils → src/utils}/functional-utils.js +0 -0
- /package/{utils → src/utils}/system-information.d.ts +0 -0
- /package/{utils → src/utils}/system-information.js +0 -0
- /package/{validator.d.ts → src/validator.d.ts} +0 -0
- /package/{validator.js → src/validator.js} +0 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { jwtVerify, decodeProtectedHeader, importJWK } from 'jose';
|
|
2
|
+
/**
|
|
3
|
+
* Token Set
|
|
4
|
+
*
|
|
5
|
+
* Represents an OAuth 2.0 / OIDC token response with validation capabilities.
|
|
6
|
+
* Handles ID token validation and claims extraction.
|
|
7
|
+
*/
|
|
8
|
+
export class TokenSet {
|
|
9
|
+
/**
|
|
10
|
+
* Creates a new TokenSet from a token response.
|
|
11
|
+
*
|
|
12
|
+
* @param tokenResponse - Raw token response from the token endpoint
|
|
13
|
+
*/
|
|
14
|
+
constructor(tokenResponse) {
|
|
15
|
+
this.access_token = tokenResponse.access_token;
|
|
16
|
+
this.token_type = tokenResponse.token_type;
|
|
17
|
+
this.expires_in = tokenResponse.expires_in;
|
|
18
|
+
this.refresh_token = tokenResponse.refresh_token;
|
|
19
|
+
this.scope = tokenResponse.scope;
|
|
20
|
+
this.id_token = tokenResponse.id_token;
|
|
21
|
+
this.tokenIssuedAt = Math.floor(Date.now() / 1000);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Validates the ID token.
|
|
25
|
+
*
|
|
26
|
+
* Performs the following validations:
|
|
27
|
+
* - Algorithm validation against allowed algorithms
|
|
28
|
+
* - Signature verification using JWKS
|
|
29
|
+
* - Issuer validation
|
|
30
|
+
* - Audience validation
|
|
31
|
+
* - Nonce validation
|
|
32
|
+
* - Timestamp validation (iat, exp)
|
|
33
|
+
*
|
|
34
|
+
* @param jwks - JSON Web Key Set for signature verification
|
|
35
|
+
* @param expectedIssuer - Expected issuer claim value
|
|
36
|
+
* @param expectedAudience - Expected audience claim value
|
|
37
|
+
* @param expectedNonce - Expected nonce value
|
|
38
|
+
* @param allowedAlgorithms - Optional list of allowed signing algorithms from discovery document
|
|
39
|
+
* @throws Error if validation fails
|
|
40
|
+
*/
|
|
41
|
+
async validate(jwks, expectedIssuer, expectedAudience, expectedNonce, allowedAlgorithms) {
|
|
42
|
+
if (!this.id_token) {
|
|
43
|
+
throw new Error('No id_token to validate');
|
|
44
|
+
}
|
|
45
|
+
try {
|
|
46
|
+
// Decode header to check algorithm before verification
|
|
47
|
+
const header = decodeProtectedHeader(this.id_token);
|
|
48
|
+
// Validate algorithm if allowed algorithms are provided
|
|
49
|
+
if (allowedAlgorithms && allowedAlgorithms.length > 0) {
|
|
50
|
+
if (!header.alg) {
|
|
51
|
+
throw new Error('ID token missing alg in header');
|
|
52
|
+
}
|
|
53
|
+
const isAllowed = allowedAlgorithms.some((alg) => alg.toLowerCase() === header.alg.toLowerCase());
|
|
54
|
+
if (!isAllowed) {
|
|
55
|
+
throw new Error(`ID token algorithm '${header.alg}' is not one of the allowed algorithms: ${allowedAlgorithms.join(', ')}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Select the appropriate key from JWKS
|
|
59
|
+
const key = await this.selectKey(jwks);
|
|
60
|
+
// Verify signature and standard claims
|
|
61
|
+
const { payload } = await jwtVerify(this.id_token, key, {
|
|
62
|
+
issuer: expectedIssuer,
|
|
63
|
+
audience: expectedAudience,
|
|
64
|
+
algorithms: ['PS256', 'RS256'], // Accept both algorithms
|
|
65
|
+
});
|
|
66
|
+
// Validate nonce
|
|
67
|
+
if (payload.nonce !== expectedNonce) {
|
|
68
|
+
throw new Error(`Nonce mismatch: expected ${expectedNonce}, got ${payload.nonce}`);
|
|
69
|
+
}
|
|
70
|
+
// Validate audience claim per OpenID Connect Core 3.1.3.7
|
|
71
|
+
// If aud is an array, all audiences must be trusted (only our client ID is trusted)
|
|
72
|
+
// and azp claim should be present
|
|
73
|
+
if (Array.isArray(payload.aud)) {
|
|
74
|
+
// Check if all audiences are trusted (only client ID is trusted)
|
|
75
|
+
const untrustedAudiences = payload.aud.filter((aud) => aud !== expectedAudience);
|
|
76
|
+
if (untrustedAudiences.length > 0) {
|
|
77
|
+
throw new Error(`ID token contains untrusted audiences: ${untrustedAudiences.join(', ')}`);
|
|
78
|
+
}
|
|
79
|
+
// Per OIDC spec clause 4: if multiple audiences, azp should be present
|
|
80
|
+
if (payload.aud.length > 1 && !payload.azp) {
|
|
81
|
+
throw new Error('ID token contains multiple audiences but azp claim is missing');
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Validate required claims are present
|
|
85
|
+
const now = Math.floor(Date.now() / 1000);
|
|
86
|
+
if (!payload.iat) {
|
|
87
|
+
throw new Error('ID token missing iat claim');
|
|
88
|
+
}
|
|
89
|
+
if (!payload.exp) {
|
|
90
|
+
throw new Error('ID token missing exp claim');
|
|
91
|
+
}
|
|
92
|
+
// Validate iat (must not be more than 10 minutes old per Java SDK)
|
|
93
|
+
if (now - payload.iat > 600) {
|
|
94
|
+
throw new Error(`ID token iat is too old: issued at ${payload.iat}, current time ${now}`);
|
|
95
|
+
}
|
|
96
|
+
// Validate exp (must not be more than 5 minutes in the past - clock skew tolerance)
|
|
97
|
+
if (payload.exp < now - 300) {
|
|
98
|
+
throw new Error(`ID token expired more than 5 minutes ago: exp ${payload.exp}, current time ${now}`);
|
|
99
|
+
}
|
|
100
|
+
// Store validated claims
|
|
101
|
+
this.jwtPayload = payload;
|
|
102
|
+
this.idTokenClaims = payload;
|
|
103
|
+
}
|
|
104
|
+
catch (error) {
|
|
105
|
+
throw new Error(`ID token validation failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Returns the parsed ID token claims.
|
|
110
|
+
*
|
|
111
|
+
* Must call validate() first.
|
|
112
|
+
*
|
|
113
|
+
* @returns Parsed and validated ID token claims
|
|
114
|
+
* @throws Error if token has not been validated
|
|
115
|
+
*/
|
|
116
|
+
claims() {
|
|
117
|
+
if (!this.idTokenClaims) {
|
|
118
|
+
throw new Error('ID token has not been validated. Call validate() first.');
|
|
119
|
+
}
|
|
120
|
+
return this.idTokenClaims;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Checks if the access token has expired.
|
|
124
|
+
*
|
|
125
|
+
* @returns true if the token is expired, false otherwise
|
|
126
|
+
*/
|
|
127
|
+
expired() {
|
|
128
|
+
if (!this.expires_in) {
|
|
129
|
+
// If no expires_in, assume token doesn't expire
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
const now = Math.floor(Date.now() / 1000);
|
|
133
|
+
const expiresAt = this.tokenIssuedAt + this.expires_in;
|
|
134
|
+
return now >= expiresAt;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Selects the appropriate key from JWKS for verification.
|
|
138
|
+
*
|
|
139
|
+
* Matches based on:
|
|
140
|
+
* - kid (key ID)
|
|
141
|
+
* - alg (algorithm)
|
|
142
|
+
* - use (key usage - should be 'sig')
|
|
143
|
+
*
|
|
144
|
+
* @param jwks - JSON Web Key Set
|
|
145
|
+
* @returns Imported crypto key for verification
|
|
146
|
+
* @throws Error if no matching key is found
|
|
147
|
+
*/
|
|
148
|
+
async selectKey(jwks) {
|
|
149
|
+
if (!this.id_token) {
|
|
150
|
+
throw new Error('No id_token present');
|
|
151
|
+
}
|
|
152
|
+
// Decode header to get kid and alg
|
|
153
|
+
const header = decodeProtectedHeader(this.id_token);
|
|
154
|
+
if (!header.kid) {
|
|
155
|
+
throw new Error('ID token missing kid in header');
|
|
156
|
+
}
|
|
157
|
+
// Find matching key
|
|
158
|
+
const matchingKey = jwks.keys.find((key) => {
|
|
159
|
+
// Match by kid (required)
|
|
160
|
+
if (key.kid !== header.kid) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
// Match by alg if present in key
|
|
164
|
+
if (key.alg && key.alg !== header.alg) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
// Match by use if present (should be 'sig' for signing)
|
|
168
|
+
if (key.use && key.use !== 'sig') {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
return true;
|
|
172
|
+
});
|
|
173
|
+
if (!matchingKey) {
|
|
174
|
+
throw new Error(`No matching key found in JWKS for kid: ${header.kid}, alg: ${header.alg}`);
|
|
175
|
+
}
|
|
176
|
+
// Import the JWK for verification
|
|
177
|
+
return importJWK(matchingKey, header.alg);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { CallbackParams, ConsolidatedTokenSet, Participant, RelyingPartyClientSdkConfig } from './types.js';
|
|
2
|
+
export default class RelyingPartyClientSdk {
|
|
3
|
+
private readonly logger;
|
|
4
|
+
private config;
|
|
5
|
+
private readonly purpose;
|
|
6
|
+
private readonly participantsEndpoint;
|
|
7
|
+
private readonly pushedAuthorisationRequestEndpoint;
|
|
8
|
+
private readonly retrieveTokenEndpoint;
|
|
9
|
+
private readonly userInfoEndpoint;
|
|
10
|
+
private readonly httpClient;
|
|
11
|
+
private readonly jwtHelper;
|
|
12
|
+
constructor(config: RelyingPartyClientSdkConfig);
|
|
13
|
+
/**
|
|
14
|
+
* Get the list of participating identity providers within the scheme.
|
|
15
|
+
*
|
|
16
|
+
* Applies filtering based on SDK configuration.
|
|
17
|
+
*
|
|
18
|
+
* @returns List of participants
|
|
19
|
+
*/
|
|
20
|
+
getParticipants(): Promise<Participant[]>;
|
|
21
|
+
/**
|
|
22
|
+
* Get the list of fallback provider participants.
|
|
23
|
+
*
|
|
24
|
+
* @returns List of fallback provider participants
|
|
25
|
+
*/
|
|
26
|
+
getFallbackProviderParticipants(): Promise<Participant[]>;
|
|
27
|
+
/**
|
|
28
|
+
* Sends a Pushed Authorization Request (PAR).
|
|
29
|
+
*
|
|
30
|
+
* @param authServerId - Authorization server ID
|
|
31
|
+
* @param essentialClaims - Claims that must be provided
|
|
32
|
+
* @param voluntaryClaims - Claims that are optional
|
|
33
|
+
* @param purpose - Purpose string for data sharing
|
|
34
|
+
* @returns Object containing authorization URL and PKCE parameters
|
|
35
|
+
*/
|
|
36
|
+
sendPushedAuthorisationRequest(authServerId: string, essentialClaims: string[], voluntaryClaims?: string[], purpose?: string): Promise<{
|
|
37
|
+
authUrl: string;
|
|
38
|
+
codeVerifier: string;
|
|
39
|
+
state: string;
|
|
40
|
+
nonce: string;
|
|
41
|
+
xFapiInteractionId: string;
|
|
42
|
+
}>;
|
|
43
|
+
/**
|
|
44
|
+
* Retrieves tokens using an authorisation code.
|
|
45
|
+
*
|
|
46
|
+
* @param authorisationServerId - Authorisation server ID
|
|
47
|
+
* @param requestParams - OAuth callback parameters
|
|
48
|
+
* @param codeVerifier - PKCE code verifier from PAR
|
|
49
|
+
* @param state - State parameter from PAR
|
|
50
|
+
* @param nonce - Nonce parameter from PAR
|
|
51
|
+
* @returns Consolidated token set with validated claims
|
|
52
|
+
*/
|
|
53
|
+
retrieveTokens(authorisationServerId: string, requestParams: CallbackParams, codeVerifier: string, state: string, nonce: string): Promise<ConsolidatedTokenSet>;
|
|
54
|
+
/**
|
|
55
|
+
* Retrieves user information from the UserInfo endpoint.
|
|
56
|
+
*
|
|
57
|
+
* @param authorisationServerId - Authorization server ID
|
|
58
|
+
* @param accessToken - Access token
|
|
59
|
+
* @returns UserInfo claims
|
|
60
|
+
*/
|
|
61
|
+
getUserInfo(authorisationServerId: string, accessToken: string): Promise<Record<string, unknown>>;
|
|
62
|
+
/**
|
|
63
|
+
* Gets the current date (for testing purposes).
|
|
64
|
+
*
|
|
65
|
+
* @returns Current date
|
|
66
|
+
*/
|
|
67
|
+
getCurrentDate(): Date;
|
|
68
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { getCertificate } from './utils/cert-utils.js';
|
|
2
|
+
import { getLogger } from './logger.js';
|
|
3
|
+
import ParticipantFilters from './filter/participant-filters.js';
|
|
4
|
+
import { illegalPurposeChars, isValidCertificate, validatePurpose } from './validator.js';
|
|
5
|
+
import { CryptoLoader } from './crypto/crypto-loader.js';
|
|
6
|
+
import { JwtHelper } from './crypto/jwt-helper.js';
|
|
7
|
+
import { HttpClientFactory } from './http/http-client-factory.js';
|
|
8
|
+
import { ParticipantsEndpoint } from './endpoints/participants-endpoint.js';
|
|
9
|
+
import { PushedAuthorisationRequestEndpoint } from './endpoints/pushed-authorisation-request-endpoint.js';
|
|
10
|
+
import { RetrieveTokenEndpoint } from './endpoints/retrieve-token-endpoint.js';
|
|
11
|
+
import { UserInfoEndpoint } from './endpoints/userinfo-endpoint.js';
|
|
12
|
+
export default class RelyingPartyClientSdk {
|
|
13
|
+
constructor(config) {
|
|
14
|
+
this.purpose = 'verifying your identity';
|
|
15
|
+
this.config = config;
|
|
16
|
+
// Validate certificates
|
|
17
|
+
if (!isValidCertificate(this.config.data.transport_key, this.config.data.transport_key_content)) {
|
|
18
|
+
throw new Error('Either transport_key or transport_key_content must be provided');
|
|
19
|
+
}
|
|
20
|
+
if (!isValidCertificate(this.config.data.transport_pem, this.config.data.transport_pem_content)) {
|
|
21
|
+
throw new Error('Either transport_pem or transport_pem_content must be provided');
|
|
22
|
+
}
|
|
23
|
+
if (!isValidCertificate(this.config.data.signing_key, this.config.data.signing_key_content)) {
|
|
24
|
+
throw new Error('Either signing_key or signing_key_content must be provided');
|
|
25
|
+
}
|
|
26
|
+
if (!isValidCertificate(this.config.data.ca_pem, this.config.data.ca_pem_content)) {
|
|
27
|
+
throw new Error('Either ca_pem or ca_pem_content must be provided');
|
|
28
|
+
}
|
|
29
|
+
this.logger = getLogger(this.config.data.log_level);
|
|
30
|
+
this.logger.info(`Creating RelyingPartyClientSdk - version ${process.env.SDK_VERSION}`);
|
|
31
|
+
// Validate and set purpose
|
|
32
|
+
if (this.config.data.purpose) {
|
|
33
|
+
const purposeValidation = validatePurpose(this.config.data.purpose);
|
|
34
|
+
if (purposeValidation === 'INVALID_LENGTH') {
|
|
35
|
+
this.logger.warn('Purpose must be between 3 and 300 characters');
|
|
36
|
+
throw new Error(`Invalid purpose supplied in config: ${this.config.data.purpose}`);
|
|
37
|
+
}
|
|
38
|
+
if (purposeValidation === 'INVALID_CHARACTERS') {
|
|
39
|
+
this.logger.warn(`Purpose cannot contain any of the following characters: ${illegalPurposeChars.join(',')}, purpose supplied: [${this.config.data.purpose}]`);
|
|
40
|
+
throw new Error(`Invalid purpose supplied in config: ${this.config.data.purpose}`);
|
|
41
|
+
}
|
|
42
|
+
this.purpose = this.config.data.purpose;
|
|
43
|
+
this.logger.info(`Using default purpose supplied in config: ${this.purpose}`);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
this.logger.info(`Using built-in default purpose: ${this.purpose}`);
|
|
47
|
+
}
|
|
48
|
+
// Log filtering configuration
|
|
49
|
+
if (this.config.data.include_uncertified_participants) {
|
|
50
|
+
this.logger.info('Identity provider list will not be filtered as include_uncertified_participants=true');
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
if (this.config.data.required_claims) {
|
|
54
|
+
this.logger.info(`Identity provider list will be filtered for participants that support the following claims: ${JSON.stringify(this.config.data.required_claims)}`);
|
|
55
|
+
}
|
|
56
|
+
if (this.config.data.required_participant_certifications) {
|
|
57
|
+
this.logger.info(`Identity provider list will be filtered for participants that support the following certifications: ${JSON.stringify(this.config.data.required_participant_certifications)}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Log certificate source
|
|
61
|
+
this.logger.info(`Using ${this.config.data.transport_key_content ? 'transport_key_content' : 'transport_key'} config prop`);
|
|
62
|
+
this.logger.info(`Using ${this.config.data.transport_pem_content ? 'transport_pem_content' : 'transport_pem'} config prop`);
|
|
63
|
+
this.logger.info(`Using ${this.config.data.ca_pem_content ? 'ca_pem_content' : 'ca_pem'} config prop`);
|
|
64
|
+
this.logger.info(`Using ${this.config.data.signing_key_content ? 'signing_key_content' : 'signing_key'} config prop`);
|
|
65
|
+
// Initialize crypto
|
|
66
|
+
const signingKeyObject = CryptoLoader.loadPrivateKey(getCertificate(this.config.data.signing_key, this.config.data.signing_key_content));
|
|
67
|
+
// Initialize JWT helper
|
|
68
|
+
this.jwtHelper = new JwtHelper(signingKeyObject, this.config.data.signing_kid, this.config.data.client_id);
|
|
69
|
+
// Initialize HTTP client
|
|
70
|
+
this.httpClient = HttpClientFactory.createClient({
|
|
71
|
+
transportKey: getCertificate(this.config.data.transport_key, this.config.data.transport_key_content),
|
|
72
|
+
transportPem: getCertificate(this.config.data.transport_pem, this.config.data.transport_pem_content),
|
|
73
|
+
caPem: getCertificate(this.config.data.ca_pem, this.config.data.ca_pem_content),
|
|
74
|
+
clientId: this.config.data.client_id,
|
|
75
|
+
});
|
|
76
|
+
// Initialize endpoints
|
|
77
|
+
this.participantsEndpoint = new ParticipantsEndpoint(this.config, new ParticipantFilters(), this.httpClient, this.logger, () => this.getCurrentDate());
|
|
78
|
+
this.pushedAuthorisationRequestEndpoint = new PushedAuthorisationRequestEndpoint(this.config, this.httpClient, this.jwtHelper, this.logger, this.participantsEndpoint);
|
|
79
|
+
this.retrieveTokenEndpoint = new RetrieveTokenEndpoint(this.config, this.httpClient, this.jwtHelper, this.logger, this.participantsEndpoint);
|
|
80
|
+
this.userInfoEndpoint = new UserInfoEndpoint(this.httpClient, this.logger, this.config.data.client_id, this.participantsEndpoint);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get the list of participating identity providers within the scheme.
|
|
84
|
+
*
|
|
85
|
+
* Applies filtering based on SDK configuration.
|
|
86
|
+
*
|
|
87
|
+
* @returns List of participants
|
|
88
|
+
*/
|
|
89
|
+
async getParticipants() {
|
|
90
|
+
return this.participantsEndpoint.getParticipants();
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get the list of fallback provider participants.
|
|
94
|
+
*
|
|
95
|
+
* @returns List of fallback provider participants
|
|
96
|
+
*/
|
|
97
|
+
async getFallbackProviderParticipants() {
|
|
98
|
+
return this.participantsEndpoint.getFallbackProviderParticipants();
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Sends a Pushed Authorization Request (PAR).
|
|
102
|
+
*
|
|
103
|
+
* @param authServerId - Authorization server ID
|
|
104
|
+
* @param essentialClaims - Claims that must be provided
|
|
105
|
+
* @param voluntaryClaims - Claims that are optional
|
|
106
|
+
* @param purpose - Purpose string for data sharing
|
|
107
|
+
* @returns Object containing authorization URL and PKCE parameters
|
|
108
|
+
*/
|
|
109
|
+
async sendPushedAuthorisationRequest(authServerId, essentialClaims, voluntaryClaims = [], purpose = this.purpose) {
|
|
110
|
+
const { authUrl, codeVerifier, state, nonce, xFapiInteractionId } = await this.pushedAuthorisationRequestEndpoint.sendPushedAuthorisationRequest(authServerId, essentialClaims, voluntaryClaims, purpose);
|
|
111
|
+
return {
|
|
112
|
+
authUrl,
|
|
113
|
+
codeVerifier,
|
|
114
|
+
state,
|
|
115
|
+
nonce,
|
|
116
|
+
xFapiInteractionId,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Retrieves tokens using an authorisation code.
|
|
121
|
+
*
|
|
122
|
+
* @param authorisationServerId - Authorisation server ID
|
|
123
|
+
* @param requestParams - OAuth callback parameters
|
|
124
|
+
* @param codeVerifier - PKCE code verifier from PAR
|
|
125
|
+
* @param state - State parameter from PAR
|
|
126
|
+
* @param nonce - Nonce parameter from PAR
|
|
127
|
+
* @returns Consolidated token set with validated claims
|
|
128
|
+
*/
|
|
129
|
+
async retrieveTokens(authorisationServerId, requestParams, codeVerifier, state, nonce) {
|
|
130
|
+
return this.retrieveTokenEndpoint.retrieveTokens(authorisationServerId, requestParams, codeVerifier, state, nonce);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Retrieves user information from the UserInfo endpoint.
|
|
134
|
+
*
|
|
135
|
+
* @param authorisationServerId - Authorization server ID
|
|
136
|
+
* @param accessToken - Access token
|
|
137
|
+
* @returns UserInfo claims
|
|
138
|
+
*/
|
|
139
|
+
async getUserInfo(authorisationServerId, accessToken) {
|
|
140
|
+
return this.userInfoEndpoint.getUserInfo(authorisationServerId, accessToken);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Gets the current date (for testing purposes).
|
|
144
|
+
*
|
|
145
|
+
* @returns Current date
|
|
146
|
+
*/
|
|
147
|
+
getCurrentDate() {
|
|
148
|
+
return new Date();
|
|
149
|
+
}
|
|
150
|
+
}
|