@pagopa/io-react-native-wallet 0.13.1 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. package/lib/commonjs/cie/component.js +180 -0
  2. package/lib/commonjs/cie/component.js.map +1 -0
  3. package/lib/commonjs/cie/error.js +44 -0
  4. package/lib/commonjs/cie/error.js.map +1 -0
  5. package/lib/commonjs/cie/index.js +32 -0
  6. package/lib/commonjs/cie/index.js.map +1 -0
  7. package/lib/commonjs/cie/manager.js +142 -0
  8. package/lib/commonjs/cie/manager.js.map +1 -0
  9. package/lib/commonjs/client/index.js +5 -2
  10. package/lib/commonjs/client/index.js.map +1 -1
  11. package/lib/commonjs/credential/issuance/04-complete-user-authorization.js +144 -19
  12. package/lib/commonjs/credential/issuance/04-complete-user-authorization.js.map +1 -1
  13. package/lib/commonjs/credential/issuance/07-verify-and-parse-credential.js +12 -4
  14. package/lib/commonjs/credential/issuance/07-verify-and-parse-credential.js.map +1 -1
  15. package/lib/commonjs/credential/issuance/index.js +18 -0
  16. package/lib/commonjs/credential/issuance/index.js.map +1 -1
  17. package/lib/commonjs/credential/issuance/types.js +9 -1
  18. package/lib/commonjs/credential/issuance/types.js.map +1 -1
  19. package/lib/commonjs/index.js +3 -1
  20. package/lib/commonjs/index.js.map +1 -1
  21. package/lib/commonjs/trust/types.js +5 -3
  22. package/lib/commonjs/trust/types.js.map +1 -1
  23. package/lib/commonjs/utils/decoder.js +28 -19
  24. package/lib/commonjs/utils/decoder.js.map +1 -1
  25. package/lib/module/cie/component.js +171 -0
  26. package/lib/module/cie/component.js.map +1 -0
  27. package/lib/module/cie/error.js +36 -0
  28. package/lib/module/cie/error.js.map +1 -0
  29. package/lib/module/cie/index.js +4 -0
  30. package/lib/module/cie/index.js.map +1 -0
  31. package/lib/module/cie/manager.js +133 -0
  32. package/lib/module/cie/manager.js.map +1 -0
  33. package/lib/module/client/index.js +5 -2
  34. package/lib/module/client/index.js.map +1 -1
  35. package/lib/module/credential/issuance/04-complete-user-authorization.js +141 -18
  36. package/lib/module/credential/issuance/04-complete-user-authorization.js.map +1 -1
  37. package/lib/module/credential/issuance/07-verify-and-parse-credential.js +12 -4
  38. package/lib/module/credential/issuance/07-verify-and-parse-credential.js.map +1 -1
  39. package/lib/module/credential/issuance/index.js +2 -2
  40. package/lib/module/credential/issuance/index.js.map +1 -1
  41. package/lib/module/credential/issuance/types.js +7 -0
  42. package/lib/module/credential/issuance/types.js.map +1 -1
  43. package/lib/module/index.js +2 -1
  44. package/lib/module/index.js.map +1 -1
  45. package/lib/module/trust/types.js +5 -3
  46. package/lib/module/trust/types.js.map +1 -1
  47. package/lib/module/utils/decoder.js +28 -19
  48. package/lib/module/utils/decoder.js.map +1 -1
  49. package/lib/typescript/cie/component.d.ts +46 -0
  50. package/lib/typescript/cie/component.d.ts.map +1 -0
  51. package/lib/typescript/cie/error.d.ts +31 -0
  52. package/lib/typescript/cie/error.d.ts.map +1 -0
  53. package/lib/typescript/cie/index.d.ts +4 -0
  54. package/lib/typescript/cie/index.d.ts.map +1 -0
  55. package/lib/typescript/cie/manager.d.ts +5 -0
  56. package/lib/typescript/cie/manager.d.ts.map +1 -0
  57. package/lib/typescript/client/index.d.ts.map +1 -1
  58. package/lib/typescript/credential/issuance/04-complete-user-authorization.d.ts +48 -1
  59. package/lib/typescript/credential/issuance/04-complete-user-authorization.d.ts.map +1 -1
  60. package/lib/typescript/credential/issuance/07-verify-and-parse-credential.d.ts +1 -0
  61. package/lib/typescript/credential/issuance/07-verify-and-parse-credential.d.ts.map +1 -1
  62. package/lib/typescript/credential/issuance/index.d.ts +3 -3
  63. package/lib/typescript/credential/issuance/index.d.ts.map +1 -1
  64. package/lib/typescript/credential/issuance/types.d.ts +10 -0
  65. package/lib/typescript/credential/issuance/types.d.ts.map +1 -1
  66. package/lib/typescript/index.d.ts +2 -1
  67. package/lib/typescript/index.d.ts.map +1 -1
  68. package/lib/typescript/trust/index.d.ts +14 -14
  69. package/lib/typescript/trust/types.d.ts +142 -142
  70. package/lib/typescript/trust/types.d.ts.map +1 -1
  71. package/lib/typescript/utils/decoder.d.ts.map +1 -1
  72. package/package.json +6 -2
  73. package/src/cie/component.tsx +216 -0
  74. package/src/cie/error.ts +58 -0
  75. package/src/cie/index.ts +4 -0
  76. package/src/cie/manager.ts +183 -0
  77. package/src/client/index.ts +4 -1
  78. package/src/credential/issuance/04-complete-user-authorization.ts +216 -21
  79. package/src/credential/issuance/07-verify-and-parse-credential.ts +14 -6
  80. package/src/credential/issuance/index.ts +10 -0
  81. package/src/credential/issuance/types.ts +7 -0
  82. package/src/index.ts +2 -0
  83. package/src/trust/types.ts +8 -6
  84. package/src/utils/decoder.ts +28 -19
  85. package/lib/commonjs/credential/issuance/03-start-credential-issuance.js +0 -287
  86. package/lib/commonjs/credential/issuance/03-start-credential-issuance.js.map +0 -1
  87. package/lib/module/credential/issuance/03-start-credential-issuance.js +0 -276
  88. package/lib/module/credential/issuance/03-start-credential-issuance.js.map +0 -1
  89. package/lib/typescript/credential/issuance/03-start-credential-issuance.d.ts +0 -41
  90. package/lib/typescript/credential/issuance/03-start-credential-issuance.d.ts.map +0 -1
  91. package/src/credential/issuance/03-start-credential-issuance.ts +0 -407
