Browse Source

Bring back automatic authorization validation and ad-hoc authorization creation

pull/803/head
Kévin Chalet 7 years ago
committed by GitHub
parent
commit
9262d5aa3e
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      src/OpenIddict.Abstractions/Descriptors/OpenIddictAuthorizationDescriptor.cs
  2. 5
      src/OpenIddict.Abstractions/Managers/IOpenIddictAuthorizationManager.cs
  3. 2
      src/OpenIddict.Abstractions/OpenIddictConstants.cs
  4. 70
      src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs
  5. 23
      src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
  6. 2
      src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionConstants.cs
  7. 13
      src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionHandlers.Serialization.cs
  8. 1
      src/OpenIddict.Server/OpenIddictServerExtensions.cs
  9. 16
      src/OpenIddict.Server/OpenIddictServerHandlerFilters.cs
  10. 62
      src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs
  11. 62
      src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs
  12. 2
      src/OpenIddict.Server/OpenIddictServerHandlers.Serialization.cs
  13. 122
      src/OpenIddict.Server/OpenIddictServerHandlers.cs

5
src/OpenIddict.Abstractions/Descriptors/OpenIddictAuthorizationDescriptor.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Security.Claims;
namespace OpenIddict.Abstractions
{
@ -14,10 +15,10 @@ namespace OpenIddict.Abstractions
public string ApplicationId { get; set; }
/// <summary>
/// Gets the claims associated with the authorization.
/// Gets or sets the optional principal associated with the authorization.
/// Note: this property is not stored by the default authorization stores.
/// </summary>
public IDictionary<string, object> Claims { get; } = new Dictionary<string, object>(StringComparer.Ordinal);
public ClaimsPrincipal Principal { get; set; }
/// <summary>
/// Gets the scopes associated with the authorization.

5
src/OpenIddict.Abstractions/Managers/IOpenIddictAuthorizationManager.cs

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Collections.Immutable;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
@ -45,7 +46,7 @@ namespace OpenIddict.Abstractions
/// <summary>
/// Creates a new permanent authorization based on the specified parameters.
/// </summary>
/// <param name="claims">The claims associated with the authorization.</param>
/// <param name="principal">The principal associated with the authorization.</param>
/// <param name="subject">The subject associated with the authorization.</param>
/// <param name="client">The client associated with the authorization.</param>
/// <param name="type">The authorization type.</param>
@ -55,7 +56,7 @@ namespace OpenIddict.Abstractions
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation, whose result returns the authorization.
/// </returns>
ValueTask<object> CreateAsync(
[NotNull] ImmutableDictionary<string, object> claims, [NotNull] string subject, [NotNull] string client,
[NotNull] ClaimsPrincipal principal, [NotNull] string subject, [NotNull] string client,
[NotNull] string type, ImmutableArray<string> scopes, CancellationToken cancellationToken = default);
/// <summary>

2
src/OpenIddict.Abstractions/OpenIddictConstants.cs

@ -88,6 +88,7 @@ namespace OpenIddict.Abstractions
public static class Private
{
public const string AccessTokenLifetime = "oi_act_lft";
public const string AuthorizationId = "oi_au_id";
public const string AuthorizationCodeLifetime = "oi_auc_lft";
public const string ClaimDestinations = "oi_cl_dstn";
public const string CodeChallenge = "oi_cd_chlg";
@ -97,6 +98,7 @@ namespace OpenIddict.Abstractions
public const string RedirectUri = "oi_reduri";
public const string RefreshTokenLifetime = "oi_reft_lft";
public const string Resource = "oi_rsrc";
public const string TokenId = "oi_tkn_id";
public const string TokenUsage = "oi_tkn_use";
}
}

70
src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs

