@sphereon/oid4vci-common 0.8.2-next.48 → 0.8.2-next.87
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/dist/functions/AuthorizationResponseUtil.d.ts +3 -0
- package/dist/functions/AuthorizationResponseUtil.d.ts.map +1 -0
- package/dist/functions/AuthorizationResponseUtil.js +21 -0
- package/dist/functions/AuthorizationResponseUtil.js.map +1 -0
- package/dist/functions/CredentialOfferUtil.d.ts +2 -0
- package/dist/functions/CredentialOfferUtil.d.ts.map +1 -1
- package/dist/functions/CredentialOfferUtil.js +64 -2
- package/dist/functions/CredentialOfferUtil.js.map +1 -1
- package/dist/functions/CredentialRequestUtil.d.ts +2 -2
- package/dist/functions/CredentialRequestUtil.d.ts.map +1 -1
- package/dist/functions/CredentialRequestUtil.js +16 -1
- package/dist/functions/CredentialRequestUtil.js.map +1 -1
- package/dist/functions/Encoding.js +1 -1
- package/dist/functions/Encoding.js.map +1 -1
- package/dist/functions/HttpUtils.js +1 -1
- package/dist/functions/HttpUtils.js.map +1 -1
- package/dist/functions/IssuerMetadataUtils.d.ts +5 -1
- package/dist/functions/IssuerMetadataUtils.d.ts.map +1 -1
- package/dist/functions/IssuerMetadataUtils.js +16 -1
- package/dist/functions/IssuerMetadataUtils.js.map +1 -1
- package/dist/functions/RandomUtils.d.ts +10 -0
- package/dist/functions/RandomUtils.d.ts.map +1 -0
- package/dist/functions/RandomUtils.js +73 -0
- package/dist/functions/RandomUtils.js.map +1 -0
- package/dist/functions/index.d.ts +5 -0
- package/dist/functions/index.d.ts.map +1 -1
- package/dist/functions/index.js +6 -0
- package/dist/functions/index.js.map +1 -1
- package/dist/functions/randomBytes.d.ts +7 -0
- package/dist/functions/randomBytes.d.ts.map +1 -0
- package/dist/functions/randomBytes.js +56 -0
- package/dist/functions/randomBytes.js.map +1 -0
- package/dist/types/Authorization.types.d.ts +48 -10
- package/dist/types/Authorization.types.d.ts.map +1 -1
- package/dist/types/Authorization.types.js +24 -3
- package/dist/types/Authorization.types.js.map +1 -1
- package/dist/types/CredentialIssuance.types.d.ts +4 -1
- package/dist/types/CredentialIssuance.types.d.ts.map +1 -1
- package/dist/types/CredentialIssuance.types.js.map +1 -1
- package/dist/types/Generic.types.d.ts +17 -0
- package/dist/types/Generic.types.d.ts.map +1 -1
- package/dist/types/Generic.types.js.map +1 -1
- package/dist/types/OpenID4VCIVersions.types.d.ts +1 -0
- package/dist/types/OpenID4VCIVersions.types.d.ts.map +1 -1
- package/dist/types/OpenID4VCIVersions.types.js +2 -1
- package/dist/types/OpenID4VCIVersions.types.js.map +1 -1
- package/dist/types/v1_0_11.types.d.ts +14 -2
- package/dist/types/v1_0_11.types.d.ts.map +1 -1
- package/dist/types/v1_0_11.types.js.map +1 -1
- package/dist/types/v1_0_12.types.d.ts +3 -0
- package/dist/types/v1_0_12.types.d.ts.map +1 -0
- package/dist/types/v1_0_12.types.js +3 -0
- package/dist/types/v1_0_12.types.js.map +1 -0
- package/lib/__tests__/CredentialOfferUtil.spec.ts +51 -2
- package/lib/__tests__/Encoding.spec.ts +15 -0
- package/lib/__tests__/randomBytes.spec.ts +15 -0
- package/lib/functions/AuthorizationResponseUtil.ts +18 -0
- package/lib/functions/CredentialOfferUtil.ts +62 -1
- package/lib/functions/CredentialRequestUtil.ts +18 -3
- package/lib/functions/Encoding.ts +1 -1
- package/lib/functions/HttpUtils.ts +1 -1
- package/lib/functions/IssuerMetadataUtils.ts +19 -0
- package/lib/functions/RandomUtils.ts +43 -0
- package/lib/functions/index.ts +5 -0
- package/lib/functions/randomBytes.js +61 -0
- package/lib/types/Authorization.types.ts +71 -6
- package/lib/types/CredentialIssuance.types.ts +7 -1
- package/lib/types/Generic.types.ts +26 -0
- package/lib/types/OpenID4VCIVersions.types.ts +2 -1
- package/lib/types/v1_0_11.types.ts +19 -2
- package/lib/types/v1_0_12.types.ts +4 -0
- package/package.json +14 -3
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Debug from 'debug';
|
|
2
|
+
import jwtDecode, { JwtPayload } from 'jwt-decode';
|
|
2
3
|
|
|
3
4
|
import {
|
|
4
5
|
AssertedUniformCredentialOffer,
|
|
@@ -68,8 +69,53 @@ export function getIssuerFromCredentialOfferPayload(request: CredentialOfferPayl
|
|
|
68
69
|
return 'issuer' in request ? request.issuer : request['credential_issuer'];
|
|
69
70
|
}
|
|
70
71
|
|
|
72
|
+
export const getClientIdFromCredentialOfferPayload = (credentialOffer?: CredentialOfferPayload): string | undefined => {
|
|
73
|
+
if (!credentialOffer) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if ('client_id' in credentialOffer) {
|
|
77
|
+
return credentialOffer.client_id;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const state: string | undefined = getStateFromCredentialOfferPayload(credentialOffer);
|
|
81
|
+
if (state && isJWT(state)) {
|
|
82
|
+
const decoded = jwtDecode<JwtPayload>(state, { header: false });
|
|
83
|
+
if ('client_id' in decoded && typeof decoded.client_id === 'string') {
|
|
84
|
+
return decoded.client_id;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const isJWT = (input?: string) => {
|
|
91
|
+
if (!input) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
const noParts = input?.split('.').length;
|
|
95
|
+
return input?.startsWith('ey') && noParts === 3;
|
|
96
|
+
};
|
|
97
|
+
export const getStateFromCredentialOfferPayload = (credentialOffer: CredentialOfferPayload): string | undefined => {
|
|
98
|
+
if ('grants' in credentialOffer) {
|
|
99
|
+
if (credentialOffer.grants?.authorization_code) {
|
|
100
|
+
return credentialOffer.grants.authorization_code.issuer_state;
|
|
101
|
+
} else if (credentialOffer.grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']) {
|
|
102
|
+
return credentialOffer.grants?.['urn:ietf:params:oauth:grant-type:pre-authorized_code']?.['pre-authorized_code'];
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if ('op_state' in credentialOffer) {
|
|
106
|
+
// older spec versions
|
|
107
|
+
return credentialOffer.op_state;
|
|
108
|
+
} else if ('pre-authorized_code' in credentialOffer) {
|
|
109
|
+
return credentialOffer['pre-authorized_code'];
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return;
|
|
113
|
+
};
|
|
114
|
+
|
|
71
115
|
export function determineSpecVersionFromOffer(offer: CredentialOfferPayload | CredentialOffer): OpenId4VCIVersion {
|
|
72
|
-
if (
|
|
116
|
+
if (isCredentialOfferV1_0_12(offer)) {
|
|
117
|
+
return OpenId4VCIVersion.VER_1_0_12;
|
|
118
|
+
} else if (isCredentialOfferV1_0_11(offer)) {
|
|
73
119
|
return OpenId4VCIVersion.VER_1_0_11;
|
|
74
120
|
} else if (isCredentialOfferV1_0_09(offer)) {
|
|
75
121
|
return OpenId4VCIVersion.VER_1_0_09;
|
|
@@ -139,6 +185,21 @@ function isCredentialOfferV1_0_11(offer: CredentialOfferPayload | CredentialOffe
|
|
|
139
185
|
return 'credential_offer_uri' in offer;
|
|
140
186
|
}
|
|
141
187
|
|
|
188
|
+
function isCredentialOfferV1_0_12(offer: CredentialOfferPayload | CredentialOffer): boolean {
|
|
189
|
+
if (!offer) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
if ('credential_issuer' in offer && 'credentials' in offer) {
|
|
193
|
+
// payload
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
if ('credential_offer' in offer && offer['credential_offer']) {
|
|
197
|
+
// offer, so check payload
|
|
198
|
+
return isCredentialOfferV1_0_12(offer['credential_offer']);
|
|
199
|
+
}
|
|
200
|
+
return 'credential_offer_uri' in offer;
|
|
201
|
+
}
|
|
202
|
+
|
|
142
203
|
export async function toUniformCredentialOfferRequest(
|
|
143
204
|
offer: CredentialOffer,
|
|
144
205
|
opts?: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CredentialRequestV1_0_08, OpenId4VCIVersion, UniformCredentialRequest } from '../types';
|
|
1
|
+
import { CredentialRequestV1_0_08, CredentialRequestV1_0_11, OpenId4VCIVersion, UniformCredentialRequest } from '../types';
|
|
2
2
|
|
|
3
3
|
import { getFormatForVersion } from './FormatUtils';
|
|
4
4
|
|
|
@@ -7,7 +7,14 @@ export function getTypesFromRequest(credentialRequest: UniformCredentialRequest,
|
|
|
7
7
|
if (credentialRequest.format === 'jwt_vc_json' || credentialRequest.format === 'jwt_vc') {
|
|
8
8
|
types = credentialRequest.types;
|
|
9
9
|
} else if (credentialRequest.format === 'jwt_vc_json-ld' || credentialRequest.format === 'ldp_vc') {
|
|
10
|
-
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
11
|
+
// @ts-ignore
|
|
12
|
+
types =
|
|
13
|
+
'credential_definition' in credentialRequest && credentialRequest.credential_definition
|
|
14
|
+
? // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
15
|
+
// @ts-ignore
|
|
16
|
+
credentialRequest.credential_definition.types
|
|
17
|
+
: credentialRequest.types;
|
|
11
18
|
} else if (credentialRequest.format === 'vc+sd-jwt') {
|
|
12
19
|
types = [credentialRequest.vct];
|
|
13
20
|
}
|
|
@@ -24,7 +31,7 @@ export function getTypesFromRequest(credentialRequest: UniformCredentialRequest,
|
|
|
24
31
|
export function getCredentialRequestForVersion(
|
|
25
32
|
credentialRequest: UniformCredentialRequest,
|
|
26
33
|
version: OpenId4VCIVersion,
|
|
27
|
-
): UniformCredentialRequest | CredentialRequestV1_0_08 {
|
|
34
|
+
): UniformCredentialRequest | CredentialRequestV1_0_08 | CredentialRequestV1_0_11 {
|
|
28
35
|
if (version === OpenId4VCIVersion.VER_1_0_08) {
|
|
29
36
|
const draft8Format = getFormatForVersion(credentialRequest.format, version);
|
|
30
37
|
const types = getTypesFromRequest(credentialRequest, { filterVerifiableCredential: true });
|
|
@@ -34,6 +41,14 @@ export function getCredentialRequestForVersion(
|
|
|
34
41
|
proof: credentialRequest.proof,
|
|
35
42
|
type: types[0],
|
|
36
43
|
} satisfies CredentialRequestV1_0_08;
|
|
44
|
+
/* } else if (version === OpenId4VCIVersion.VER_1_0_11) {
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
46
|
+
// @ts-ignore
|
|
47
|
+
const { credential_definition = undefined, ...requestv11 } = credentialRequest;
|
|
48
|
+
return {
|
|
49
|
+
...requestv11,
|
|
50
|
+
...credential_definition,
|
|
51
|
+
} as CredentialRequestV1_0_11;*/
|
|
37
52
|
}
|
|
38
53
|
|
|
39
54
|
return credentialRequest;
|
|
@@ -88,7 +88,7 @@ export function convertJsonToURI(
|
|
|
88
88
|
* - arrayTypeProperties: properties that can show up more that once
|
|
89
89
|
*/
|
|
90
90
|
export function convertURIToJsonObject(uri: string, opts?: DecodeURIAsJsonOpts): unknown {
|
|
91
|
-
if (!uri ||
|
|
91
|
+
if (!uri || (opts?.requiredProperties && !opts.requiredProperties?.every((p) => uri.includes(p)))) {
|
|
92
92
|
throw new Error(BAD_PARAMS);
|
|
93
93
|
}
|
|
94
94
|
const uriComponents = getURIComponentsAsArray(uri, opts?.arrayTypeProperties);
|
|
@@ -87,7 +87,7 @@ const openIdFetch = async <T>(
|
|
|
87
87
|
|
|
88
88
|
debug(`START fetching url: ${url}`);
|
|
89
89
|
if (body) {
|
|
90
|
-
debug(`Body:\r\n${JSON.stringify(body)}`);
|
|
90
|
+
debug(`Body:\r\n${typeof body == 'string' ? body : JSON.stringify(body)}`);
|
|
91
91
|
}
|
|
92
92
|
debug(`Headers:\r\n${JSON.stringify(payload.headers)}`);
|
|
93
93
|
const origResponse = await fetch(url, payload);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
+
AuthorizationServerMetadata,
|
|
2
3
|
CredentialIssuerMetadata,
|
|
3
4
|
CredentialOfferFormat,
|
|
4
5
|
CredentialSupported,
|
|
@@ -165,3 +166,21 @@ export function getIssuerDisplays(metadata: CredentialIssuerMetadata | IssuerMet
|
|
|
165
166
|
) ?? [];
|
|
166
167
|
return matchedDisplays.sort((item) => (item.locale ? opts?.prefLocales.indexOf(item.locale) ?? 1 : Number.MAX_VALUE));
|
|
167
168
|
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* TODO check again when WAL-617 is done to replace how we get the issuer name.
|
|
172
|
+
*/
|
|
173
|
+
export function getIssuerName(
|
|
174
|
+
url: string,
|
|
175
|
+
credentialIssuerMetadata?: Partial<AuthorizationServerMetadata> & (CredentialIssuerMetadata | IssuerMetadataV1_0_08),
|
|
176
|
+
): string {
|
|
177
|
+
if (credentialIssuerMetadata) {
|
|
178
|
+
const displays: Array<MetadataDisplay> = credentialIssuerMetadata ? getIssuerDisplays(credentialIssuerMetadata) : [];
|
|
179
|
+
for (const display of displays) {
|
|
180
|
+
if (display.name) {
|
|
181
|
+
return display.name;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return url;
|
|
186
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import SHA from 'sha.js';
|
|
2
|
+
import * as u8a from 'uint8arrays';
|
|
3
|
+
import { SupportedEncodings } from 'uint8arrays/to-string';
|
|
4
|
+
|
|
5
|
+
import { CodeChallengeMethod } from '../types';
|
|
6
|
+
|
|
7
|
+
import { randomBytes } from './randomBytes';
|
|
8
|
+
|
|
9
|
+
export const CODE_VERIFIER_DEFAULT_LENGTH = 128;
|
|
10
|
+
export const NONCE_LENGTH = 32;
|
|
11
|
+
|
|
12
|
+
export const generateRandomString = (length: number, encoding?: SupportedEncodings): string => {
|
|
13
|
+
return u8a.toString(randomBytes(length), encoding).slice(0, length);
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const generateNonce = (length?: number): string => {
|
|
17
|
+
return generateRandomString(length ?? NONCE_LENGTH);
|
|
18
|
+
};
|
|
19
|
+
export const generateCodeVerifier = (length?: number): string => {
|
|
20
|
+
const codeVerifier = generateRandomString(length ?? CODE_VERIFIER_DEFAULT_LENGTH, 'base64url');
|
|
21
|
+
assertValidCodeVerifier(codeVerifier);
|
|
22
|
+
return codeVerifier;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export const createCodeChallenge = (codeVerifier: string, codeChallengeMethod?: CodeChallengeMethod): string => {
|
|
26
|
+
if (codeChallengeMethod === CodeChallengeMethod.plain) {
|
|
27
|
+
return codeVerifier;
|
|
28
|
+
} else if (!codeChallengeMethod || codeChallengeMethod === CodeChallengeMethod.S256) {
|
|
29
|
+
return u8a.toString(SHA('sha256').update(codeVerifier).digest(), 'base64url');
|
|
30
|
+
} else {
|
|
31
|
+
// Just a precaution if a new method would be introduced
|
|
32
|
+
throw Error(`code challenge method ${codeChallengeMethod} not implemented`);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const assertValidCodeVerifier = (codeVerifier: string) => {
|
|
37
|
+
const length = codeVerifier.length;
|
|
38
|
+
if (length < 43) {
|
|
39
|
+
throw Error(`code_verifier should have a minimum length of 43; see rfc7636`);
|
|
40
|
+
} else if (length > 128) {
|
|
41
|
+
throw Error(`code_verifier should have a maximum length of 128; see rfc7636`);
|
|
42
|
+
}
|
|
43
|
+
};
|
package/lib/functions/index.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomBytes } from './randomBytes.js';
|
|
1
2
|
export * from './CredentialRequestUtil';
|
|
2
3
|
export * from './CredentialResponseUtil';
|
|
3
4
|
export * from './CredentialOfferUtil';
|
|
@@ -5,3 +6,7 @@ export * from './Encoding';
|
|
|
5
6
|
export * from './TypeConversionUtils';
|
|
6
7
|
export * from './IssuerMetadataUtils';
|
|
7
8
|
export * from './FormatUtils';
|
|
9
|
+
export * from './HttpUtils';
|
|
10
|
+
export * from './AuthorizationResponseUtil';
|
|
11
|
+
export { randomBytes };
|
|
12
|
+
export * from './RandomUtils';
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// limit of Crypto.getRandomValues()
|
|
4
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Crypto/getRandomValues
|
|
5
|
+
const MAX_BYTES = 65536;
|
|
6
|
+
|
|
7
|
+
// Node supports requesting up to this number of bytes
|
|
8
|
+
// https://github.com/nodejs/node/blob/master/lib/internal/crypto/random.js#L48
|
|
9
|
+
const MAX_UINT32 = 4294967295;
|
|
10
|
+
|
|
11
|
+
function oldBrowser() {
|
|
12
|
+
throw new Error('Secure random number generation is not supported by this browser.\nUse Chrome, Firefox or Internet Explorer 11');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// eslint-disable-next-line no-undef
|
|
16
|
+
const _global = typeof globalThis !== 'undefined' ? globalThis : global;
|
|
17
|
+
|
|
18
|
+
let crypto = _global.crypto || _global.msCrypto;
|
|
19
|
+
if (!crypto) {
|
|
20
|
+
try {
|
|
21
|
+
// eslint-disable-next-line no-undef
|
|
22
|
+
crypto = require('crypto');
|
|
23
|
+
} catch (err) {
|
|
24
|
+
throw Error('crypto module is not available');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (crypto && crypto.getRandomValues) {
|
|
29
|
+
// eslint-disable-next-line no-undef
|
|
30
|
+
module.exports = randomBytes;
|
|
31
|
+
} else {
|
|
32
|
+
// eslint-disable-next-line no-undef
|
|
33
|
+
module.exports = oldBrowser;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function randomBytes(size) {
|
|
37
|
+
// phantomjs needs to throw
|
|
38
|
+
if (size > MAX_UINT32) throw new Error('requested too many random bytes');
|
|
39
|
+
|
|
40
|
+
// eslint-disable-next-line no-undef
|
|
41
|
+
const bytes = Buffer.allocUnsafe(size);
|
|
42
|
+
|
|
43
|
+
if (size > 0) {
|
|
44
|
+
// getRandomValues fails on IE if size == 0
|
|
45
|
+
if (size > MAX_BYTES) {
|
|
46
|
+
// this is the max bytes crypto.getRandomValues
|
|
47
|
+
// can do at once see https://developer.mozilla.org/en-US/docs/Web/API/window.crypto.getRandomValues
|
|
48
|
+
for (let generated = 0; generated < size; generated += MAX_BYTES) {
|
|
49
|
+
// buffer.slice automatically checks if the end is past the end of
|
|
50
|
+
// the buffer so we don't have to here
|
|
51
|
+
crypto.getRandomValues(bytes.slice(generated, generated + MAX_BYTES));
|
|
52
|
+
}
|
|
53
|
+
} else {
|
|
54
|
+
crypto.getRandomValues(bytes);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return Uint8Array.from(bytes);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// eslint-disable-next-line no-undef
|
|
61
|
+
module.exports = { randomBytes };
|
|
@@ -70,7 +70,9 @@ export interface CommonAuthorizationRequest {
|
|
|
70
70
|
/**
|
|
71
71
|
* string type added for conformity with our previous code in the client
|
|
72
72
|
*/
|
|
73
|
-
export type AuthorizationDetails =
|
|
73
|
+
export type AuthorizationDetails =
|
|
74
|
+
| (CommonAuthorizationDetails & (AuthorizationDetailsJwtVcJson | AuthorizationDetailsJwtVcJsonLdAndLdpVc | AuthorizationDetailsSdJwtVc))
|
|
75
|
+
| string;
|
|
74
76
|
|
|
75
77
|
export type AuthorizationRequest = AuthorizationRequestJwtVcJson | AuthorizationRequestJwtVcJsonLdAndLdpVc | AuthorizationRequestSdJwtVc;
|
|
76
78
|
|
|
@@ -86,6 +88,16 @@ export interface AuthorizationRequestSdJwtVc extends CommonAuthorizationRequest
|
|
|
86
88
|
authorization_details?: AuthorizationDetailsSdJwtVc[];
|
|
87
89
|
}
|
|
88
90
|
|
|
91
|
+
/*
|
|
92
|
+
export interface AuthDetails {
|
|
93
|
+
type: 'openid_credential' | string;
|
|
94
|
+
locations?: string | string[];
|
|
95
|
+
format: CredentialFormat | CredentialFormat[];
|
|
96
|
+
|
|
97
|
+
[s: string]: unknown;
|
|
98
|
+
}
|
|
99
|
+
*/
|
|
100
|
+
|
|
89
101
|
export interface CommonAuthorizationDetails {
|
|
90
102
|
/**
|
|
91
103
|
* REQUIRED. JSON string that determines the authorization details type.
|
|
@@ -159,8 +171,8 @@ export enum ResponseType {
|
|
|
159
171
|
}
|
|
160
172
|
|
|
161
173
|
export enum CodeChallengeMethod {
|
|
162
|
-
|
|
163
|
-
|
|
174
|
+
plain = 'plain',
|
|
175
|
+
S256 = 'S256',
|
|
164
176
|
}
|
|
165
177
|
|
|
166
178
|
export interface AuthorizationServerOpts {
|
|
@@ -176,6 +188,9 @@ export interface IssuerOpts {
|
|
|
176
188
|
fetchMetadata?: boolean;
|
|
177
189
|
}
|
|
178
190
|
|
|
191
|
+
export interface AccessTokenFromAuthorizationResponseOpts extends AccessTokenRequestOpts {
|
|
192
|
+
authorizationResponse: AuthorizationResponse;
|
|
193
|
+
}
|
|
179
194
|
export interface AccessTokenRequestOpts {
|
|
180
195
|
credentialOffer?: UniformCredentialOffer;
|
|
181
196
|
credentialIssuer?: string;
|
|
@@ -187,22 +202,72 @@ export interface AccessTokenRequestOpts {
|
|
|
187
202
|
pin?: string; // Pin-number. Only used when required
|
|
188
203
|
}
|
|
189
204
|
|
|
190
|
-
export interface AuthorizationRequestOpts {
|
|
205
|
+
/*export interface AuthorizationRequestOpts {
|
|
191
206
|
clientId: string;
|
|
192
207
|
codeChallenge: string;
|
|
193
208
|
codeChallengeMethod: CodeChallengeMethod;
|
|
194
209
|
authorizationDetails?: AuthorizationDetails[];
|
|
195
210
|
redirectUri: string;
|
|
196
211
|
scope?: string;
|
|
212
|
+
}*/
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Determinse whether PAR should be used when supported
|
|
216
|
+
*
|
|
217
|
+
* REQUIRE: Require PAR, if AS does not support it throw an error
|
|
218
|
+
* AUTO: Use PAR is the AS supports it, otherwise construct a reqular URI,
|
|
219
|
+
* NEVER: Do not use PAR even if the AS supports it (not recommended)
|
|
220
|
+
*/
|
|
221
|
+
export enum PARMode {
|
|
222
|
+
REQUIRE,
|
|
223
|
+
AUTO,
|
|
224
|
+
NEVER,
|
|
197
225
|
}
|
|
198
226
|
|
|
199
|
-
|
|
200
|
-
|
|
227
|
+
/**
|
|
228
|
+
* Optional options to provide PKCE params like code verifier and challenge yourself, or to disable PKCE altogether. If not provide PKCE will still be used! If individual params are not provide, they will be generated/calculated
|
|
229
|
+
*/
|
|
230
|
+
export interface PKCEOpts {
|
|
231
|
+
/**
|
|
232
|
+
* PKCE is enabled by default even if you do not provide these options. Set this to true to disable PKCE
|
|
233
|
+
*/
|
|
234
|
+
disabled?: boolean;
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Provide a code_challenge, otherwise it will be calculated using the code_verifier and method
|
|
238
|
+
*/
|
|
239
|
+
codeChallenge?: string;
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* The code_challenge_method, should always by S256
|
|
243
|
+
*/
|
|
244
|
+
codeChallengeMethod?: CodeChallengeMethod;
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Provide a code_verifier, otherwise it will be generated
|
|
248
|
+
*/
|
|
249
|
+
codeVerifier?: string;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export interface AuthorizationRequestOpts {
|
|
253
|
+
clientId?: string;
|
|
254
|
+
pkce?: PKCEOpts;
|
|
255
|
+
parMode?: PARMode;
|
|
256
|
+
authorizationDetails?: AuthorizationDetails | AuthorizationDetails[];
|
|
257
|
+
redirectUri?: string;
|
|
258
|
+
scope?: string;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
export interface AuthorizationResponse {
|
|
201
262
|
code: string;
|
|
202
263
|
scope?: string;
|
|
203
264
|
state?: string;
|
|
204
265
|
}
|
|
205
266
|
|
|
267
|
+
export interface AuthorizationGrantResponse extends AuthorizationResponse {
|
|
268
|
+
grant_type: string;
|
|
269
|
+
}
|
|
270
|
+
|
|
206
271
|
export interface AccessTokenRequest {
|
|
207
272
|
client_id?: string;
|
|
208
273
|
code?: string;
|
|
@@ -18,6 +18,7 @@ export interface CredentialResponse {
|
|
|
18
18
|
|
|
19
19
|
export interface CredentialOfferRequestWithBaseUrl extends UniformCredentialOfferRequest {
|
|
20
20
|
scheme: string;
|
|
21
|
+
clientId?: string;
|
|
21
22
|
baseUrl: string;
|
|
22
23
|
userPinRequired: boolean;
|
|
23
24
|
issuerState?: string;
|
|
@@ -26,7 +27,9 @@ export interface CredentialOfferRequestWithBaseUrl extends UniformCredentialOffe
|
|
|
26
27
|
|
|
27
28
|
export type CredentialOffer = CredentialOfferV1_0_09 | CredentialOfferV1_0_11;
|
|
28
29
|
|
|
29
|
-
export type CredentialOfferPayload = CredentialOfferPayloadV1_0_08 | CredentialOfferPayloadV1_0_09 | CredentialOfferPayloadV1_0_11
|
|
30
|
+
export type CredentialOfferPayload = (CredentialOfferPayloadV1_0_08 | CredentialOfferPayloadV1_0_09 | CredentialOfferPayloadV1_0_11) & {
|
|
31
|
+
[x: string]: any;
|
|
32
|
+
};
|
|
30
33
|
|
|
31
34
|
export interface AssertedUniformCredentialOffer extends UniformCredentialOffer {
|
|
32
35
|
credential_offer: UniformCredentialOfferPayload;
|
|
@@ -107,6 +110,7 @@ export interface JWK extends BaseJWK {
|
|
|
107
110
|
x5t?: string;
|
|
108
111
|
'x5t#S256'?: string;
|
|
109
112
|
x5u?: string;
|
|
113
|
+
|
|
110
114
|
[propName: string]: unknown;
|
|
111
115
|
}
|
|
112
116
|
|
|
@@ -147,6 +151,7 @@ export interface JWSHeaderParameters extends JoseHeaderParameters {
|
|
|
147
151
|
alg?: Alg | string; // REQUIRED by the JWT signer
|
|
148
152
|
b64?: boolean;
|
|
149
153
|
crit?: string[];
|
|
154
|
+
|
|
150
155
|
[propName: string]: unknown;
|
|
151
156
|
}
|
|
152
157
|
|
|
@@ -172,6 +177,7 @@ export interface JWTPayload {
|
|
|
172
177
|
|
|
173
178
|
export type JWTSignerCallback = (jwt: Jwt, kid?: string) => Promise<string>;
|
|
174
179
|
export type JWTVerifyCallback<DIDDoc> = (args: { jwt: string; kid?: string }) => Promise<JwtVerifyResult<DIDDoc>>;
|
|
180
|
+
|
|
175
181
|
export interface JwtVerifyResult<DIDDoc> {
|
|
176
182
|
jwt: Jwt;
|
|
177
183
|
kid?: string;
|
|
@@ -51,6 +51,7 @@ export interface CredentialIssuerMetadataOpts {
|
|
|
51
51
|
credentials_supported: CredentialSupported[]; // REQUIRED. A JSON array containing a list of JSON objects, each of them representing metadata about a separate credential type that the Credential Issuer can issue. The JSON objects in the array MUST conform to the structure of the Section 10.2.3.1.
|
|
52
52
|
credential_issuer: string; // REQUIRED. The Credential Issuer's identifier.
|
|
53
53
|
authorization_server?: string; // OPTIONAL. Identifier of the OAuth 2.0 Authorization Server (as defined in [RFC8414]) the Credential Issuer relies on for authorization. If this element is omitted, the entity providing the Credential Issuer is also acting as the AS, i.e. the Credential Issuer's identifier is used as the OAuth 2.0 Issuer value to obtain the Authorization Server metadata as per [RFC8414].
|
|
54
|
+
// authorization_servers?: string[]; // OPTIONAL. Array of strings that identify the OAuth 2.0 Authorization Servers (as defined in [RFC8414]) the Credential Issuer relies on for authorization. If this element is omitted, the entity providing the Credential Issuer is also acting as the AS, i.e. the Credential Issuer's identifier is used as the OAuth 2.0 Issuer value to obtain the Authorization Server metadata as per [RFC8414].
|
|
54
55
|
token_endpoint?: string;
|
|
55
56
|
display?: MetadataDisplay[]; // An array of objects, where each object contains display properties of a Credential Issuer for a certain language. Below is a non-exhaustive list of valid parameters that MAY be included:
|
|
56
57
|
credential_supplier_config?: CredentialSupplierConfig;
|
|
@@ -58,9 +59,16 @@ export interface CredentialIssuerMetadataOpts {
|
|
|
58
59
|
|
|
59
60
|
// For now we extend the opts above. Only difference is that the credential endpoint is optional in the Opts, as it can come from other sources. The value is however required in the eventual Issuer Metadata
|
|
60
61
|
export interface CredentialIssuerMetadata extends CredentialIssuerMetadataOpts, Partial<AuthorizationServerMetadata> {
|
|
62
|
+
authorization_servers?: string[]; // OPTIONAL. Array of strings that identify the OAuth 2.0 Authorization Servers (as defined in [RFC8414]) the Credential Issuer relies on for authorization. If this element is omitted, the entity providing the Credential Issuer is also acting as the AS, i.e. the Credential Issuer's identifier is used as the OAuth 2.0 Issuer value to obtain the Authorization Server metadata as per [RFC8414].
|
|
61
63
|
credential_endpoint: string; // REQUIRED. URL of the Credential Issuer's Credential Endpoint. This URL MUST use the https scheme and MAY contain port, path and query parameter components.
|
|
64
|
+
credential_response_encryption_alg_values_supported?: string; // OPTIONAL. Array containing a list of the JWE [RFC7516] encryption algorithms (alg values) [RFC7518] supported by the Credential and/or Batch Credential Endpoint to encode the Credential or Batch Credential Response in a JWT [RFC7519].
|
|
65
|
+
credential_response_encryption_enc_values_supported?: string; //OPTIONAL. Array containing a list of the JWE [RFC7516] encryption algorithms (enc values) [RFC7518] supported by the Credential and/or Batch Credential Endpoint to encode the Credential or Batch Credential Response in a JWT [RFC7519].
|
|
66
|
+
require_credential_response_encryption?: boolean; //OPTIONAL. Boolean value specifying whether the Credential Issuer requires additional encryption on top of TLS for the Credential Response and expects encryption parameters to be present in the Credential Request and/or Batch Credential Request, with true indicating support. When the value is true, credential_response_encryption_alg_values_supported parameter MUST also be provided. If omitted, the default value is false.
|
|
67
|
+
credential_identifiers_supported?: boolean; // OPTIONAL. Boolean value specifying whether the Credential Issuer supports returning credential_identifiers parameter in the authorization_details Token Response parameter, with true indicating support. If omitted, the default value is false.
|
|
62
68
|
}
|
|
63
69
|
|
|
70
|
+
// For now we extend the opts above. Only difference is that the credential endpoint is optional in the Opts, as it can come from other sources. The value is however required in the eventual Issuer Metadata
|
|
71
|
+
|
|
64
72
|
export interface CredentialSupportedBrief {
|
|
65
73
|
cryptographic_binding_methods_supported?: string[]; // OPTIONAL. Array of case sensitive strings that identify how the Credential is bound to the identifier of the End-User who possesses the Credential
|
|
66
74
|
cryptographic_suites_supported?: string[]; // OPTIONAL. Array of case sensitive strings that identify the cryptographic suites that are supported for the cryptographic_binding_methods_supported
|
|
@@ -229,6 +237,12 @@ export interface GrantAuthorizationCode {
|
|
|
229
237
|
* Authorization Request with the Credential Issuer to a context set up during previous steps.
|
|
230
238
|
*/
|
|
231
239
|
issuer_state?: string;
|
|
240
|
+
|
|
241
|
+
// v12 feature
|
|
242
|
+
/**
|
|
243
|
+
* OPTIONAL string that the Wallet can use to identify the Authorization Server to use with this grant type when authorization_servers parameter in the Credential Issuer metadata has multiple entries. MUST NOT be used otherwise. The value of this parameter MUST match with one of the values in the authorization_servers array obtained from the Credential Issuer metadata
|
|
244
|
+
*/
|
|
245
|
+
authorization_server?: string;
|
|
232
246
|
}
|
|
233
247
|
|
|
234
248
|
export interface GrantUrnIetf {
|
|
@@ -241,6 +255,18 @@ export interface GrantUrnIetf {
|
|
|
241
255
|
* in a Pre-Authorized Code Flow. Default is false.
|
|
242
256
|
*/
|
|
243
257
|
user_pin_required: boolean;
|
|
258
|
+
|
|
259
|
+
//v12
|
|
260
|
+
/**
|
|
261
|
+
* OPTIONAL. The minimum amount of time in seconds that the Wallet SHOULD wait between polling requests to the token endpoint (in case the Authorization Server responds with error code authorization_pending - see Section 6.3). If no value is provided, Wallets MUST use 5 as the default.
|
|
262
|
+
*/
|
|
263
|
+
interval?: number;
|
|
264
|
+
|
|
265
|
+
// v12 feature
|
|
266
|
+
/**
|
|
267
|
+
* OPTIONAL string that the Wallet can use to identify the Authorization Server to use with this grant type when authorization_servers parameter in the Credential Issuer metadata has multiple entries. MUST NOT be used otherwise. The value of this parameter MUST match with one of the values in the authorization_servers array obtained from the Credential Issuer metadata
|
|
268
|
+
*/
|
|
269
|
+
authorization_server?: string;
|
|
244
270
|
}
|
|
245
271
|
|
|
246
272
|
export const PRE_AUTH_CODE_LITERAL = 'pre-authorized_code';
|
|
@@ -2,13 +2,15 @@ import { AuthorizationDetailsJwtVcJson, CommonAuthorizationRequest } from './Aut
|
|
|
2
2
|
import {
|
|
3
3
|
CommonCredentialRequest,
|
|
4
4
|
CredentialDataSupplierInput,
|
|
5
|
+
CredentialIssuerMetadataOpts,
|
|
5
6
|
CredentialOfferFormat,
|
|
6
7
|
CredentialRequestJwtVcJson,
|
|
7
|
-
CredentialRequestJwtVcJsonLdAndLdpVc,
|
|
8
8
|
CredentialRequestSdJwtVc,
|
|
9
9
|
Grant,
|
|
10
|
+
JsonLdIssuerCredentialDefinition,
|
|
10
11
|
} from './Generic.types';
|
|
11
12
|
import { QRCodeOpts } from './QRCode.types';
|
|
13
|
+
import { AuthorizationServerMetadata } from './ServerMetadata';
|
|
12
14
|
|
|
13
15
|
export interface CredentialOfferV1_0_11 {
|
|
14
16
|
credential_offer?: CredentialOfferPayloadV1_0_11;
|
|
@@ -48,10 +50,25 @@ export interface CredentialOfferPayloadV1_0_11 {
|
|
|
48
50
|
* using the respective metadata. When multiple grants are present, it's at the Wallet's discretion which one to use.
|
|
49
51
|
*/
|
|
50
52
|
grants?: Grant;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Some implementations might include a client_id in the offer. For instance EBSI in a same-device flow. (Cross-device tucks it in the state JWT)
|
|
56
|
+
*/
|
|
57
|
+
client_id?: string;
|
|
51
58
|
}
|
|
52
59
|
|
|
53
60
|
export type CredentialRequestV1_0_11 = CommonCredentialRequest &
|
|
54
|
-
(CredentialRequestJwtVcJson |
|
|
61
|
+
(CredentialRequestJwtVcJson | CredentialRequestJwtVcJsonLdAndLdpVcV1_0_11 | CredentialRequestSdJwtVc);
|
|
62
|
+
|
|
63
|
+
export interface CredentialRequestJwtVcJsonLdAndLdpVcV1_0_11
|
|
64
|
+
extends CommonCredentialRequest,
|
|
65
|
+
Pick<JsonLdIssuerCredentialDefinition, 'credentialSubject' | 'types'> {
|
|
66
|
+
format: 'ldp_vc' | 'jwt_vc_json-ld';
|
|
67
|
+
}
|
|
68
|
+
export interface CredentialIssuerMetadataV1_0_11 extends CredentialIssuerMetadataOpts, Partial<AuthorizationServerMetadata> {
|
|
69
|
+
credential_endpoint: string; // REQUIRED. URL of the Credential Issuer's Credential Endpoint. This URL MUST use the https scheme and MAY contain port, path and query parameter components.
|
|
70
|
+
authorization_server?: string;
|
|
71
|
+
}
|
|
55
72
|
|
|
56
73
|
export interface AuthorizationRequestV1_0_11 extends AuthorizationDetailsJwtVcJson, AuthorizationDetailsJwtVcJson {
|
|
57
74
|
issuer_state?: string;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { CommonCredentialRequest, CredentialRequestJwtVcJson, CredentialRequestJwtVcJsonLdAndLdpVc, CredentialRequestSdJwtVc } from './Generic.types';
|
|
2
|
+
|
|
3
|
+
export type CredentialRequestV1_0_12 = CommonCredentialRequest &
|
|
4
|
+
(CredentialRequestJwtVcJson | CredentialRequestJwtVcJsonLdAndLdpVc | CredentialRequestSdJwtVc);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sphereon/oid4vci-common",
|
|
3
|
-
"version": "0.8.2-next.
|
|
3
|
+
"version": "0.8.2-next.87+9f0679e",
|
|
4
4
|
"description": "OpenID 4 Verifiable Credential Issuance Common Types",
|
|
5
5
|
"source": "lib/index.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -12,12 +12,23 @@
|
|
|
12
12
|
"dependencies": {
|
|
13
13
|
"@sphereon/ssi-types": "^0.18.1",
|
|
14
14
|
"cross-fetch": "^3.1.8",
|
|
15
|
-
"jwt-decode": "^3.1.2"
|
|
15
|
+
"jwt-decode": "^3.1.2",
|
|
16
|
+
"sha.js": "^2.4.11",
|
|
17
|
+
"uint8arrays": "3.1.1"
|
|
16
18
|
},
|
|
17
19
|
"devDependencies": {
|
|
18
20
|
"@types/jest": "^29.5.3",
|
|
21
|
+
"@types/sha.js": "^2.4.4",
|
|
19
22
|
"typescript": "5.3.3"
|
|
20
23
|
},
|
|
24
|
+
"peerDependencies": {
|
|
25
|
+
"msrcrypto": "^1.5.8"
|
|
26
|
+
},
|
|
27
|
+
"peerDependenciesMeta": {
|
|
28
|
+
"msrcrypto": {
|
|
29
|
+
"optional": true
|
|
30
|
+
}
|
|
31
|
+
},
|
|
21
32
|
"engines": {
|
|
22
33
|
"node": ">=18"
|
|
23
34
|
},
|
|
@@ -46,5 +57,5 @@
|
|
|
46
57
|
"publishConfig": {
|
|
47
58
|
"access": "public"
|
|
48
59
|
},
|
|
49
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "9f0679e6cbf0b0ba7f7d4f8ecc2263981d4ef80e"
|
|
50
61
|
}
|