@@ -4,12 +4,26 @@ import {
4
4
  type AuthorizationContext,
5
5
  type AuthorizationResult,
6
6
  } from "../../utils/auth";
7
- import { until, type Out } from "../../utils/misc";
7
+ import { hasStatus, until, type Out } from "../../utils/misc";
8
8
  import type { StartUserAuthorization } from "./03-start-user-authorization";
9
9
  import parseUrl from "parse-url";
10
- import { AuthorizationError, AuthorizationIdpError } from "../../utils/errors";
10
+ import {
11
+ AuthorizationError,
12
+ AuthorizationIdpError,
13
+ ValidationFailed,
14
+ } from "../../utils/errors";
11
15
  import type { EvaluateIssuerTrust } from "./02-evaluate-issuer-trust";
12
16
  import { Linking } from "react-native";
17
+ import {
18
+ decode,
19
+ encodeBase64,
20
+ SignJWT,
21
+ type CryptoContext,
22
+ } from "@pagopa/io-react-native-jwt";
23
+ import { RequestObject } from "../presentation/types";
24
+ import uuid from "react-native-uuid";
25
+ import { ResponseUriResultShape } from "./types";
26
+ import { getJwtFromFormPost } from "../../../src/utils/decoder";
13
27
 
14
28
  /**
15
29
  * The interface of the phase to complete User authorization via strong identification when the response mode is "query" and the request credential is a PersonIdentificationData.
@@ -23,6 +37,24 @@ export type CompleteUserAuthorizationWithQueryMode = (
23
37
  authorizationContext?: AuthorizationContext
24
38
  ) => Promise<AuthorizationResult>;
25
39
 
40
+ export type CompleteUserAuthorizationWithFormPostJwtMode = (
41
+ requestObject: Out<GetRequestedCredentialToBePresented>,
42
+ context: {
43
+ wiaCryptoContext: CryptoContext;
44
+ pidCryptoContext: CryptoContext;
45
+ pid: string;
46
+ walletInstanceAttestation: string;
47
+ appFetch?: GlobalFetch["fetch"];
48
+ }
49
+ ) => Promise<AuthorizationResult>;
50
+
51
+ export type GetRequestedCredentialToBePresented = (
52
+ issuerRequestUri: Out<StartUserAuthorization>["issuerRequestUri"],
53
+ clientId: Out<StartUserAuthorization>["clientId"],
54
+ issuerConf: Out<EvaluateIssuerTrust>["issuerConf"],
55
+ appFetch?: GlobalFetch["fetch"]
56
+ ) => Promise<RequestObject>;
57
+
26
58
  /**
27
59
  * WARNING: This function must be called after {@link startUserAuthorization}. The next function to be called is {@link authorizeAccess}.
28
60
  * The interface of the phase to complete User authorization via strong identification when the response mode is "query" and the request credential is a PersonIdentificationData.
@@ -49,11 +81,6 @@ export const completeUserAuthorizationWithQueryMode: CompleteUserAuthorizationWi
49
81
  redirectUri,
50
82
  authorizationContext
51
83
  ) => {
52
- /**
53
- * Starts the authorization flow which dependes on the response mode and the request credential.
54
- * If the response mode is "query" the authorization flow is handled differently via the authorization context which opens an in-app browser capable of catching the redirectSchema.
55
- * The form_post.jwt mode is not currently supported.
56
- */
57
84
  const authzRequestEndpoint =