@ -1246,11 +1246,41 @@ namespace OpenIddict.Abstractions
}
/// <summary>
/// Gets the unique identifier associated with the claims principal.
/// Gets the internal authorization identifier associated with the claims principal.
/// </summary>
/// <param name="principal">The claims principal.</param>
/// <returns>The unique identifier or <c>null</c> if the claim cannot be found.</returns>
public static string GetTokenId([NotNull] this ClaimsPrincipal principal)
public static string GetInternalAuthorizationId([NotNull] this ClaimsPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
return principal.GetClaim(Claims.Private.AuthorizationId);
}
/// <summary>
/// Gets the internal token identifier associated with the claims principal.
/// </summary>
/// <param name="principal">The claims principal.</param>
/// <returns>The unique identifier or <c>null</c> if the claim cannot be found.</returns>
public static string GetInternalTokenId([NotNull] this ClaimsPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
return principal.GetClaim(Claims.Private.TokenId);
}
/// <summary>
/// Gets the public token identifier associated with the claims principal.
/// </summary>
/// <param name="principal">The claims principal.</param>
/// <returns>The unique identifier or <c>null</c> if the claim cannot be found.</returns>
public static string GetPublicTokenId([NotNull] this ClaimsPrincipal principal)
{
if (principal == null)
{
@ -1731,12 +1761,44 @@ namespace OpenIddict.Abstractions
}
/// <summary>
/// Sets the unique identifier associated with the claims principal.
/// Sets the internal authorization identifier associated with the claims principal.
/// </summary>
/// <param name="principal">The claims principal.</param>
/// <param name="identifier">The unique identifier to store.</param>
/// <returns>The claims principal.</returns>
public static ClaimsPrincipal SetInternalAuthorizationId([NotNull] this ClaimsPrincipal principal, string identifier)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
return principal.SetClaim(Claims.Private.AuthorizationId, identifier);
}
/// <summary>
/// Sets the internal token identifier associated with the claims principal.
/// </summary>
/// <param name="principal">The claims principal.</param>
/// <param name="identifier">The unique identifier to store.</param>
/// <returns>The claims principal.</returns>
public static ClaimsPrincipal SetInternalTokenId([NotNull] this ClaimsPrincipal principal, string identifier)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
return principal.SetClaim(Claims.Private.TokenId, identifier);
}
/// <summary>
/// Sets the public token identifier associated with the claims principal.
/// </summary>
/// <param name="principal">The claims principal.</param>
/// <param name="identifier">The unique identifier to store.</param>
/// <returns>The claims principal.</returns>
public static ClaimsPrincipal SetTokenId([NotNull] this ClaimsPrincipal principal, string identifier)
public static ClaimsPrincipal SetPublicTokenId([NotNull] this ClaimsPrincipal principal, string identifier)
{
if (principal == null)
{

23
src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs

@ -10,6 +10,7 @@ using System.Collections.Immutable;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Claims;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@ -165,7 +166,7 @@ namespace OpenIddict.Core
/// <summary>
/// Creates a new permanent authorization based on the specified parameters.
/// </summary>
/// <param name="claims">The claims associated with the authorization.</param>
/// <param name="principal">The principal associated with the authorization.</param>
/// <param name="subject">The subject associated with the authorization.</param>
/// <param name="client">The client associated with the authorization.</param>
/// <param name="type">The authorization type.</param>
@ -175,12 +176,12 @@ namespace OpenIddict.Core
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation, whose result returns the authorization.
/// </returns>
public virtual ValueTask<TAuthorization> CreateAsync(
[NotNull] ImmutableDictionary<string, object> claims, [NotNull] string subject,
[NotNull] string client, [NotNull] string type, ImmutableArray<string> scopes, CancellationToken cancellationToken = default)
[NotNull] ClaimsPrincipal principal, [NotNull] string subject, [NotNull] string client,
[NotNull] string type, ImmutableArray<string> scopes, CancellationToken cancellationToken = default)
{
if (claims == null)
if (principal == null)
{
throw new ArgumentNullException(nameof(claims));
throw new ArgumentNullException(nameof(principal));
}
if (string.IsNullOrEmpty(subject))
@ -201,6 +202,7 @@ namespace OpenIddict.Core
var descriptor = new OpenIddictAuthorizationDescriptor
{
ApplicationId = client,
Principal = principal,
Status = OpenIddictConstants.Statuses.Valid,
Subject = subject,
Type = type
@ -208,11 +210,6 @@ namespace OpenIddict.Core
descriptor.Scopes.UnionWith(scopes);
foreach (var claim in claims)
{
descriptor.Claims.Add(claim);
}
return CreateAsync(descriptor, cancellationToken);
}
@ -1035,8 +1032,6 @@ namespace OpenIddict.Core
throw new ArgumentNullException(nameof(authorization));
}
var builder = ImmutableArray.CreateBuilder<ValidationResult>();
var type = await Store.GetTypeAsync(authorization, cancellationToken);
if (string.IsNullOrEmpty(type))
{
@ -1084,8 +1079,8 @@ namespace OpenIddict.Core
ValueTask<long> IOpenIddictAuthorizationManager.CountAsync<TResult>(Func<IQueryable<object>, IQueryable<TResult>> query, CancellationToken cancellationToken)
=> CountAsync(query, cancellationToken);
async ValueTask<object> IOpenIddictAuthorizationManager.CreateAsync(ImmutableDictionary<string, object> claims, string subject, string client, string type, ImmutableArray<string> scopes, CancellationToken cancellationToken)
=> await CreateAsync(claims, subject, client, type, scopes, cancellationToken);
async ValueTask<object> IOpenIddictAuthorizationManager.CreateAsync(ClaimsPrincipal principal, string subject, string client, string type, ImmutableArray<string> scopes, CancellationToken cancellationToken)
=> await CreateAsync(principal, subject, client, type, scopes, cancellationToken);
async ValueTask<object> IOpenIddictAuthorizationManager.CreateAsync(OpenIddictAuthorizationDescriptor descriptor, CancellationToken cancellationToken)
=> await CreateAsync(descriptor, cancellationToken);

2
src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionConstants.cs

@ -18,6 +18,8 @@ namespace OpenIddict.Server.DataProtection
public const string DataProtector = ".data_protector";
public const string Expires = ".expires";
public const string IdentityTokenLifetime = ".identity_token_lifetime";
public const string InternalAuthorizationId = ".internal_authorization_id";
public const string InternalTokenId = ".internal_token_id";
public const string Issued = ".issued";
public const string Nonce = ".nonce";
public const string OriginalRedirectUri = ".original_redirect_uri";

13
src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionHandlers.Serialization.cs

@ -116,20 +116,31 @@ namespace OpenIddict.Server.DataProtection
SetProperty(properties, Properties.AccessTokenLifetime,
context.Principal.GetClaim(Claims.Private.AccessTokenLifetime));
SetProperty(properties, Properties.AuthorizationCodeLifetime,
context.Principal.GetClaim(Claims.Private.AuthorizationCodeLifetime));
SetProperty(properties, Properties.CodeChallenge,
context.Principal.GetClaim(Claims.Private.CodeChallenge));
SetProperty(properties, Properties.CodeChallengeMethod,
context.Principal.GetClaim(Claims.Private.CodeChallengeMethod));
SetProperty(properties, Properties.Expires,
context.Principal.GetExpirationDate()?.ToString("r", CultureInfo.InvariantCulture));
SetProperty(properties, Properties.IdentityTokenLifetime,
context.Principal.GetClaim(Claims.Private.IdentityTokenLifetime));
SetProperty(properties, Properties.InternalAuthorizationId, context.Principal.GetInternalAuthorizationId());
SetProperty(properties, Properties.InternalTokenId, context.Principal.GetInternalTokenId());
SetProperty(properties, Properties.Issued,
context.Principal.GetCreationDate()?.ToString("r", CultureInfo.InvariantCulture));
SetProperty(properties, Properties.OriginalRedirectUri,
context.Principal.GetClaim(Claims.Private.RedirectUri));
SetProperty(properties, Properties.RefreshTokenLifetime,
context.Principal.GetClaim(Claims.Private.RefreshTokenLifetime));
@ -342,11 +353,13 @@ namespace OpenIddict.Server.DataProtection
.SetClaim(Claims.Private.AccessTokenLifetime, GetProperty(properties, Properties.AccessTokenLifetime))
.SetClaim(Claims.Private.AuthorizationCodeLifetime, GetProperty(properties, Properties.AuthorizationCodeLifetime))
.SetClaim(Claims.Private.AuthorizationId, GetProperty(properties, Properties.InternalAuthorizationId))
.SetClaim(Claims.Private.CodeChallenge, GetProperty(properties, Properties.CodeChallenge))
.SetClaim(Claims.Private.CodeChallengeMethod, GetProperty(properties, Properties.CodeChallengeMethod))
.SetClaim(Claims.Private.IdentityTokenLifetime, GetProperty(properties, Properties.IdentityTokenLifetime))
.SetClaim(Claims.Private.RedirectUri, GetProperty(properties, Properties.OriginalRedirectUri))
.SetClaim(Claims.Private.RefreshTokenLifetime, GetProperty(properties, Properties.RefreshTokenLifetime))
.SetClaim(Claims.Private.TokenId, GetProperty(properties, Properties.InternalTokenId))
// Note: since the data format relies on a data protector using different "purposes" strings
// per token type, the token processed at this stage is guaranteed to be of the expected type.

1
src/OpenIddict.Server/OpenIddictServerExtensions.cs

@ -45,6 +45,7 @@ namespace Microsoft.Extensions.DependencyInjection
// Register the built-in filters used by the default OpenIddict server event handlers.
builder.Services.TryAddSingleton<RequireAccessTokenIncluded>();
builder.Services.TryAddSingleton<RequireAuthorizationCodeIncluded>();
builder.Services.TryAddSingleton<RequireAuthorizationStorageEnabled>();
builder.Services.TryAddSingleton<RequireClientIdParameter>();
builder.Services.TryAddSingleton<RequireDegradedModeDisabled>();
builder.Services.TryAddSingleton<RequireEndpointPermissionsEnabled>();

16
src/OpenIddict.Server/OpenIddictServerHandlerFilters.cs

@ -47,6 +47,22 @@ namespace OpenIddict.Server
}
}
/// <summary>
/// Represents a filter that excludes the associated handlers if authorization storage was not enabled.
/// </summary>
public class RequireAuthorizationStorageEnabled : IOpenIddictServerHandlerFilter<BaseContext>
{
public ValueTask<bool> IsActiveAsync([NotNull] BaseContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
return new ValueTask<bool>(!context.Options.DisableAuthorizationStorage);
}
}
/// <summary>
/// Represents a filter that excludes the associated handlers when no client identifier is received.
/// </summary>

