Browse Source

Store the provider name in the state token as a private claim and update the ASP.NET Core/OWIN hosts to return it as part of the merged principal

pull/1642/head
Kévin Chalet 3 years ago
parent
commit
62a10af526
  1. 1
      src/OpenIddict.Abstractions/OpenIddictConstants.cs
  2. 3
      src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandler.cs
  3. 3
      src/OpenIddict.Client.Owin/OpenIddictClientOwinHandler.cs
  4. 21
      src/OpenIddict.Client/OpenIddictClientHandlers.cs

1
src/OpenIddict.Abstractions/OpenIddictConstants.cs

@ -133,6 +133,7 @@ public static class OpenIddictConstants
public const string Issuer = "oi_iss";
public const string Nonce = "oi_nce";
public const string PostLogoutRedirectUri = "oi_pstlgt_reduri";
public const string ProviderName = "oi_prvd_name";
public const string Presenter = "oi_prst";
public const string RedirectUri = "oi_reduri";
public const string RefreshTokenLifetime = "oi_reft_lft";

3
src/OpenIddict.Client.AspNetCore/OpenIddictClientAspNetCoreHandler.cs

@ -165,7 +165,8 @@ public sealed class OpenIddictClientAspNetCoreHandler : AuthenticationHandler<Op
// Attach the identity of the authorization to the returned principal to allow resolving it even if no other
// claim was added to the principal (e.g when no id_token was returned and no userinfo endpoint is available).
principal.SetClaim(Claims.AuthorizationServer, context.StateTokenPrincipal?.GetClaim(Claims.AuthorizationServer));
principal.SetClaim(Claims.AuthorizationServer, context.StateTokenPrincipal?.GetClaim(Claims.AuthorizationServer))
.SetClaim(Claims.Private.ProviderName, context.StateTokenPrincipal?.GetClaim(Claims.Private.ProviderName));
// Restore or create a new authentication properties collection and populate it.
var properties = CreateProperties(context.StateTokenPrincipal);

3
src/OpenIddict.Client.Owin/OpenIddictClientOwinHandler.cs

@ -180,7 +180,8 @@ public sealed class OpenIddictClientOwinHandler : AuthenticationHandler<OpenIddi
// Attach the identity of the authorization to the returned principal to allow resolving it even if no other
// claim was added to the principal (e.g when no id_token was returned and no userinfo endpoint is available).
principal.SetClaim(Claims.AuthorizationServer, context.StateTokenPrincipal?.GetClaim(Claims.AuthorizationServer));
principal.SetClaim(Claims.AuthorizationServer, context.StateTokenPrincipal?.GetClaim(Claims.AuthorizationServer))
.SetClaim(Claims.Private.ProviderName, context.StateTokenPrincipal?.GetClaim(Claims.Private.ProviderName));
// Restore or create a new authentication properties collection and populate it.
var properties = CreateProperties(context.StateTokenPrincipal);

21
src/OpenIddict.Client/OpenIddictClientHandlers.cs

@ -876,8 +876,8 @@ public static partial class OpenIddictClientHandlers
// Restore the identity of the authorization server from the special "as" claim.
// See https://datatracker.ietf.org/doc/html/draft-bradley-oauth-jwt-encoded-state-09#section-2
// for more information.
var value = context.StateTokenPrincipal.GetClaim(Claims.AuthorizationServer);
if (string.IsNullOrEmpty(value) || !Uri.TryCreate(value, UriKind.Absolute, out Uri? issuer) ||
var server = context.StateTokenPrincipal.GetClaim(Claims.AuthorizationServer);
if (string.IsNullOrEmpty(server) || !Uri.TryCreate(server, UriKind.Absolute, out Uri? issuer) ||
!issuer.IsWellFormedOriginalString())
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0291));
@ -890,6 +890,15 @@ public static partial class OpenIddictClientHandlers
context.Registration = context.Options.Registrations.Find(registration => registration.Issuer == issuer) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0292));
// If an explicit provider name was also added, ensure the two values point to the same issuer.
var provider = context.StateTokenPrincipal.GetClaim(Claims.Private.ProviderName);
if (!string.IsNullOrEmpty(provider) &&
!string.IsNullOrEmpty(context.Registration.ProviderName) &&
!string.Equals(provider, context.Registration.ProviderName, StringComparison.Ordinal))
{
throw new InvalidOperationException(SR.GetResourceString(SR.ID0349));
}
// Resolve and attach the server configuration to the context.
context.Configuration = await context.Registration.ConfigurationManager.GetConfigurationAsync(default) ??
throw new InvalidOperationException(SR.GetResourceString(SR.ID0140));
@ -951,7 +960,7 @@ public static partial class OpenIddictClientHandlers
// If the two values don't match, this may indicate a mix-up attack attempt.
if (!Uri.TryCreate(issuer, UriKind.Absolute, out Uri? uri) ||
!uri.IsWellFormedOriginalString() || uri != context.Configuration.Issuer)
!uri.IsWellFormedOriginalString() || uri != context.Issuer)
{
context.Reject(
error: Errors.InvalidRequest,
@ -4548,7 +4557,8 @@ public static partial class OpenIddictClientHandlers
//
// See https://datatracker.ietf.org/doc/html/draft-bradley-oauth-jwt-encoded-state-09
// for more information about this special claim.
principal.SetClaim(Claims.AuthorizationServer, context.Issuer.AbsoluteUri);
principal.SetClaim(Claims.AuthorizationServer, context.Issuer.AbsoluteUri)
.SetClaim(Claims.Private.ProviderName, context.Registration.ProviderName);
// Store the request forgery protection in the state token so it can be later used to
// ensure the authorization response sent to the redirection endpoint is not forged.
@ -5123,7 +5133,8 @@ public static partial class OpenIddictClientHandlers
//
// See https://datatracker.ietf.org/doc/html/draft-bradley-oauth-jwt-encoded-state-09
// for more information about this special claim.
principal.SetClaim(Claims.AuthorizationServer, context.Issuer.AbsoluteUri);
principal.SetClaim(Claims.AuthorizationServer, context.Issuer.AbsoluteUri)
.SetClaim(Claims.Private.ProviderName, context.Registration.ProviderName);
// Store the request forgery protection in the state token so it can be later used to
// ensure the logout response sent to the post-logout redirection endpoint is not forged.

Loading…
Cancel
Save