58
85
  issuerConf.oauth_authorization_server.authorization_endpoint;
59
86
  const params = new URLSearchParams({
@@ -97,22 +124,190 @@ export const completeUserAuthorizationWithQueryMode: CompleteUserAuthorizationWi
97
124
  }
98
125
  }
99
126
 
100
- const urlParse = parseUrl(authRedirectUrl);
101
- const authRes = AuthorizationResultShape.safeParse(urlParse.query);
102
- if (!authRes.success) {
103
- const authErr = AuthorizationErrorShape.safeParse(urlParse.query);
104
- if (!authErr.success) {
105
- throw new AuthorizationError(authRes.error.message); // an error occured while parsing the result and the error
106
- }
107
- throw new AuthorizationIdpError(
108
- authErr.data.error,
109
- authErr.data.error_description
127
+ const query = parseUrl(authRedirectUrl).query;
128
+ return parseAuthroizationResponse(query);
129
+ };
130
+
131
+ /**
132
+ * WARNING: This function must be called after {@link startUserAuthorization}. The next function to be called is {@link completeUserAuthorizationWithFormPostJwtMode}.
133
+ * The interface of the phase to complete User authorization via presentation of existing credentials when the response mode is "form_post.jwt".
134
+ * It is used as a first step to complete the user authorization by obtaining the requested credential to be presented from the authorization server.
135
+ * The information is obtained by performing a GET request to the authorization endpoint with request_uri and client_id parameters.
136
+ * @param issuerRequestUri the URI of the issuer where the request is sent
137
+ * @param clientId Identifies the current client across all the requests of the issuing flow returned by {@link startUserAuthorization}
138
+ * @param issuerConf The issuer configuration returned by {@link evaluateIssuerTrust}
139
+ * @param appFetch (optional) fetch api implementation. Default: built-in fetch
140
+ * @throws {ValidationFailed} if an error while validating the response
141
+ * @returns the request object which contains the credential to be presented in order to obtain the requested credential
142
+ */
143
+ export const getRequestedCredentialToBePresented: GetRequestedCredentialToBePresented =
144
+ async (issuerRequestUri, clientId, issuerConf, appFetch = fetch) => {
145
+ const authzRequestEndpoint =
146
+ issuerConf.oauth_authorization_server.authorization_endpoint;
147
+ const params = new URLSearchParams({
148
+ client_id: clientId,
149
+ request_uri: issuerRequestUri,
150
+ });
151
+
152
+ const requestObject = await appFetch(
153
+ `${authzRequestEndpoint}?${params.toString()}`,
154
+ { method: "GET" }
155
+ )
156
+ .then(hasStatus(200))
157
+ .then((res) => res.text())
158
+ .then((jws) => decode(jws))
159
+ .then((reqObj) => RequestObject.safeParse(reqObj.payload));
160
+
161
+ if (!requestObject.success) {
162
+ throw new ValidationFailed(
163
+ "Request Object validation failed",
164
+ requestObject.error.message
110
165
  );
111
166
  }
112
- return authRes.data;
167
+ return requestObject.data;
113
168
  };
114
169
 
115
- // TODO: SIW-1120 implement generic credential issuance flow
116
- export const completeUserAuthorizationWithFormPostJwtMode = () => {
117
- throw new Error("Not implemented");
170
+ /**
171
+ * WARNING: This function must be called after {@link startUserAuthorization}. The next function to be called is {@link completeUserAuthorizationWithFormPostJwtMode}.
172
+ * The interface of the phase to complete User authorization via presentation of existing credentials when the response mode is "form_post.jwt".
173
+ * It is used as a first step to complete the user authorization by obtaining the requested credential to be presented from the authorization server.
174
+ * The information is obtained by performing a GET request to the authorization endpoint with request_uri and client_id parameters.
175
+ * @param issuerRequestUri the URI of the issuer where the request is sent
176
+ * @param clientId Identifies the current client across all the requests of the issuing flow returned by {@link startUserAuthorization}
177
+ * @param issuerConf The issuer configuration returned by {@link evaluateIssuerTrust}
178
+ * @param context.walletInstanceAccestation the Wallet Instance's attestation to be presented
179
+ * @param context.pid the PID to be presented
180
+ * @param context.wiaCryptoContext The Wallet Instance's crypto context associated with the walletInstanceAttestation parameter
181
+ * @param context.pidCryptoContext The PID crypto context associated with the pid parameter
182
+ * @param context.appFetch (optional) fetch api implementation. Default: built-in fetch
183
+ * @throws {ValidationFailed} if an error while validating the response
184
+ * @returns the authorization response which contains code, state and iss
185
+ */
186
+ export const completeUserAuthorizationWithFormPostJwtMode: CompleteUserAuthorizationWithFormPostJwtMode =
187
+ async (requestObject, ctx) => {
188
+ const {
189
+ wiaCryptoContext,
190
+ pidCryptoContext,
191
+ pid,
192
+ walletInstanceAttestation,
193
+ appFetch = fetch,
194
+ } = ctx;
195
+
196
+ const wiaWpToken = await new SignJWT(wiaCryptoContext)
197
+ .setProtectedHeader({
198
+ alg: "ES256",
199
+ typ: "JWT",
200
+ })
201
+ .setPayload({
202
+ vp: walletInstanceAttestation,
203
+ jti: uuid.v4().toString(),
204
+ nonce: requestObject.nonce,
205
+ })
206
+ .setIssuedAt()
207
+ .setExpirationTime("5m")
208
+ .setAudience(requestObject.response_uri)
209
+ .sign();
210
+
211
+ const pidWpToken = await new SignJWT(pidCryptoContext)
212
+ .setProtectedHeader({
213
+ alg: "ES256",
214
+ typ: "JWT",
215
+ })
216
+ .setPayload({
217
+ vp: pid,
218
+ jti: uuid.v4().toString(),
219
+ nonce: requestObject.nonce,
220
+ })
221
+ .setIssuedAt()
222
+ .setExpirationTime("5m")
223
+ .setAudience(requestObject.response_uri)
224
+ .sign();
225
+
226
+ /* The path parameter refers to the vp_token variable of the authzResponsePayload and must point to the plain credential which
227
+ * is cointaned in the `vp` property of the signed jwt token payload
228
+ */
229
+ const presentationSubmission = {
230
+ definition_id: `${uuid.v4()}`,
231
+ id: `${uuid.v4()}`,
232
+ descriptor_map: [
233
+ {
234
+ id: "PersonIdentificationData",
235
+ path: "$.vp_token[0].vp",
236
+ format: "vc+sd-jwt",
237
+ },
238
+ {
239
+ id: "WalletAttestation",
240
+ path: "$.vp_token[1].vp",
241
+ format: "jwt",
242
+ },
243
+ ],
244
+ };
245
+
246
+ const authzResponsePayload = encodeBase64(
247
+ JSON.stringify({
248
+ state: requestObject.state,
249
+ presentation_submission: presentationSubmission,
250
+ vp_token: [pidWpToken, wiaWpToken],
251
+ })
252
+ );
253
+
254
+ // Note: according to the spec, the response should be encrypted with the public key of the RP however this is not implemented yet
255
+ // https://openid.net/specs/openid-4-verifiable-presentations-1_0.html#name-signed-and-encrypted-response
256
+ // const rsaPublicJwk = chooseRSAPublicKeyToEncrypt(rpConf);
257
+ // const encrypted = await new EncryptJwe(authzResponsePayload, {
258
+ // alg: "RSA-OAEP-256",
259
+ // enc: "A256CBC-HS512",
260
+ // kid: rsaPublicJwk.kid,
261
+ // }).encrypt(rsaPublicJwk);
262
+
263
+ const body = new URLSearchParams({
264
+ response: authzResponsePayload,
265
+ }).toString();
266
+ const resUriRes = await appFetch(requestObject.response_uri, {
267
+ method: "POST",
268
+ headers: {
269
+ "Content-Type": "application/x-www-form-urlencoded",
270
+ },
271
+ body,
272
+ })
273
+ .then(hasStatus(200))
274
+ .then((reqUri) => reqUri.json());
275
+
276
+ const responseUri = ResponseUriResultShape.safeParse(resUriRes);
277
+ if (!responseUri.success) {
278
+ throw new ValidationFailed(
279
+ "Response Uri validation failed",
280
+ responseUri.error.message
281
+ );
282
+ }
283
+
284
+ return await appFetch(responseUri.data.redirect_uri)
285
+ .then(hasStatus(200))
286
+ .then((res) => res.text())
287
+ .then(getJwtFromFormPost)
288
+ .then((cbRes) => parseAuthroizationResponse(cbRes.decodedJwt.payload));
289
+ };
290
+
291
+ /**
292
+ * Parse the authorization response and return the result which contains code, state and iss.
293
+ * @throws {AuthorizationError} if an error occurs during the parsing process
294
+ * @throws {AuthorizationIdpError} if an error occurs during the parsing process and the error is related to the IDP
295
+ * @param authRes the authorization response to be parsed
296
+ * @returns the authorization result which contains code, state and iss
297
+ */
298
+ export const parseAuthroizationResponse = (
299
+ authRes: unknown
300
+ ): AuthorizationResult => {
301
+ const authResParsed = AuthorizationResultShape.safeParse(authRes);
302
+ if (!authResParsed.success) {
303
+ const authErr = AuthorizationErrorShape.safeParse(authRes);
304
+ if (!authErr.success) {
305
+ throw new AuthorizationError(authResParsed.error.message); // an error occured while parsing the result and the error
306
+ }
307
+ throw new AuthorizationIdpError(
308
+ authErr.data.error,
309
+ authErr.data.error_description
310
+ );
311
+ }
312
+ return authResParsed.data;
118
313
  };
@@ -13,6 +13,7 @@ export type VerifyAndParseCredential = (
13
13
  format: Out<ObtainCredential>["format"],
14
14
  context: {
15
15
  credentialCryptoContext: CryptoContext;
16
+ ignoreMissingAttributes?: boolean;
16
17
  }
17
18
  ) => Promise<{ parsedCredential: ParsedCredential }>;
18
19
 
@@ -42,7 +43,8 @@ type DecodedSdJwtCredential = Out<typeof verifySdJwt> & {
42
43
  const parseCredentialSdJwt = (
43
44
  // the list of supported credentials, as defined in the issuer configuration
44
45
  credentials_supported: Out<EvaluateIssuerTrust>["issuerConf"]["openid_credential_issuer"]["credential_configurations_supported"],
45
- { sdJwt, disclosures }: DecodedSdJwtCredential
46
+ { sdJwt, disclosures }: DecodedSdJwtCredential,
47
+ ignoreMissingAttributes: boolean = false
46
48
  ): ParsedCredential => {
47
49
  const credentialSubject = credentials_supported[sdJwt.payload.vct];
48
50
 
@@ -57,6 +59,9 @@ const parseCredentialSdJwt = (
57
59
  }
58
60
 
59
61
  // transfrom a record { key: value } in an iterable of pairs [key, value]
62
+ if (!credentialSubject.claims) {
63
+ throw new IoWalletError("Missing claims in the credential subject"); // TODO [SIW-1268]: should not be optional
64
+ }
60
65
  const attrDefinitions = Object.entries(credentialSubject.claims);
61
66
 
62
67
  // the key of the attribute defintion must match the disclosure's name
@@ -66,9 +71,11 @@ const parseCredentialSdJwt = (
66
71
  if (attrsNotInDisclosures.length > 0) {
67
72
  const missing = attrsNotInDisclosures.map((_) => _[0 /* key */]).join(", ");
68
73
  const received = disclosures.map((_) => _[1 /* name */]).join(", ");
69
- throw new IoWalletError(
70
- `Some attributes are missing in the credential. Missing: [${missing}], received: [${received}]`
71
- );
74
+ if (!ignoreMissingAttributes) {
75
+ throw new IoWalletError(
76
+ `Some attributes are missing in the credential. Missing: [${missing}], received: [${received}]`
77
+ );
78
+ }
72
79
  }
73
80
 
74
81
  // attributes that are defined in the issuer configuration
@@ -169,7 +176,7 @@ const verifyAndParseCredentialSdJwt: WithFormat<"vc+sd-jwt"> = async (
169
176
  issuerConf,
170
177
  credential,
171
178
  _,
172
- { credentialCryptoContext }
179
+ { credentialCryptoContext, ignoreMissingAttributes }
173
180
  ) => {
174
181
  const decoded = await verifyCredentialSdJwt(
175
182
  credential,
@@ -179,7 +186,8 @@ const verifyAndParseCredentialSdJwt: WithFormat<"vc+sd-jwt"> = async (
179
186
 
180
187
  const parsedCredential = parseCredentialSdJwt(
181
188
  issuerConf.openid_credential_issuer.credential_configurations_supported,
182
- decoded
189
+ decoded,
190
+ ignoreMissingAttributes
183
191
  );
184
192
 
185
193
  return { parsedCredential };
@@ -9,7 +9,12 @@ import {
9
9
  } from "./03-start-user-authorization";
10
10
  import {
11
11
  completeUserAuthorizationWithQueryMode,
12
+ completeUserAuthorizationWithFormPostJwtMode,
13
+ parseAuthroizationResponse,
12
14
  type CompleteUserAuthorizationWithQueryMode,
15
+ type CompleteUserAuthorizationWithFormPostJwtMode,
16
+ type GetRequestedCredentialToBePresented,
17
+ getRequestedCredentialToBePresented,
13
18
  } from "./04-complete-user-authorization";
14
19
  import { authorizeAccess, type AuthorizeAccess } from "./05-authorize-access";
15
20
  import {
@@ -25,15 +30,20 @@ export {
25
30
  evaluateIssuerTrust,
26
31
  startUserAuthorization,
27
32
  completeUserAuthorizationWithQueryMode,
33
+ getRequestedCredentialToBePresented,
34
+ completeUserAuthorizationWithFormPostJwtMode,
28
35
  authorizeAccess,
29
36
  obtainCredential,
30
37
  verifyAndParseCredential,
38
+ parseAuthroizationResponse,
31
39
  };
32
40
  export type {
33
41
  StartFlow,
34
42
  EvaluateIssuerTrust,
35
43
  StartUserAuthorization,
36
44
  CompleteUserAuthorizationWithQueryMode,
45
+ GetRequestedCredentialToBePresented,
46
+ CompleteUserAuthorizationWithFormPostJwtMode,
37
47
  AuthorizeAccess,
38
48
  ObtainCredential,
39
49
  VerifyAndParseCredential,
@@ -22,4 +22,11 @@ export const CredentialResponse = z.object({
22
22
  format: SupportedCredentialFormat,
23
23
  });
24
24
 
25
+ /**
26
+ * Shape from parsing a response given by a request uri during the EAA credential issuance flow with response mode "form_post.jwt".
27
+ */
28
+ export const ResponseUriResultShape = z.object({
29
+ redirect_uri: z.string(),
30
+ });
31
+
25
32
  export type ResponseMode = "query" | "form_post.jwt";
package/src/index.ts CHANGED
@@ -11,6 +11,7 @@ import * as Errors from "./utils/errors";
11
11
  import * as WalletInstanceAttestation from "./wallet-instance-attestation";
12
12
  import * as Trust from "./trust";
13
13
  import * as WalletInstance from "./wallet-instance";
14
+ import * as Cie from "./cie";
14
15
  import { AuthorizationDetail, AuthorizationDetails } from "./utils/par";
15
16
  import { createCryptoContextFor } from "./utils/crypto";
16
17
  import type { IntegrityContext } from "./utils/integrity";
@@ -27,6 +28,7 @@ export {
27
28
  AuthorizationDetail,
28
29
  AuthorizationDetails,
29
30
  fixBase64EncodingOnKey,
31
+ Cie,
30
32
  };
31
33
 
32
34
  export type { IntegrityContext, AuthorizationContext };
@@ -37,10 +37,12 @@ type CredentialIssuerDisplayMetadata = z.infer<
37
37
  const CredentialIssuerDisplayMetadata = z.object({
38
38
  name: z.string(),
39
39
  locale: z.string(),
40
- logo: z.object({
41
- url: z.string(),
42
- alt_text: z.string(),
43
- }),
40
+ logo: z
41
+ .object({
42
+ url: z.string(),
43
+ alt_text: z.string(),
44
+ })
45
+ .optional(), // TODO [SIW-1268]: should not be optional
44
46
  });
45
47
 
46
48
  type ClaimsMetadata = z.infer<typeof ClaimsMetadata>;
@@ -57,7 +59,7 @@ const SupportedCredentialMetadata = z.object({
57
59
  format: z.union([z.literal("vc+sd-jwt"), z.literal("vc+mdoc-cbor")]),
58
60
  scope: z.string(),
59
61
  display: z.array(CredentialDisplayMetadata),
60
- claims: ClaimsMetadata,
62
+ claims: ClaimsMetadata.optional(), // TODO [SIW-1268]: should not be optional
61
63
  cryptographic_binding_methods_supported: z.array(z.string()),
62
64
  credential_signing_alg_values_supported: z.array(z.string()),
63
65
  });
@@ -180,7 +182,7 @@ export const CredentialIssuerEntityConfiguration = BaseEntityConfiguration.and(
180
182
  /** Credential Issuers act as Relying Party
181
183
  when they require the presentation of other credentials.
182
184
  This does not apply for PID issuance, which requires CIE authz. */
183
- openid_relying_party: RelyingPartyMetadata.optional(),
185
+ wallet_relying_party: RelyingPartyMetadata.optional(),
184
186
  }),
185
187
  }),
186
188
  })
@@ -6,34 +6,43 @@ import { ValidationFailed } from "./errors";
6
6
  * Decode a form_post.jwt and return the final JWT.
7
7
  * The formData here is in form_post.jwt format as defined in
8
8
  * JWT Secured Authorization Response Mode for OAuth 2.0 (JARM)
9
- * HTTP/1.1 200 OK
10
- * Content-Type: text/html;charset=UTF-8
11
- * Cache-Control: no-cache, no-store
12
- * Pragma: no-cache
13
- *
14
- * <html>
15
- * <head><title>Submit This Form</title></head>
16
- * <body onload="javascript:document.forms[0].submit()">
17
- * <form method="post" action="https://client.example.com/cb">
18
- * <input type="hidden" name="response"
19
- * value="eyJhbGciOiJSUz....."/>
20
- * </form>
21
- * </body>
22
- * </html>
9
+ <!DOCTYPE html>
10
+ <html>
11
+ <head>
12
+ <meta charset="utf-8" />
13
+ </head>
14
+ <body onload="document.forms[0].submit()">
15
+ <noscript>
16
+ <p>
17
+ <strong>Note:</strong> Since your browser does not support JavaScript, you must press the Continue button once to proceed.
18
+ </p>
19
+ </noscript>
20
+ <form action="iowalletexample//cb" method="post">
21
+ <div>
22
+ <input type="hidden" name="response" value="somevalue" />
23
+ </div>
24
+ <noscript>
25
+ <div>
26
+ <input type="submit" value="Continue" />
27
+ </div>
28
+ </noscript>
29
+ </form>
30
+ </body>
31
+ </html>
23
32
  */
24
33
  export const getJwtFromFormPost = async (
25
34
  formData: string
26
35
  ): Promise<{ jwt: string; decodedJwt: JWTDecodeResult }> => {
27
- const formPostRegex = /<input(.|\n)*value\s*=\s*"((.|\n)*)"(.|\n)*>/gm;
36
+ const formPostRegex = /<input[^>]*name="response"[^>]*value="([^"]*)"/i;
28
37
  const lineExpressionRegex = /\r\n|\n\r|\n|\r|\s+/g;
29
38
 
30
- const matches = formPostRegex.exec(formData);
31
- if (matches && matches.length >= 2) {
32
- const responseJwt = matches[2];
39
+ const match = formPostRegex.exec(formData);
40
+ if (match && match[1]) {
41
+ const responseJwt = match[1];
33
42
 
34
43
  if (responseJwt) {
35
44
  const jwt = responseJwt.replace(lineExpressionRegex, "");
36
- const decodedJwt = await decodeJwt(jwt);
45
+ const decodedJwt = decodeJwt(jwt);
37
46
  return { jwt, decodedJwt };
38
47
  }
39
48
  }