From 8716dfc162aab3341c29a9ad55e9dc3d95e3524e Mon Sep 17 00:00:00 2001 From: Johannes Tuerk Date: Mon, 16 Jun 2025 14:47:14 +0200 Subject: [PATCH] Use AuthServer requested in the CredentialOffer Signed-off-by: Johannes Tuerk --- .../CredOffer/GrantTypes/PreAuthorizedCode.cs | 17 ++++++++-- .../Implementations/Oid4VciClientService.cs | 31 ++++++++++++------- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/WalletFramework.Oid4Vc/Oid4Vci/CredOffer/GrantTypes/PreAuthorizedCode.cs b/src/WalletFramework.Oid4Vc/Oid4Vci/CredOffer/GrantTypes/PreAuthorizedCode.cs index 48e05d61..983422f6 100644 --- a/src/WalletFramework.Oid4Vc/Oid4Vci/CredOffer/GrantTypes/PreAuthorizedCode.cs +++ b/src/WalletFramework.Oid4Vc/Oid4Vci/CredOffer/GrantTypes/PreAuthorizedCode.cs @@ -3,6 +3,7 @@ using Newtonsoft.Json.Linq; using WalletFramework.Core.Functional; using WalletFramework.Core.Json; +using WalletFramework.Oid4Vc.Oid4Vci.Authorization.Models; using static WalletFramework.Oid4Vc.Oid4Vci.CredOffer.GrantTypes.TransactionCode; namespace WalletFramework.Oid4Vc.Oid4Vci.CredOffer.GrantTypes; @@ -24,11 +25,18 @@ public record PreAuthorizedCode /// [JsonProperty("tx_code")] public Option TransactionCode { get; } + + /// + /// Specifying whether the user must send a Transaction Code along with the Token Request in a Pre-Authorized Code Flow. + /// + [JsonProperty("authorization_server")] + public Option AuthorizationServer { get; } - private PreAuthorizedCode(string value, Option transactionCode) + private PreAuthorizedCode(string value, Option transactionCode, Option authorizationServer) { Value = value; TransactionCode = transactionCode; + AuthorizationServer = authorizationServer; } public static Option OptionalPreAuthorizedCode(JToken preAuthCode) @@ -38,12 +46,17 @@ public static Option OptionalPreAuthorizedCode(JToken preAuth .ToOption() .OnSome(OptionalTransactionCode); + var authorizationServer = preAuthCode + .GetByKey("authorization_server") + .OnSuccess(AuthorizationServerId.ValidAuthorizationServerId) + .ToOption(); + return preAuthCode .GetByKey("pre-authorized_code") .OnSuccess(token => { var value = token.ToString(); - return new PreAuthorizedCode(value, transactionCode); + return new PreAuthorizedCode(value, transactionCode, authorizationServer); }) .ToOption(); } diff --git a/src/WalletFramework.Oid4Vc/Oid4Vci/Implementations/Oid4VciClientService.cs b/src/WalletFramework.Oid4Vc/Oid4Vci/Implementations/Oid4VciClientService.cs index 02c41a84..01396750 100644 --- a/src/WalletFramework.Oid4Vc/Oid4Vci/Implementations/Oid4VciClientService.cs +++ b/src/WalletFramework.Oid4Vc/Oid4Vci/Implementations/Oid4VciClientService.cs @@ -711,9 +711,7 @@ from server in code.AuthorizationServer var getAuthServerResponse = await _httpClient.GetAsync(authServerUrl); if (!getAuthServerResponse.IsSuccessStatusCode) - throw new HttpRequestException( - $"Failed to get authorization server metadata. Status Code is: {getAuthServerResponse.StatusCode}" - ); + continue; var content = await getAuthServerResponse.Content.ReadAsStringAsync(); @@ -724,9 +722,6 @@ from server in code.AuthorizationServer authorizationServerMetadatas.Add(authServer); } - if (authorizationServerMetadatas.Count == 1) - return authorizationServerMetadatas.First(); - return credentialOffer.Match( Some: offer => { @@ -734,18 +729,30 @@ from server in code.AuthorizationServer from code in grants.AuthorizationCode select code; - return credentialOfferAuthCodeGrantType.Match( - Some: code => authorizationServerMetadatas.Find(authServer => authServer.SupportsAuthCodeFlow) ?? - throw new InvalidOperationException("No suitable Authorization Server found"), + return credentialOfferAuthCodeGrantType.Match( + Some: code => code.AuthorizationServer.Match( + Some: requestedAuthServer => + authorizationServerMetadatas.Find(authServer => + authServer.Issuer == requestedAuthServer.ToString()) + ?? throw new InvalidOperationException("No suitable Authorization Server found"), + None: () => authorizationServerMetadatas.Find(authServer => authServer.SupportsAuthCodeFlow) ?? + throw new InvalidOperationException("No suitable Authorization Server found")), None: () => { var credentialOfferPreAuthGrantType = from grants in offer.Grants - from code in grants.AuthorizationCode + from code in grants.PreAuthorizedCode select code; return credentialOfferPreAuthGrantType.Match( - Some: preAuth => authorizationServerMetadatas.Find(authServer => authServer.SupportsPreAuthFlow) - ?? throw new InvalidOperationException("No suitable Authorization Server found"), + Some: preAuth => + { + return preAuth.AuthorizationServer.Match( + Some: requestedAuthServer => + authorizationServerMetadatas.Find(authServer => + authServer.Issuer == requestedAuthServer.ToString()) + ?? throw new InvalidOperationException("No suitable Authorization Server found"), + None: () => authorizationServerMetadatas.Find(authServer => authServer.SupportsPreAuthFlow)); + }, None: () => authorizationServerMetadatas.First()); }); },