From edefb5164c534096a0e9498774238dc4ad2097f6 Mon Sep 17 00:00:00 2001 From: Anders Revsgaard Date: Tue, 28 Dec 2021 14:59:35 +0100 Subject: [PATCH] .NET 6.0 and .NET 5.0 only read ID token. .NET Standard 2.0 validates the ID token. --- .../ITfoxtec.Identity.BlazorWA.Oidc.csproj | 6 +- .../OpenidConnectPkce.cs | 66 ++++++++++++------- 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/src/ITfoxtec.Identity.BlazorWA.Oidc/ITfoxtec.Identity.BlazorWA.Oidc.csproj b/src/ITfoxtec.Identity.BlazorWA.Oidc/ITfoxtec.Identity.BlazorWA.Oidc.csproj index 61c87c7..84623ac 100644 --- a/src/ITfoxtec.Identity.BlazorWA.Oidc/ITfoxtec.Identity.BlazorWA.Oidc.csproj +++ b/src/ITfoxtec.Identity.BlazorWA.Oidc/ITfoxtec.Identity.BlazorWA.Oidc.csproj @@ -22,9 +22,9 @@ The component automatically handle token / session update with use of the refres Blazor WebAssembly OpenID Connect (OIDC) Proof Key for Code Exchange (PKCE) id token access token refresh token true © 2020 ITfoxtec - 1.6.2.0 - 1.6.2.0 - 1.6.2 + 1.6.3.0 + 1.6.3.0 + 1.6.3 diff --git a/src/ITfoxtec.Identity.BlazorWA.Oidc/OpenidConnectPkce.cs b/src/ITfoxtec.Identity.BlazorWA.Oidc/OpenidConnectPkce.cs index b3b21bf..eed8bdd 100644 --- a/src/ITfoxtec.Identity.BlazorWA.Oidc/OpenidConnectPkce.cs +++ b/src/ITfoxtec.Identity.BlazorWA.Oidc/OpenidConnectPkce.cs @@ -15,6 +15,9 @@ using System.Security; using System.Security.Claims; using System.Threading.Tasks; +#if !NET50 && !NET60 +using ITfoxtec.Identity.Models; +#endif namespace ITfoxtec.Identity.BlazorWebAssembly.OpenidConnect { @@ -161,13 +164,19 @@ public async Task LoginCallBackAsync(string responseUrl) if (tokenResponse.AccessToken.IsNullOrEmpty()) throw new ArgumentNullException(nameof(tokenResponse.AccessToken), tokenResponse.GetTypeName()); if (tokenResponse.ExpiresIn <= 0) throw new ArgumentNullException(nameof(tokenResponse.ExpiresIn), tokenResponse.GetTypeName()); - //var oidcDiscoveryKeySet = await GetOidcDiscoveryKeysAsync(openidClientPkceState.OidcDiscoveryUri); - - //(var idTokenPrincipal, _) = JwtHandler.ValidateToken(tokenResponse.IdToken, oidcDiscovery.Issuer, oidcDiscoveryKeySet.Keys.ToMSJsonWebKeys(), openidClientPkceState.ClientId, - // nameClaimType: globalOpenidClientPkceSettings.NameClaimType, roleClaimType: globalOpenidClientPkceSettings.RoleClaimType); - // Changed to only read ID token and not do validation - + // .NET 5.0 error, System.Security.Cryptography.RSA.Create() - System.PlatformNotSupportedException: System.Security.Cryptography.Algorithms is not supported on this platform. + // https://github.com/dotnet/aspnetcore/issues/26123 + // https://github.com/dotnet/runtime/issues/40074 + // .NET 7 + // https://github.com/dotnet/designs/blob/main/accepted/2021/blazor-wasm-crypto.md#net-7-plan +#if !NET50 && !NET60 + var oidcDiscoveryKeySet = await GetOidcDiscoveryKeysAsync(openidClientPkceState.OidcDiscoveryUri); + + (var idTokenPrincipal, _) = JwtHandler.ValidateToken(tokenResponse.IdToken, oidcDiscovery.Issuer, oidcDiscoveryKeySet.Keys.ToMSJsonWebKeys(), openidClientPkceState.ClientId, + nameClaimType: globalOpenidClientPkceSettings.NameClaimType, roleClaimType: globalOpenidClientPkceSettings.RoleClaimType); +#else var idTokenPrincipal = JwtHandler.ReadTokenClaims(tokenResponse.IdToken); +#endif var nonce = idTokenPrincipal.Claims.Where(c => c.Type == JwtClaimTypes.Nonce).Select(c => c.Value).FirstOrDefault(); if (!openidClientPkceState.Nonce.Equals(nonce, StringComparison.Ordinal)) @@ -228,13 +237,19 @@ public async Task HandleRefreshTokenAsync(OidcUserSession userS if (tokenResponse.AccessToken.IsNullOrEmpty()) throw new ArgumentNullException(nameof(tokenResponse.AccessToken), tokenResponse.GetTypeName()); if (tokenResponse.ExpiresIn <= 0) throw new ArgumentNullException(nameof(tokenResponse.ExpiresIn), tokenResponse.GetTypeName()); - //var oidcDiscoveryKeySet = await GetOidcDiscoveryKeysAsync(oidcDiscoveryUri); - - //(var idTokenPrincipal, _) = JwtHandler.ValidateToken(tokenResponse.IdToken, oidcDiscovery.Issuer, oidcDiscoveryKeySet.Keys, clientId, - // nameClaimType: globalOpenidClientPkceSettings.NameClaimType, roleClaimType: globalOpenidClientPkceSettings.RoleClaimType); - // Changed to only read ID token and not do validation - + // .NET 5.0 error, System.Security.Cryptography.RSA.Create() - System.PlatformNotSupportedException: System.Security.Cryptography.Algorithms is not supported on this platform. + // https://github.com/dotnet/aspnetcore/issues/26123 + // https://github.com/dotnet/runtime/issues/40074 + // .NET 7 + // https://github.com/dotnet/designs/blob/main/accepted/2021/blazor-wasm-crypto.md#net-7-plan +#if !NET50 && !NET60 + var oidcDiscoveryKeySet = await GetOidcDiscoveryKeysAsync(oidcDiscoveryUri); + + (var idTokenPrincipal, _) = JwtHandler.ValidateToken(tokenResponse.IdToken, oidcDiscovery.Issuer, oidcDiscoveryKeySet.Keys, clientId, + nameClaimType: globalOpenidClientPkceSettings.NameClaimType, roleClaimType: globalOpenidClientPkceSettings.RoleClaimType); +#else var idTokenPrincipal = JwtHandler.ReadTokenClaims(tokenResponse.IdToken); +#endif if (!subject.IsNullOrEmpty() && subject != idTokenPrincipal.Claims.Where(c => c.Type == globalOpenidClientPkceSettings.NameClaimType).Single().Value) { @@ -353,19 +368,20 @@ private async Task GetOidcDiscoveryAsync(string oidcDiscoveryUri) } } - // Changed to only read ID token and not do validation - //private async Task GetOidcDiscoveryKeysAsync(string oidcDiscoveryUri) - //{ - // try - // { - // var oidcDiscoveryHandler = serviceProvider.GetService(); - // return await oidcDiscoveryHandler.GetOidcDiscoveryKeysAsync(oidcDiscoveryUri); - // } - // catch (Exception ex) - // { - // throw new Exception($"Failed to fetch OIDC Discovery Keys from discovery '{oidcDiscoveryUri}'.", ex); - // } - //} +#if !NET50 && !NET60 + private async Task GetOidcDiscoveryKeysAsync(string oidcDiscoveryUri) + { + try + { + var oidcDiscoveryHandler = serviceProvider.GetService(); + return await oidcDiscoveryHandler.GetOidcDiscoveryKeysAsync(oidcDiscoveryUri); + } + catch (Exception ex) + { + throw new Exception($"Failed to fetch OIDC Discovery Keys from discovery '{oidcDiscoveryUri}'.", ex); + } + } +#endif private async Task SaveStateAsync(OpenidConnectPkceSettings openidConnectPkceSettings, string callBackUri, string redirectUri, string codeVerifier = null, string nonce = null) {