Skip to content

Commit

Permalink
Fix IDX21323: RequireNonce is 'False' during token refreshClient (#240)
Browse files Browse the repository at this point in the history
  • Loading branch information
halter73 authored Mar 9, 2024
1 parent 8ff9eea commit c98a9cc
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 14 deletions.
14 changes: 7 additions & 7 deletions 8.0/BlazorWebAppOidc/BlazorWebAppOidc/CookieOidcRefresher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
namespace BlazorWebAppOidc;

// https://github.com/dotnet/aspnetcore/issues/8175
internal sealed class CookieOidcRefresher(IOptionsMonitor<OpenIdConnectOptions> oidcOptionsMonitor) : IDisposable
internal sealed class CookieOidcRefresher(IOptionsMonitor<OpenIdConnectOptions> oidcOptionsMonitor)
{
private readonly HttpClient refreshClient = new();
private readonly OpenIdConnectProtocolValidator oidcTokenValidator = new()
{
// Refresh requests do not use the nonce parameter. Otherwise, we'd use oidcOptions.ProtocolValidator.
// We no longer have the original nonce cookie which is deleted at the end of the authorization code flow having served its purpose.
// Even if we had the nonce, it's likely expired. It's not intended for refresh requests. Otherwise, we'd use oidcOptions.ProtocolValidator.
RequireNonce = false,
};

Expand All @@ -39,7 +39,7 @@ public async Task ValidateOrRefreshCookieAsync(CookieValidatePrincipalContext va
var oidcConfiguration = await oidcOptions.ConfigurationManager!.GetConfigurationAsync(validateContext.HttpContext.RequestAborted);
var tokenEndpoint = oidcConfiguration.TokenEndpoint ?? throw new InvalidOperationException("Cannot refresh cookie. TokenEndpoint missing!");

using var refreshResponse = await refreshClient.PostAsync(tokenEndpoint,
using var refreshResponse = await oidcOptions.Backchannel.PostAsync(tokenEndpoint,
new FormUrlEncodedContent(new Dictionary<string, string?>()
{
["grant_type"] = "refresh_token",
Expand Down Expand Up @@ -77,11 +77,13 @@ public async Task ValidateOrRefreshCookieAsync(CookieValidatePrincipalContext va
return;
}

var validatedIdToken = JwtSecurityTokenConverter.Convert(validationResult.SecurityToken as JsonWebToken);
validatedIdToken.Payload["nonce"] = null;
oidcTokenValidator.ValidateTokenResponse(new()
{
ProtocolMessage = message,
ClientId = oidcOptions.ClientId,
ValidatedIdToken = JwtSecurityTokenConverter.Convert(validationResult.SecurityToken as JsonWebToken),
ValidatedIdToken = validatedIdToken,
});

validateContext.ShouldRenew = true;
Expand All @@ -97,6 +99,4 @@ public async Task ValidateOrRefreshCookieAsync(CookieValidatePrincipalContext va
new() { Name = "expires_at", Value = expiresAt.ToString("o", CultureInfo.InvariantCulture) },
]);
}

public void Dispose() => refreshClient.Dispose();
}
14 changes: 7 additions & 7 deletions 8.0/BlazorWebAppOidcBff/BlazorWebAppOidc/CookieOidcRefresher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
namespace BlazorWebAppOidc;

// https://github.com/dotnet/aspnetcore/issues/8175
internal sealed class CookieOidcRefresher(IOptionsMonitor<OpenIdConnectOptions> oidcOptionsMonitor) : IDisposable
internal sealed class CookieOidcRefresher(IOptionsMonitor<OpenIdConnectOptions> oidcOptionsMonitor)
{
private readonly HttpClient refreshClient = new();
private readonly OpenIdConnectProtocolValidator oidcTokenValidator = new()
{
// Refresh requests do not use the nonce parameter. Otherwise, we'd use oidcOptions.ProtocolValidator.
// We no longer have the original nonce cookie which is deleted at the end of the authorization code flow having served its purpose.
// Even if we had the nonce, it's likely expired. It's not intended for refresh requests. Otherwise, we'd use oidcOptions.ProtocolValidator.
RequireNonce = false,
};

Expand All @@ -39,7 +39,7 @@ public async Task ValidateOrRefreshCookieAsync(CookieValidatePrincipalContext va
var oidcConfiguration = await oidcOptions.ConfigurationManager!.GetConfigurationAsync(validateContext.HttpContext.RequestAborted);
var tokenEndpoint = oidcConfiguration.TokenEndpoint ?? throw new InvalidOperationException("Cannot refresh cookie. TokenEndpoint missing!");

using var refreshResponse = await refreshClient.PostAsync(tokenEndpoint,
using var refreshResponse = await oidcOptions.Backchannel.PostAsync(tokenEndpoint,
new FormUrlEncodedContent(new Dictionary<string, string?>()
{
["grant_type"] = "refresh_token",
Expand Down Expand Up @@ -77,11 +77,13 @@ public async Task ValidateOrRefreshCookieAsync(CookieValidatePrincipalContext va
return;
}

var validatedIdToken = JwtSecurityTokenConverter.Convert(validationResult.SecurityToken as JsonWebToken);
validatedIdToken.Payload["nonce"] = null;
oidcTokenValidator.ValidateTokenResponse(new()
{
ProtocolMessage = message,
ClientId = oidcOptions.ClientId,
ValidatedIdToken = JwtSecurityTokenConverter.Convert(validationResult.SecurityToken as JsonWebToken),
ValidatedIdToken = validatedIdToken,
});

validateContext.ShouldRenew = true;
Expand All @@ -97,6 +99,4 @@ public async Task ValidateOrRefreshCookieAsync(CookieValidatePrincipalContext va
new() { Name = "expires_at", Value = expiresAt.ToString("o", CultureInfo.InvariantCulture) },
]);
}

public void Dispose() => refreshClient.Dispose();
}

0 comments on commit c98a9cc

Please sign in to comment.