62
src/OpenIddict.Server/OpenIddictServerHandlers.Exchange.cs

@ -60,6 +60,7 @@ namespace OpenIddict.Server
ValidateRedirectUri.Descriptor,
ValidateCodeVerifier.Descriptor,
ValidateGrantedScopes.Descriptor,
ValidateAuthorization.Descriptor,
/*
* Token request handling:
@ -1687,6 +1688,67 @@ namespace OpenIddict.Server
}
}
/// <summary>
/// Contains the logic responsible of rejecting token requests that use an authorization code
/// or refresh token whose associated authorization is no longer valid (e.g was revoked).
/// Note: this handler is not used when the degraded mode is enabled.
/// </summary>
public class ValidateAuthorization : IOpenIddictServerHandler<ValidateTokenRequestContext>
{
private readonly IOpenIddictAuthorizationManager _authorizationManager;
public ValidateAuthorization() => throw new InvalidOperationException(new StringBuilder()
.AppendLine("The core services must be registered when enabling the OpenIddict server feature.")
.Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ")
.AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.")
.Append("Alternatively, you can disable the built-in database-based server features by enabling ")
.Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.")
.ToString());
public ValidateAuthorization([NotNull] IOpenIddictAuthorizationManager authorizationManager)
=> _authorizationManager = authorizationManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateTokenRequestContext>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireAuthorizationStorageEnabled>()
.UseScopedHandler<ValidateAuthorization>()
.SetOrder(ValidateGrantedScopes.Descriptor.Order + 1_000)
.Build();
public async ValueTask HandleAsync([NotNull] ValidateTokenRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var identifier = context.Principal.GetInternalAuthorizationId();
if (string.IsNullOrEmpty(identifier))
{
return;
}
var authorization = await _authorizationManager.FindByIdAsync(identifier);
if (authorization == null || !await _authorizationManager.IsValidAsync(authorization))
{
context.Logger.LogError("The token '{Identifier}' was rejected because the associated " +
"authorization was no longer valid.", context.Principal.GetPublicTokenId());
context.Reject(
error: Errors.InvalidGrant,
description: context.Request.IsAuthorizationCodeGrantType() ?
"The authorization associated with the authorization code is no longer valid." :
"The authorization associated with the refresh token is no longer valid.");
return;
}
}
}
/// <summary>
/// Contains the logic responsible of attaching the principal extracted
/// from the authorization code/refresh token to the event context.

62
src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs

@ -48,6 +48,7 @@ namespace OpenIddict.Server
ValidateEndpointPermissions.Descriptor,
ValidateToken.Descriptor,
ValidateAuthorizedParty.Descriptor,
ValidateAuthorization.Descriptor,
/*
* Introspection request handling:
@ -918,6 +919,65 @@ namespace OpenIddict.Server
}
}
/// <summary>
/// Contains the logic responsible of rejecting introspection requests that use
/// a token whose associated authorization is no longer valid (e.g was revoked).
/// Note: this handler is not used when the degraded mode is enabled.
/// </summary>
public class ValidateAuthorization : IOpenIddictServerHandler<ValidateIntrospectionRequestContext>
{
private readonly IOpenIddictAuthorizationManager _authorizationManager;
public ValidateAuthorization() => throw new InvalidOperationException(new StringBuilder()
.AppendLine("The core services must be registered when enabling the OpenIddict server feature.")
.Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ")
.AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.")
.Append("Alternatively, you can disable the built-in database-based server features by enabling ")
.Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.")
.ToString());
public ValidateAuthorization([NotNull] IOpenIddictAuthorizationManager authorizationManager)
=> _authorizationManager = authorizationManager;
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ValidateIntrospectionRequestContext>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireAuthorizationStorageEnabled>()
.UseScopedHandler<ValidateAuthorization>()
.SetOrder(ValidateAuthorizedParty.Descriptor.Order + 1_000)
.Build();
public async ValueTask HandleAsync([NotNull] ValidateIntrospectionRequestContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
var identifier = context.Principal.GetInternalAuthorizationId();
if (string.IsNullOrEmpty(identifier))
{
return;
}
var authorization = await _authorizationManager.FindByIdAsync(identifier);
if (authorization == null || !await _authorizationManager.IsValidAsync(authorization))
{
context.Logger.LogError("The token '{Identifier}' was rejected because the associated " +
"authorization was no longer valid.", context.Principal.GetPublicTokenId());
context.Reject(
error: Errors.InvalidGrant,
description: "The authorization associated with the token is no longer valid.");
return;
}
}
}
/// <summary>
/// Contains the logic responsible of attaching the principal
/// extracted from the introspected token to the event context.
@ -984,7 +1044,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
context.TokenId = context.Principal.GetTokenId();
context.TokenId = context.Principal.GetPublicTokenId();
context.TokenUsage = context.Principal.GetTokenUsage();
context.Subject = context.Principal.GetClaim(Claims.Subject);

2
src/OpenIddict.Server/OpenIddictServerHandlers.Serialization.cs

@ -208,6 +208,8 @@ namespace OpenIddict.Server
{
context.Logger.LogTrace("The token '{Token}' could not be validated.", context.Token);
}
return default;
}
var assertion = ((JsonWebToken) result.SecurityToken)?.InnerToken ?? (JsonWebToken) result.SecurityToken;

122
src/OpenIddict.Server/OpenIddictServerHandlers.cs

@ -45,6 +45,7 @@ namespace OpenIddict.Server
AttachDefaultPresenters.Descriptor,
InferResources.Descriptor,
EvaluateReturnedTokens.Descriptor,
AttachAuthorization.Descriptor,
AttachAccessToken.Descriptor,
AttachAuthorizationCode.Descriptor,
AttachRefreshToken.Descriptor,
@ -428,6 +429,117 @@ namespace OpenIddict.Server
}
}
/// <summary>
/// Contains the logic responsible of creating an ad-hoc authorization, if necessary.
/// Note: this handler is not used when the degraded mode is enabled.
/// </summary>
public class AttachAuthorization : IOpenIddictServerHandler<ProcessSigninContext>
{
private readonly IOpenIddictApplicationManager _applicationManager;
private readonly IOpenIddictAuthorizationManager _authorizationManager;
public AttachAuthorization() => throw new InvalidOperationException(new StringBuilder()
.AppendLine("The core services must be registered when enabling the OpenIddict server feature.")
.Append("To register the OpenIddict core services, reference the 'OpenIddict.Core' package ")
.AppendLine("and call 'services.AddOpenIddict().AddCore()' from 'ConfigureServices'.")
.Append("Alternatively, you can disable the built-in database-based server features by enabling ")
.Append("the degraded mode with 'services.AddOpenIddict().AddServer().EnableDegradedMode()'.")
.ToString());
public AttachAuthorization(
[NotNull] IOpenIddictApplicationManager applicationManager,
[NotNull] IOpenIddictAuthorizationManager authorizationManager)
{
_applicationManager = applicationManager;
_authorizationManager = authorizationManager;
}
/// <summary>
/// Gets the default descriptor definition assigned to this handler.
/// </summary>
public static OpenIddictServerHandlerDescriptor Descriptor { get; }
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSigninContext>()
.AddFilter<RequireDegradedModeDisabled>()
.AddFilter<RequireAuthorizationStorageEnabled>()
.UseScopedHandler<AttachAuthorization>()
.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 1_000)
.Build();
/// <summary>
/// Processes the event.
/// </summary>
/// <param name="context">The context associated with the event to process.</param>
/// <returns>
/// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
/// </returns>
public async ValueTask HandleAsync([NotNull] ProcessSigninContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
// If no authorization code or refresh token is returned, don't create an authorization.
if (!context.IncludeAuthorizationCode && !context.IncludeRefreshToken)
{
return;
}
// If an authorization identifier was explicitly specified, don't create an ad-hoc authorization.
if (!string.IsNullOrEmpty(context.Principal.GetInternalAuthorizationId()))
{
return;
}
var descriptor = new OpenIddictAuthorizationDescriptor
{
Principal = context.Principal,
Status = Statuses.Valid,
Subject = context.Principal.GetClaim(Claims.Subject),
Type = AuthorizationTypes.AdHoc
};
descriptor.Scopes.UnionWith(context.Principal.GetScopes());
// If the client application is known, associate it to the authorization.
if (!string.IsNullOrEmpty(context.Request.ClientId))
{
var application = await _applicationManager.FindByClientIdAsync(context.Request.ClientId);
if (application == null)
{
throw new InvalidOperationException("The application entry cannot be found in the database.");
}
descriptor.ApplicationId = await _applicationManager.GetIdAsync(application);
}
var authorization = await _authorizationManager.CreateAsync(descriptor);
if (authorization == null)
{
return;
}
var identifier = await _authorizationManager.GetIdAsync(authorization);
if (string.IsNullOrEmpty(context.Request.ClientId))
{
context.Logger.LogInformation("An ad hoc authorization was automatically created and " +
"associated with an unknown application: {Identifier}.", identifier);
}
else
{
context.Logger.LogInformation("An ad hoc authorization was automatically created and " +
"associated with the '{ClientId}' application: {Identifier}.",
context.Request.ClientId, identifier);
}
// Attach the unique identifier of the ad hoc authorization to the authentication principal
// so that it is attached to all the derived tokens, allowing batched revocations support.
context.Principal.SetInternalAuthorizationId(identifier);
}
}
/// <summary>
/// Contains the logic responsible of generating and attaching an access token.
/// </summary>
@ -445,7 +557,7 @@ namespace OpenIddict.Server
= OpenIddictServerHandlerDescriptor.CreateBuilder<ProcessSigninContext>()
.AddFilter<RequireAccessTokenIncluded>()
.UseScopedHandler<AttachAccessToken>()
.SetOrder(EvaluateReturnedTokens.Descriptor.Order + 1_000)
.SetOrder(AttachAuthorization.Descriptor.Order + 1_000)
.Build();
/// <summary>
@ -496,7 +608,7 @@ namespace OpenIddict.Server
claim.Properties.Remove(OpenIddictConstants.Properties.Destinations);
}
principal.SetTokenId(Guid.NewGuid().ToString()).SetCreationDate(DateTimeOffset.UtcNow);
principal.SetPublicTokenId(Guid.NewGuid().ToString()).SetCreationDate(DateTimeOffset.UtcNow);
var lifetime = context.Principal.GetAccessTokenLifetime() ?? context.Options.AccessTokenLifetime;
if (lifetime.HasValue)
@ -583,7 +695,7 @@ namespace OpenIddict.Server
}
var principal = context.Principal.Clone(_ => true)
.SetTokenId(Guid.NewGuid().ToString())
.SetPublicTokenId(Guid.NewGuid().ToString())
.SetCreationDate(DateTimeOffset.UtcNow);
var lifetime = context.Principal.GetAuthorizationCodeLifetime() ?? context.Options.AuthorizationCodeLifetime;
@ -664,7 +776,7 @@ namespace OpenIddict.Server
}
var principal = context.Principal.Clone(_ => true)
.SetTokenId(Guid.NewGuid().ToString())
.SetPublicTokenId(Guid.NewGuid().ToString())
.SetCreationDate(DateTimeOffset.UtcNow);
var lifetime = context.Principal.GetRefreshTokenLifetime() ?? context.Options.RefreshTokenLifetime;
@ -753,7 +865,7 @@ namespace OpenIddict.Server
claim.Properties.Remove(OpenIddictConstants.Properties.Destinations);
}
principal.SetTokenId(Guid.NewGuid().ToString()).SetCreationDate(DateTimeOffset.UtcNow);
principal.SetPublicTokenId(Guid.NewGuid().ToString()).SetCreationDate(DateTimeOffset.UtcNow);
var lifetime = context.Principal.GetIdentityTokenLifetime() ?? context.Options.IdentityTokenLifetime;
if (lifetime.HasValue)

Loading…
Cancel
Save