Browse Source

Automatically map the scope/azp access token claims to their OpenIddict private claims equivalents

pull/879/head
Kévin Chalet 6 years ago
parent
commit
a25907cd52
  1. 28
      samples/Mvc.Server/Controllers/UserinfoController.cs
  2. 12
      src/OpenIddict.Abstractions/OpenIddictConstants.cs
  3. 28
      src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs
  4. 24
      src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs
  5. 15
      src/OpenIddict.Core/Managers/OpenIddictAuthorizationManager.cs
  6. 3
      src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs
  7. 29
      src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs
  8. 2
      src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionConstants.cs
  9. 3
      src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionFormatter.cs
  10. 32
      src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionHandlers.cs
  11. 2
      src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs
  12. 69
      src/OpenIddict.Server/OpenIddictServerHandlers.cs
  13. 2
      src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionConstants.cs
  14. 3
      src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionFormatter.cs
  15. 2
      src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionHandlers.cs
  16. 16
      src/OpenIddict.Validation/OpenIddictValidationHandlers.cs
  17. 112
      test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs
  18. 64
      test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Exchange.cs
  19. 6
      test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.cs

28
samples/Mvc.Server/Controllers/UserinfoController.cs

@ -7,6 +7,7 @@ using Microsoft.AspNetCore.Mvc;
using Mvc.Server.Models;
using OpenIddict.Abstractions;
using OpenIddict.Server.AspNetCore;
using static OpenIddict.Abstractions.OpenIddictConstants;
namespace Mvc.Server.Controllers
{
@ -15,9 +16,7 @@ namespace Mvc.Server.Controllers
private readonly UserManager<ApplicationUser> _userManager;
public UserinfoController(UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
}
=> _userManager = userManager;
//
// GET: /api/userinfo
@ -31,24 +30,25 @@ namespace Mvc.Server.Controllers
return Challenge(OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
}
var claims = new Dictionary<string, object>(StringComparer.Ordinal);
// Note: the "sub" claim is a mandatory claim and must be included in the JSON response.
claims[OpenIddictConstants.Claims.Subject] = await _userManager.GetUserIdAsync(user);
var claims = new Dictionary<string, object>(StringComparer.Ordinal)
{
// Note: the "sub" claim is a mandatory claim and must be included in the JSON response.
[Claims.Subject] = await _userManager.GetUserIdAsync(user)
};
if (User.HasClaim(OpenIddictConstants.Claims.Scope, OpenIddictConstants.Scopes.Email))
if (User.HasScope(Scopes.Email))
{
claims[OpenIddictConstants.Claims.Email] = await _userManager.GetEmailAsync(user);
claims[OpenIddictConstants.Claims.EmailVerified] = await _userManager.IsEmailConfirmedAsync(user);
claims[Claims.Email] = await _userManager.GetEmailAsync(user);
claims[Claims.EmailVerified] = await _userManager.IsEmailConfirmedAsync(user);
}
if (User.HasClaim(OpenIddictConstants.Claims.Scope, OpenIddictConstants.Scopes.Phone))
if (User.HasScope(Scopes.Phone))
{
claims[OpenIddictConstants.Claims.PhoneNumber] = await _userManager.GetPhoneNumberAsync(user);
claims[OpenIddictConstants.Claims.PhoneNumberVerified] = await _userManager.IsPhoneNumberConfirmedAsync(user);
claims[Claims.PhoneNumber] = await _userManager.GetPhoneNumberAsync(user);
claims[Claims.PhoneNumberVerified] = await _userManager.IsPhoneNumberConfirmedAsync(user);
}
if (User.HasClaim(OpenIddictConstants.Claims.Scope, "roles"))
if (User.HasScope("roles"))
{
claims["roles"] = await _userManager.GetRolesAsync(user);
}

12
src/OpenIddict.Abstractions/OpenIddictConstants.cs

@ -103,7 +103,7 @@ namespace OpenIddict.Abstractions
public const string Resources = "oi_rsrc";
public const string Scopes = "oi_scp";
public const string TokenId = "oi_tkn_id";
public const string TokenUsage = "oi_tkn_use";
public const string TokenType = "oi_tkn_typ";
public const string UserCodeLifetime = "oi_usrc_lft";
}
}
@ -428,15 +428,5 @@ namespace OpenIddict.Abstractions
{
public const string Bearer = "Bearer";
}
public static class TokenUsages
{
public const string AccessToken = "access_token";
public const string AuthorizationCode = "authorization_code";
public const string DeviceCode = "device_code";
public const string IdToken = "id_token";
public const string RefreshToken = "refresh_token";
public const string UserCode = "user_code";
}
}
}

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

@ -1359,12 +1359,12 @@ namespace OpenIddict.Abstractions
=> principal.GetClaim(Claims.Private.TokenId);
/// <summary>
/// Gets the token usage associated with the claims principal.
/// Gets the token type associated with the claims principal.
/// </summary>
/// <param name="principal">The claims principal.</param>
/// <returns>The token usage or <c>null</c> if the claim cannot be found.</returns>
public static string GetTokenUsage([NotNull] this ClaimsPrincipal principal)
=> principal.GetClaim(Claims.Private.TokenUsage);
/// <returns>The token type or <c>null</c> if the claim cannot be found.</returns>
public static string GetTokenType([NotNull] this ClaimsPrincipal principal)
=> principal.GetClaim(Claims.Private.TokenType);
/// <summary>
/// Gets a boolean value indicating whether the claims principal corresponds to an access token.
@ -1378,7 +1378,7 @@ namespace OpenIddict.Abstractions
throw new ArgumentNullException(nameof(principal));
}
return string.Equals(principal.GetTokenUsage(), TokenUsages.AccessToken, StringComparison.OrdinalIgnoreCase);
return string.Equals(principal.GetTokenType(), TokenTypeHints.AccessToken, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
@ -1393,7 +1393,7 @@ namespace OpenIddict.Abstractions
throw new ArgumentNullException(nameof(principal));
}
return string.Equals(principal.GetTokenUsage(), TokenUsages.AuthorizationCode, StringComparison.OrdinalIgnoreCase);
return string.Equals(principal.GetTokenType(), TokenTypeHints.AuthorizationCode, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
@ -1408,7 +1408,7 @@ namespace OpenIddict.Abstractions
throw new ArgumentNullException(nameof(principal));
}
return string.Equals(principal.GetTokenUsage(), TokenUsages.DeviceCode, StringComparison.OrdinalIgnoreCase);
return string.Equals(principal.GetTokenType(), TokenTypeHints.DeviceCode, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
@ -1423,7 +1423,7 @@ namespace OpenIddict.Abstractions
throw new ArgumentNullException(nameof(principal));
}
return string.Equals(principal.GetTokenUsage(), TokenUsages.IdToken, StringComparison.OrdinalIgnoreCase);
return string.Equals(principal.GetTokenType(), TokenTypeHints.IdToken, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
@ -1438,7 +1438,7 @@ namespace OpenIddict.Abstractions
throw new ArgumentNullException(nameof(principal));
}
return string.Equals(principal.GetTokenUsage(), TokenUsages.RefreshToken, StringComparison.OrdinalIgnoreCase);
return string.Equals(principal.GetTokenType(), TokenTypeHints.RefreshToken, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
@ -1453,7 +1453,7 @@ namespace OpenIddict.Abstractions
throw new ArgumentNullException(nameof(principal));
}
return string.Equals(principal.GetTokenUsage(), TokenUsages.UserCode, StringComparison.OrdinalIgnoreCase);
return string.Equals(principal.GetTokenType(), TokenTypeHints.UserCode, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
@ -1887,13 +1887,13 @@ namespace OpenIddict.Abstractions
=> principal.SetClaim(Claims.Private.TokenId, identifier);
/// <summary>
/// Sets the token usage associated with the claims principal.
/// Sets the token type associated with the claims principal.
/// </summary>
/// <param name="principal">The claims principal.</param>
/// <param name="usage">The token usage to store.</param>
/// <param name="type">The token type to store.</param>
/// <returns>The claims principal.</returns>
public static ClaimsPrincipal SetTokenUsage([NotNull] this ClaimsPrincipal principal, string usage)
=> principal.SetClaim(Claims.Private.TokenUsage, usage);
public static ClaimsPrincipal SetTokenType([NotNull] this ClaimsPrincipal principal, string type)
=> principal.SetClaim(Claims.Private.TokenType, type);
private static IEnumerable<string> GetValues(string source, char[] separators)
{

24
src/OpenIddict.Core/Managers/OpenIddictApplicationManager.cs

@ -18,6 +18,7 @@ using JetBrains.Annotations;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using OpenIddict.Abstractions;
using static OpenIddict.Abstractions.OpenIddictConstants;
#if !SUPPORTS_KEY_DERIVATION_WITH_SPECIFIED_HASH_ALGORITHM
using Org.BouncyCastle.Crypto;
@ -139,8 +140,7 @@ namespace OpenIddict.Core
if (string.IsNullOrEmpty(type))
{
await Store.SetClientTypeAsync(application, string.IsNullOrEmpty(secret) ?
OpenIddictConstants.ClientTypes.Public :
OpenIddictConstants.ClientTypes.Confidential, cancellationToken);
ClientTypes.Public : ClientTypes.Confidential, cancellationToken);
}
// If a client secret was provided, obfuscate it.
@ -479,7 +479,7 @@ namespace OpenIddict.Core
var type = await Store.GetConsentTypeAsync(application, cancellationToken);
if (string.IsNullOrEmpty(type))
{
return OpenIddictConstants.ConsentTypes.Explicit;
return ConsentTypes.Explicit;
}
return type;
@ -669,7 +669,7 @@ namespace OpenIddict.Core
return false;
}
return string.Equals(type, OpenIddictConstants.ClientTypes.Confidential, StringComparison.OrdinalIgnoreCase);
return string.Equals(type, ClientTypes.Confidential, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
@ -691,7 +691,7 @@ namespace OpenIddict.Core
return false;
}
return string.Equals(type, OpenIddictConstants.ClientTypes.Hybrid, StringComparison.OrdinalIgnoreCase);
return string.Equals(type, ClientTypes.Hybrid, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
@ -714,7 +714,7 @@ namespace OpenIddict.Core
return true;
}
return string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase);
return string.Equals(type, ClientTypes.Public, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
@ -1027,9 +1027,9 @@ namespace OpenIddict.Core
else
{
// Ensure the application type is supported by the manager.
if (!string.Equals(type, OpenIddictConstants.ClientTypes.Confidential, StringComparison.OrdinalIgnoreCase) &&
!string.Equals(type, OpenIddictConstants.ClientTypes.Hybrid, StringComparison.OrdinalIgnoreCase) &&
!string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase))
if (!string.Equals(type, ClientTypes.Confidential, StringComparison.OrdinalIgnoreCase) &&
!string.Equals(type, ClientTypes.Hybrid, StringComparison.OrdinalIgnoreCase) &&
!string.Equals(type, ClientTypes.Public, StringComparison.OrdinalIgnoreCase))
{
yield return new ValidationResult("Only 'confidential', 'hybrid' or 'public' applications are " +
"supported by the default application manager.");
@ -1037,15 +1037,13 @@ namespace OpenIddict.Core
// Ensure a client secret was specified if the client is a confidential application.
var secret = await Store.GetClientSecretAsync(application, cancellationToken);
if (string.IsNullOrEmpty(secret) &&
string.Equals(type, OpenIddictConstants.ClientTypes.Confidential, StringComparison.OrdinalIgnoreCase))
if (string.IsNullOrEmpty(secret) && string.Equals(type, ClientTypes.Confidential, StringComparison.OrdinalIgnoreCase))
{
yield return new ValidationResult("The client secret cannot be null or empty for a confidential application.");
}
// Ensure no client secret was specified if the client is a public application.
else if (!string.IsNullOrEmpty(secret) &&
string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase))
else if (!string.IsNullOrEmpty(secret) && string.Equals(type, ClientTypes.Public, StringComparison.OrdinalIgnoreCase))
{
yield return new ValidationResult("A client secret cannot be associated with a public application.");
}

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

@ -18,6 +18,7 @@ using JetBrains.Annotations;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using OpenIddict.Abstractions;
using static OpenIddict.Abstractions.OpenIddictConstants;
using static OpenIddict.Abstractions.OpenIddictExceptions;
namespace OpenIddict.Core
@ -110,7 +111,7 @@ namespace OpenIddict.Core
// If no status was explicitly specified, assume that the authorization is valid.
if (string.IsNullOrEmpty(await Store.GetStatusAsync(authorization, cancellationToken)))
{
await Store.SetStatusAsync(authorization, OpenIddictConstants.Statuses.Valid, cancellationToken);
await Store.SetStatusAsync(authorization, Statuses.Valid, cancellationToken);
}
var results = await ValidateAsync(authorization, cancellationToken).ToListAsync(cancellationToken);
@ -204,7 +205,7 @@ namespace OpenIddict.Core
{
ApplicationId = client,
Principal = principal,
Status = OpenIddictConstants.Statuses.Valid,
Status = Statuses.Valid,
Subject = subject,
Type = type
};
@ -878,12 +879,12 @@ namespace OpenIddict.Core
}
var status = await Store.GetStatusAsync(authorization, cancellationToken);
if (string.Equals(status, OpenIddictConstants.Statuses.Revoked, StringComparison.OrdinalIgnoreCase))
if (string.Equals(status, Statuses.Revoked, StringComparison.OrdinalIgnoreCase))
{
return true;
}
await Store.SetStatusAsync(authorization, OpenIddictConstants.Statuses.Revoked, cancellationToken);
await Store.SetStatusAsync(authorization, Statuses.Revoked, cancellationToken);
try
{
@ -997,8 +998,8 @@ namespace OpenIddict.Core
yield return new ValidationResult("The authorization type cannot be null or empty.");
}
else if (!string.Equals(type, OpenIddictConstants.AuthorizationTypes.AdHoc, StringComparison.OrdinalIgnoreCase) &&
!string.Equals(type, OpenIddictConstants.AuthorizationTypes.Permanent, StringComparison.OrdinalIgnoreCase))
else if (!string.Equals(type, AuthorizationTypes.AdHoc, StringComparison.OrdinalIgnoreCase) &&
!string.Equals(type, AuthorizationTypes.Permanent, StringComparison.OrdinalIgnoreCase))
{
yield return new ValidationResult("The specified authorization type is not supported by the default token manager.");
}
@ -1018,7 +1019,7 @@ namespace OpenIddict.Core
break;
}
if (scope.Contains(OpenIddictConstants.Separators.Space[0]))
if (scope.Contains(Separators.Space[0]))
{
yield return new ValidationResult("Scopes cannot contain spaces.");

3
src/OpenIddict.Core/Managers/OpenIddictScopeManager.cs

@ -17,6 +17,7 @@ using JetBrains.Annotations;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using OpenIddict.Abstractions;
using static OpenIddict.Abstractions.OpenIddictConstants;
namespace OpenIddict.Core
{
@ -688,7 +689,7 @@ namespace OpenIddict.Core
yield return new ValidationResult("The scope name cannot be null or empty.");
}
else if (name.Contains(OpenIddictConstants.Separators.Space[0]))
else if (name.Contains(Separators.Space[0]))
{
yield return new ValidationResult("The scope name cannot contain spaces.");
}

29
src/OpenIddict.Core/Managers/OpenIddictTokenManager.cs

@ -18,6 +18,7 @@ using JetBrains.Annotations;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using OpenIddict.Abstractions;
using static OpenIddict.Abstractions.OpenIddictConstants;
using static OpenIddict.Abstractions.OpenIddictExceptions;
namespace OpenIddict.Core
@ -110,7 +111,7 @@ namespace OpenIddict.Core
// If no status was explicitly specified, assume that the token is valid.
if (string.IsNullOrEmpty(await Store.GetStatusAsync(token, cancellationToken)))
{
await Store.SetStatusAsync(token, OpenIddictConstants.Statuses.Valid, cancellationToken);
await Store.SetStatusAsync(token, Statuses.Valid, cancellationToken);
}
// If a reference identifier was set, obfuscate it.
@ -1022,12 +1023,12 @@ namespace OpenIddict.Core
}
var status = await Store.GetStatusAsync(token, cancellationToken);
if (string.Equals(status, OpenIddictConstants.Statuses.Redeemed, StringComparison.OrdinalIgnoreCase))
if (string.Equals(status, Statuses.Redeemed, StringComparison.OrdinalIgnoreCase))
{
return true;
}
await Store.SetStatusAsync(token, OpenIddictConstants.Statuses.Redeemed, cancellationToken);
await Store.SetStatusAsync(token, Statuses.Redeemed, cancellationToken);
try
{
@ -1070,12 +1071,12 @@ namespace OpenIddict.Core
}
var status = await Store.GetStatusAsync(token, cancellationToken);
if (string.Equals(status, OpenIddictConstants.Statuses.Rejected, StringComparison.OrdinalIgnoreCase))
if (string.Equals(status, Statuses.Rejected, StringComparison.OrdinalIgnoreCase))
{
return true;
}
await Store.SetStatusAsync(token, OpenIddictConstants.Statuses.Rejected, cancellationToken);
await Store.SetStatusAsync(token, Statuses.Rejected, cancellationToken);
try
{
@ -1118,12 +1119,12 @@ namespace OpenIddict.Core
}
var status = await Store.GetStatusAsync(token, cancellationToken);
if (string.Equals(status, OpenIddictConstants.Statuses.Revoked, StringComparison.OrdinalIgnoreCase))
if (string.Equals(status, Statuses.Revoked, StringComparison.OrdinalIgnoreCase))
{
return true;
}
await Store.SetStatusAsync(token, OpenIddictConstants.Statuses.Revoked, cancellationToken);
await Store.SetStatusAsync(token, Statuses.Revoked, cancellationToken);
try
{
@ -1266,11 +1267,11 @@ namespace OpenIddict.Core
yield return new ValidationResult("The token type cannot be null or empty.");
}
else if (!string.Equals(type, OpenIddictConstants.TokenUsages.AccessToken, StringComparison.OrdinalIgnoreCase) &&
!string.Equals(type, OpenIddictConstants.TokenUsages.AuthorizationCode, StringComparison.OrdinalIgnoreCase) &&
!string.Equals(type, OpenIddictConstants.TokenUsages.DeviceCode, StringComparison.OrdinalIgnoreCase) &&
!string.Equals(type, OpenIddictConstants.TokenUsages.RefreshToken, StringComparison.OrdinalIgnoreCase) &&
!string.Equals(type, OpenIddictConstants.TokenUsages.UserCode, StringComparison.OrdinalIgnoreCase))
else if (!string.Equals(type, TokenTypeHints.AccessToken, StringComparison.OrdinalIgnoreCase) &&
!string.Equals(type, TokenTypeHints.AuthorizationCode, StringComparison.OrdinalIgnoreCase) &&
!string.Equals(type, TokenTypeHints.DeviceCode, StringComparison.OrdinalIgnoreCase) &&
!string.Equals(type, TokenTypeHints.RefreshToken, StringComparison.OrdinalIgnoreCase) &&
!string.Equals(type, TokenTypeHints.UserCode, StringComparison.OrdinalIgnoreCase))
{
yield return new ValidationResult("The specified token type is not supported by the default token manager.");
}
@ -1281,8 +1282,8 @@ namespace OpenIddict.Core
}
if (string.IsNullOrEmpty(await Store.GetSubjectAsync(token, cancellationToken)) &&
!string.Equals(type, OpenIddictConstants.TokenUsages.DeviceCode, StringComparison.OrdinalIgnoreCase) &&
!string.Equals(type, OpenIddictConstants.TokenUsages.UserCode, StringComparison.OrdinalIgnoreCase))
!string.Equals(type, TokenTypeHints.DeviceCode, StringComparison.OrdinalIgnoreCase) &&
!string.Equals(type, TokenTypeHints.UserCode, StringComparison.OrdinalIgnoreCase))
{
yield return new ValidationResult("The subject cannot be null or empty.");
}

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

@ -27,8 +27,6 @@ namespace OpenIddict.Server.DataProtection
public const string RefreshTokenLifetime = ".refresh_token_lifetime";
public const string Resources = ".resources";
public const string Scopes = ".scopes";
public const string TokenId = ".token_id";
public const string TokenUsage = ".token_usage";
}
public static class Purposes

3
src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionFormatter.cs

@ -44,6 +44,7 @@ namespace OpenIddict.Server.DataProtection
.SetCreationDate(GetDateProperty(properties, Properties.Issued))
.SetExpirationDate(GetDateProperty(properties, Properties.Expires))
.SetPresenters(GetArrayProperty(properties, Properties.Presenters))
.SetResources(GetArrayProperty(properties, Properties.Resources))
.SetScopes(GetArrayProperty(properties, Properties.Scopes))
.SetClaim(Claims.Private.AccessTokenLifetime, GetProperty(properties, Properties.AccessTokenLifetime))
@ -219,6 +220,7 @@ namespace OpenIddict.Server.DataProtection
SetArrayProperty(properties, Properties.Audiences, principal.GetAudiences());
SetArrayProperty(properties, Properties.Presenters, principal.GetPresenters());
SetArrayProperty(properties, Properties.Resources, principal.GetResources());
SetArrayProperty(properties, Properties.Scopes, principal.GetScopes());
// Copy the principal and exclude the claim that were mapped to authentication properties.
@ -238,6 +240,7 @@ namespace OpenIddict.Server.DataProtection
Claims.Private.Presenters => false,
Claims.Private.RedirectUri => false,
Claims.Private.RefreshTokenLifetime => false,
Claims.Private.Resources => false,
Claims.Private.Scopes => false,
Claims.Private.TokenId => false,

32
src/OpenIddict.Server.DataProtection/OpenIddictServerDataProtectionHandlers.cs

@ -86,11 +86,11 @@ namespace OpenIddict.Server.DataProtection
// If the token cannot be validated, don't return an error to allow another handle to validate it.
var principal = !string.IsNullOrEmpty(context.TokenType) ?
ValidateToken(context.Token, context.TokenType) :
ValidateToken(context.Token, TokenUsages.AccessToken) ??
ValidateToken(context.Token, TokenUsages.RefreshToken) ??
ValidateToken(context.Token, TokenUsages.AuthorizationCode) ??
ValidateToken(context.Token, TokenUsages.DeviceCode) ??
ValidateToken(context.Token, TokenUsages.UserCode);
ValidateToken(context.Token, TokenTypeHints.AccessToken) ??
ValidateToken(context.Token, TokenTypeHints.RefreshToken) ??
ValidateToken(context.Token, TokenTypeHints.AuthorizationCode) ??
ValidateToken(context.Token, TokenTypeHints.DeviceCode) ??
ValidateToken(context.Token, TokenTypeHints.UserCode);
if (principal == null)
{
return default;
@ -108,26 +108,26 @@ namespace OpenIddict.Server.DataProtection
// Create a Data Protection protector using the provider registered in the options.
var protector = _options.CurrentValue.DataProtectionProvider.CreateProtector(type switch
{
TokenUsages.AccessToken when context.Options.UseReferenceAccessTokens
TokenTypeHints.AccessToken when context.Options.UseReferenceAccessTokens
=> new[] { Handlers.Server, Formats.AccessToken, Features.ReferenceTokens, Schemes.Server },
TokenUsages.AuthorizationCode when !context.Options.DisableTokenStorage
TokenTypeHints.AuthorizationCode when !context.Options.DisableTokenStorage
=> new[] { Handlers.Server, Formats.AuthorizationCode, Features.ReferenceTokens, Schemes.Server },
TokenUsages.DeviceCode when !context.Options.DisableTokenStorage
TokenTypeHints.DeviceCode when !context.Options.DisableTokenStorage
=> new[] { Handlers.Server, Formats.DeviceCode, Features.ReferenceTokens, Schemes.Server },
TokenUsages.RefreshToken when !context.Options.DisableTokenStorage
TokenTypeHints.RefreshToken when !context.Options.DisableTokenStorage
=> new[] { Handlers.Server, Formats.RefreshToken, Features.ReferenceTokens, Schemes.Server },
TokenUsages.UserCode when !context.Options.DisableTokenStorage
TokenTypeHints.UserCode when !context.Options.DisableTokenStorage
=> new[] { Handlers.Server, Formats.UserCode, Features.ReferenceTokens, Schemes.Server },
TokenUsages.AccessToken => new[] { Handlers.Server, Formats.AccessToken, Schemes.Server },
TokenUsages.AuthorizationCode => new[] { Handlers.Server, Formats.AuthorizationCode, Schemes.Server },
TokenUsages.DeviceCode => new[] { Handlers.Server, Formats.DeviceCode, Schemes.Server },
TokenUsages.RefreshToken => new[] { Handlers.Server, Formats.RefreshToken, Schemes.Server },
TokenUsages.UserCode => new[] { Handlers.Server, Formats.UserCode, Schemes.Server },
TokenTypeHints.AccessToken => new[] { Handlers.Server, Formats.AccessToken, Schemes.Server },
TokenTypeHints.AuthorizationCode => new[] { Handlers.Server, Formats.AuthorizationCode, Schemes.Server },
TokenTypeHints.DeviceCode => new[] { Handlers.Server, Formats.DeviceCode, Schemes.Server },
TokenTypeHints.RefreshToken => new[] { Handlers.Server, Formats.RefreshToken, Schemes.Server },
TokenTypeHints.UserCode => new[] { Handlers.Server, Formats.UserCode, Schemes.Server },
_ => throw new InvalidOperationException("The specified token type is not supported.")
});
@ -139,7 +139,7 @@ namespace OpenIddict.Server.DataProtection
// 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.
return _options.CurrentValue.Formatter.ReadToken(reader)?.SetClaim(Claims.Private.TokenUsage, type);
return _options.CurrentValue.Formatter.ReadToken(reader)?.SetClaim(Claims.Private.TokenType, type);
}
catch (Exception exception)

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

@ -1035,7 +1035,7 @@ namespace OpenIddict.Server
}
context.TokenId = context.Principal.GetClaim(Claims.JwtId);
context.TokenUsage = context.Principal.GetTokenUsage();
context.TokenUsage = context.Principal.GetTokenType();
context.Subject = context.Principal.GetClaim(Claims.Subject);
context.IssuedAt = context.NotBefore = context.Principal.GetCreationDate();

69
src/OpenIddict.Server/OpenIddictServerHandlers.cs

@ -198,8 +198,8 @@ namespace OpenIddict.Server
var (token, type) = context.EndpointType switch
{
OpenIddictServerEndpointType.Authorization => (context.Request.IdTokenHint, TokenUsages.IdToken),
OpenIddictServerEndpointType.Logout => (context.Request.IdTokenHint, TokenUsages.IdToken),
OpenIddictServerEndpointType.Authorization => (context.Request.IdTokenHint, TokenTypeHints.IdToken),
OpenIddictServerEndpointType.Logout => (context.Request.IdTokenHint, TokenTypeHints.IdToken),
// Generic tokens received by the introspection and revocation can be of any type.
// Additional token type filtering is made by the endpoint themselves, if needed.
@ -207,15 +207,15 @@ namespace OpenIddict.Server
OpenIddictServerEndpointType.Revocation => (context.Request.Token, null),
OpenIddictServerEndpointType.Token when context.Request.IsAuthorizationCodeGrantType()
=> (context.Request.Code, TokenUsages.AuthorizationCode),
=> (context.Request.Code, TokenTypeHints.AuthorizationCode),
OpenIddictServerEndpointType.Token when context.Request.IsDeviceCodeGrantType()
=> (context.Request.DeviceCode, TokenUsages.DeviceCode),
=> (context.Request.DeviceCode, TokenTypeHints.DeviceCode),
OpenIddictServerEndpointType.Token when context.Request.IsRefreshTokenGrantType()
=> (context.Request.RefreshToken, TokenUsages.RefreshToken),
=> (context.Request.RefreshToken, TokenTypeHints.RefreshToken),
OpenIddictServerEndpointType.Userinfo => (context.Request.AccessToken, TokenUsages.AccessToken),
OpenIddictServerEndpointType.Userinfo => (context.Request.AccessToken, TokenTypeHints.AccessToken),
OpenIddictServerEndpointType.Verification => (context.Request.UserCode, TokenUsages.UserCode),
OpenIddictServerEndpointType.Verification => (context.Request.UserCode, TokenTypeHints.UserCode),
_ => (null, null)
};
@ -279,7 +279,7 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
if (!string.Equals(context.TokenType, TokenUsages.UserCode, StringComparison.OrdinalIgnoreCase))
if (!string.Equals(context.TokenType, TokenTypeHints.UserCode, StringComparison.OrdinalIgnoreCase))
{
return default;
}
@ -445,13 +445,13 @@ namespace OpenIddict.Server
{
context.TokenType switch
{
TokenUsages.AccessToken => JsonWebTokenTypes.AccessToken,
TokenUsages.IdToken => JsonWebTokenTypes.IdentityToken,
TokenTypeHints.AccessToken => JsonWebTokenTypes.AccessToken,
TokenTypeHints.IdToken => JsonWebTokenTypes.IdentityToken,
TokenUsages.AuthorizationCode => JsonWebTokenTypes.Private.AuthorizationCode,
TokenUsages.DeviceCode => JsonWebTokenTypes.Private.DeviceCode,
TokenUsages.RefreshToken => JsonWebTokenTypes.Private.RefreshToken,
TokenUsages.UserCode => JsonWebTokenTypes.Private.UserCode,
TokenTypeHints.AuthorizationCode => JsonWebTokenTypes.Private.AuthorizationCode,
TokenTypeHints.DeviceCode => JsonWebTokenTypes.Private.DeviceCode,
TokenTypeHints.RefreshToken => JsonWebTokenTypes.Private.RefreshToken,
TokenTypeHints.UserCode => JsonWebTokenTypes.Private.UserCode,
_ => throw new InvalidOperationException("The token type is not supported.")
}
@ -478,15 +478,15 @@ namespace OpenIddict.Server
context.Principal = new ClaimsPrincipal(result.ClaimsIdentity);
// Store the token type as a special private claim.
context.Principal.SetClaim(Claims.Private.TokenUsage, token.Typ switch
context.Principal.SetClaim(Claims.Private.TokenType, token.Typ switch
{
JsonWebTokenTypes.AccessToken => TokenUsages.AccessToken,
JsonWebTokenTypes.IdentityToken => TokenUsages.IdToken,
JsonWebTokenTypes.AccessToken => TokenTypeHints.AccessToken,
JsonWebTokenTypes.IdentityToken => TokenTypeHints.IdToken,
JsonWebTokenTypes.Private.AuthorizationCode => TokenUsages.AuthorizationCode,
JsonWebTokenTypes.Private.DeviceCode => TokenUsages.DeviceCode,
JsonWebTokenTypes.Private.RefreshToken => TokenUsages.RefreshToken,
JsonWebTokenTypes.Private.UserCode => TokenUsages.UserCode,
JsonWebTokenTypes.Private.AuthorizationCode => TokenTypeHints.AuthorizationCode,
JsonWebTokenTypes.Private.DeviceCode => TokenTypeHints.DeviceCode,
JsonWebTokenTypes.Private.RefreshToken => TokenTypeHints.RefreshToken,
JsonWebTokenTypes.Private.UserCode => TokenTypeHints.UserCode,
_ => throw new InvalidOperationException("The token type is not supported.")
});
@ -497,6 +497,19 @@ namespace OpenIddict.Server
context.Principal.SetDestinations(destinations);
}
if (context.Principal.IsAccessToken())
{
// Map the standardized "azp" and "scope" claims to their "oi_" equivalent so that
// the ClaimsPrincipal extensions exposed by OpenIddict return consistent results.
context.Principal.SetPresenters(context.Principal.GetClaims(Claims.AuthorizedParty));
// Note: starting in OpenIddict 3.0, the public "scope" claim is formatted
// as a unique space-separated string containing all the granted scopes.
// Visit https://tools.ietf.org/html/draft-ietf-oauth-access-token-jwt-03 for more information.
context.Principal.SetScopes(context.Principal.GetClaim(Claims.Scope)
?.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries));
}
context.Logger.LogTrace("The token '{Token}' was successfully validated and the following claims " +
"could be extracted: {Claims}.", context.Token, context.Principal.Claims);
@ -563,7 +576,7 @@ namespace OpenIddict.Server
.SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token))
.SetInternalAuthorizationId(await _tokenManager.GetAuthorizationIdAsync(token))
.SetInternalTokenId(await _tokenManager.GetIdAsync(token))
.SetClaim(Claims.Private.TokenUsage, await _tokenManager.GetTypeAsync(token));
.SetClaim(Claims.Private.TokenType, await _tokenManager.GetTypeAsync(token));
}
}
@ -801,7 +814,7 @@ namespace OpenIddict.Server
.SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token))
.SetInternalAuthorizationId(await _tokenManager.GetAuthorizationIdAsync(token))
.SetInternalTokenId(await _tokenManager.GetIdAsync(token))
.SetClaim(Claims.Private.TokenUsage, await _tokenManager.GetTypeAsync(token));
.SetClaim(Claims.Private.TokenType, await _tokenManager.GetTypeAsync(token));
async ValueTask TryRevokeAuthorizationChainAsync(string identifier)
{
@ -2791,7 +2804,7 @@ namespace OpenIddict.Server
ReferenceId = Base64UrlEncoder.Encode(data),
Status = Statuses.Valid,
Subject = context.AccessTokenPrincipal.GetClaim(Claims.Subject),
Type = TokenUsages.AccessToken
Type = TokenTypeHints.AccessToken
};
// If the client application is known, associate it with the token.
@ -2968,7 +2981,7 @@ namespace OpenIddict.Server
ReferenceId = Base64UrlEncoder.Encode(data),
Status = Statuses.Valid,
Subject = context.AuthorizationCodePrincipal.GetClaim(Claims.Subject),
Type = TokenUsages.AuthorizationCode
Type = TokenTypeHints.AuthorizationCode
};
// If the client application is known, associate it with the token.
@ -3150,7 +3163,7 @@ namespace OpenIddict.Server
ReferenceId = Base64UrlEncoder.Encode(data),
Status = Statuses.Inactive,
Subject = null, // Device codes are not bound to a user, which is not known until the user code is populated.
Type = TokenUsages.DeviceCode
Type = TokenTypeHints.DeviceCode
};
// If the client application is known, associate it with the token.
@ -3423,7 +3436,7 @@ namespace OpenIddict.Server
ReferenceId = Base64UrlEncoder.Encode(data),
Status = Statuses.Valid,
Subject = context.RefreshTokenPrincipal.GetClaim(Claims.Subject),
Type = TokenUsages.RefreshToken
Type = TokenTypeHints.RefreshToken
};
// If the client application is known, associate it with the token.
@ -3641,7 +3654,7 @@ namespace OpenIddict.Server
ReferenceId = builder.ToString(),
Status = Statuses.Valid,
Subject = null, // User codes are not bound to a user until authorization is granted.
Type = TokenUsages.UserCode
Type = TokenTypeHints.UserCode
};
// If the client application is known, associate it with the token.

2
src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionConstants.cs

@ -27,8 +27,6 @@ namespace OpenIddict.Validation.DataProtection
public const string RefreshTokenLifetime = ".refresh_token_lifetime";
public const string Resources = ".resources";
public const string Scopes = ".scopes";
public const string TokenId = ".token_id";
public const string TokenUsage = ".token_usage";
}
public static class Purposes

3
src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionFormatter.cs

@ -10,8 +10,8 @@ using System.Collections.Immutable;
using System.Globalization;
using System.IO;
using System.Security.Claims;
using JetBrains.Annotations;
using System.Text.Json;
using JetBrains.Annotations;
using OpenIddict.Abstractions;
using static OpenIddict.Abstractions.OpenIddictConstants;
using Properties = OpenIddict.Validation.DataProtection.OpenIddictValidationDataProtectionConstants.Properties;
@ -42,6 +42,7 @@ namespace OpenIddict.Validation.DataProtection
.SetCreationDate(GetDateProperty(properties, Properties.Issued))
.SetExpirationDate(GetDateProperty(properties, Properties.Expires))
.SetPresenters(GetArrayProperty(properties, Properties.Presenters))
.SetResources(GetArrayProperty(properties, Properties.Resources))
.SetScopes(GetArrayProperty(properties, Properties.Scopes))
.SetClaim(Claims.Private.AccessTokenLifetime, GetProperty(properties, Properties.AccessTokenLifetime))

2
src/OpenIddict.Validation.DataProtection/OpenIddictValidationDataProtectionHandlers.cs

@ -102,7 +102,7 @@ namespace OpenIddict.Validation.DataProtection
// 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.
context.Principal = principal.SetClaim(Claims.Private.TokenUsage, TokenUsages.AccessToken);
context.Principal = principal.SetClaim(Claims.Private.TokenType, TokenTypeHints.AccessToken);
context.Logger.LogTrace("The self-contained DP token '{Token}' was successfully validated and the following " +
"claims could be extracted: {Claims}.", context.Token, context.Principal.Claims);

16
src/OpenIddict.Validation/OpenIddictValidationHandlers.cs

@ -130,7 +130,7 @@ namespace OpenIddict.Validation
}
var type = await _tokenManager.GetTypeAsync(token);
if (!string.Equals(type, TokenUsages.AccessToken, StringComparison.OrdinalIgnoreCase))
if (!string.Equals(type, TokenTypeHints.AccessToken, StringComparison.OrdinalIgnoreCase))
{
context.Reject(
error: Errors.InvalidToken,
@ -221,7 +221,17 @@ namespace OpenIddict.Validation
// Attach the principal extracted from the token to the parent event context.
context.Principal = new ClaimsPrincipal(result.ClaimsIdentity);
context.Principal.SetClaim(Claims.Private.TokenUsage, TokenUsages.AccessToken);
context.Principal.SetClaim(Claims.Private.TokenType, TokenTypeHints.AccessToken);
// Map the standardized "azp" and "scope" claims to their "oi_" equivalent so that
// the ClaimsPrincipal extensions exposed by OpenIddict return consistent results.
context.Principal.SetPresenters(context.Principal.GetClaims(Claims.AuthorizedParty));
// Note: starting in OpenIddict 3.0, the public "scope" claim is formatted
// as a unique space-separated string containing all the granted scopes.
// Visit https://tools.ietf.org/html/draft-ietf-oauth-access-token-jwt-03 for more information.
context.Principal.SetScopes(context.Principal.GetClaim(Claims.Scope)
?.Split(Separators.Space, StringSplitOptions.RemoveEmptyEntries));
context.Logger.LogTrace("The self-contained JWT token '{Token}' was successfully validated and the following " +
"claims could be extracted: {Claims}.", context.Token, context.Principal.Claims);
@ -286,7 +296,7 @@ namespace OpenIddict.Validation
.SetExpirationDate(await _tokenManager.GetExpirationDateAsync(token))
.SetInternalAuthorizationId(await _tokenManager.GetAuthorizationIdAsync(token))
.SetInternalTokenId(await _tokenManager.GetIdAsync(token))
.SetClaim(Claims.Private.TokenUsage, await _tokenManager.GetTypeAsync(token));
.SetClaim(Claims.Private.TokenType, await _tokenManager.GetTypeAsync(token));
}
}

112
test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs

@ -1906,13 +1906,13 @@ namespace OpenIddict.Abstractions.Tests.Primitives
}
[Fact]
public void GetTokenUsage_ThrowsAnExceptionForNullPrincipal()
public void GetTokenType_ThrowsAnExceptionForNullPrincipal()
{
// Arrange
var principal = (ClaimsPrincipal) null;
// Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => principal.GetTokenUsage());
var exception = Assert.Throws<ArgumentNullException>(() => principal.GetTokenType());
Assert.Equal("principal", exception.ParamName);
}
@ -1920,16 +1920,16 @@ namespace OpenIddict.Abstractions.Tests.Primitives
[Theory]
[InlineData(null)]
[InlineData("access_token")]
public void GetTokenUsage_ReturnsExpectedResult(string usage)
public void GetTokenType_ReturnsExpectedResult(string type)
{
// Arrange
var identity = new ClaimsIdentity();
var principal = new ClaimsPrincipal(identity);
principal.SetClaim(Claims.Private.TokenUsage, usage);
principal.SetClaim(Claims.Private.TokenType, type);
// Act and assert
Assert.Equal(usage, principal.GetTokenUsage());
Assert.Equal(type, principal.GetTokenType());
}
[Fact]
@ -2203,19 +2203,19 @@ namespace OpenIddict.Abstractions.Tests.Primitives
[Theory]
[InlineData(null, false)]
[InlineData("unknown", false)]
[InlineData(TokenUsages.AccessToken, true)]
[InlineData(TokenUsages.AuthorizationCode, false)]
[InlineData(TokenUsages.DeviceCode, false)]
[InlineData(TokenUsages.IdToken, false)]
[InlineData(TokenUsages.RefreshToken, false)]
[InlineData(TokenUsages.UserCode, false)]
public void IsAccessToken_ReturnsExpectedResult(string usage, bool result)
[InlineData(TokenTypeHints.AccessToken, true)]
[InlineData(TokenTypeHints.AuthorizationCode, false)]
[InlineData(TokenTypeHints.DeviceCode, false)]
[InlineData(TokenTypeHints.IdToken, false)]
[InlineData(TokenTypeHints.RefreshToken, false)]
[InlineData(TokenTypeHints.UserCode, false)]
public void IsAccessToken_ReturnsExpectedResult(string type, bool result)
{
// Arrange
var identity = new ClaimsIdentity();
var principal = new ClaimsPrincipal(identity);
principal.SetClaim(Claims.Private.TokenUsage, usage);
principal.SetClaim(Claims.Private.TokenType, type);
// Act and assert
Assert.Equal(result, principal.IsAccessToken());
@ -2236,19 +2236,19 @@ namespace OpenIddict.Abstractions.Tests.Primitives
[Theory]
[InlineData(null, false)]
[InlineData("unknown", false)]
[InlineData(TokenUsages.AccessToken, false)]
[InlineData(TokenUsages.AuthorizationCode, true)]
[InlineData(TokenUsages.DeviceCode, false)]
[InlineData(TokenUsages.IdToken, false)]
[InlineData(TokenUsages.RefreshToken, false)]
[InlineData(TokenUsages.UserCode, false)]
public void IsAuthorizationCode_ReturnsExpectedResult(string usage, bool result)
[InlineData(TokenTypeHints.AccessToken, false)]
[InlineData(TokenTypeHints.AuthorizationCode, true)]
[InlineData(TokenTypeHints.DeviceCode, false)]
[InlineData(TokenTypeHints.IdToken, false)]
[InlineData(TokenTypeHints.RefreshToken, false)]
[InlineData(TokenTypeHints.UserCode, false)]
public void IsAuthorizationCode_ReturnsExpectedResult(string type, bool result)
{
// Arrange
var identity = new ClaimsIdentity();
var principal = new ClaimsPrincipal(identity);
principal.SetClaim(Claims.Private.TokenUsage, usage);
principal.SetClaim(Claims.Private.TokenType, type);
// Act and assert
Assert.Equal(result, principal.IsAuthorizationCode());
@ -2269,19 +2269,19 @@ namespace OpenIddict.Abstractions.Tests.Primitives
[Theory]
[InlineData(null, false)]
[InlineData("unknown", false)]
[InlineData(TokenUsages.AccessToken, false)]
[InlineData(TokenUsages.AuthorizationCode, false)]
[InlineData(TokenUsages.DeviceCode, true)]
[InlineData(TokenUsages.IdToken, false)]
[InlineData(TokenUsages.RefreshToken, false)]
[InlineData(TokenUsages.UserCode, false)]
public void IsDeviceCode_ReturnsExpectedResult(string usage, bool result)
[InlineData(TokenTypeHints.AccessToken, false)]
[InlineData(TokenTypeHints.AuthorizationCode, false)]
[InlineData(TokenTypeHints.DeviceCode, true)]
[InlineData(TokenTypeHints.IdToken, false)]
[InlineData(TokenTypeHints.RefreshToken, false)]
[InlineData(TokenTypeHints.UserCode, false)]
public void IsDeviceCode_ReturnsExpectedResult(string type, bool result)
{
// Arrange
var identity = new ClaimsIdentity();
var principal = new ClaimsPrincipal(identity);
principal.SetClaim(Claims.Private.TokenUsage, usage);
principal.SetClaim(Claims.Private.TokenType, type);
// Act and assert
Assert.Equal(result, principal.IsDeviceCode());
@ -2302,19 +2302,19 @@ namespace OpenIddict.Abstractions.Tests.Primitives
[Theory]
[InlineData(null, false)]
[InlineData("unknown", false)]
[InlineData(TokenUsages.AccessToken, false)]
[InlineData(TokenUsages.AuthorizationCode, false)]
[InlineData(TokenUsages.DeviceCode, false)]
[InlineData(TokenUsages.IdToken, true)]
[InlineData(TokenUsages.RefreshToken, false)]
[InlineData(TokenUsages.UserCode, false)]
public void IsIdentityToken_ReturnsExpectedResult(string usage, bool result)
[InlineData(TokenTypeHints.AccessToken, false)]
[InlineData(TokenTypeHints.AuthorizationCode, false)]
[InlineData(TokenTypeHints.DeviceCode, false)]
[InlineData(TokenTypeHints.IdToken, true)]
[InlineData(TokenTypeHints.RefreshToken, false)]
[InlineData(TokenTypeHints.UserCode, false)]
public void IsIdentityToken_ReturnsExpectedResult(string type, bool result)
{
// Arrange
var identity = new ClaimsIdentity();
var principal = new ClaimsPrincipal(identity);
principal.SetClaim(Claims.Private.TokenUsage, usage);
principal.SetClaim(Claims.Private.TokenType, type);
// Act and assert
Assert.Equal(result, principal.IsIdentityToken());
@ -2335,17 +2335,17 @@ namespace OpenIddict.Abstractions.Tests.Primitives
[Theory]
[InlineData(null, false)]
[InlineData("unknown", false)]
[InlineData(TokenUsages.AccessToken, false)]
[InlineData(TokenUsages.AuthorizationCode, false)]
[InlineData(TokenUsages.IdToken, false)]
[InlineData(TokenUsages.RefreshToken, true)]
public void IsRefreshToken_ReturnsExpectedResult(string usage, bool result)
[InlineData(TokenTypeHints.AccessToken, false)]
[InlineData(TokenTypeHints.AuthorizationCode, false)]
[InlineData(TokenTypeHints.IdToken, false)]
[InlineData(TokenTypeHints.RefreshToken, true)]
public void IsRefreshToken_ReturnsExpectedResult(string type, bool result)
{
// Arrange
var identity = new ClaimsIdentity();
var principal = new ClaimsPrincipal(identity);
principal.SetClaim(Claims.Private.TokenUsage, usage);
principal.SetClaim(Claims.Private.TokenType, type);
// Act and assert
Assert.Equal(result, principal.IsRefreshToken());
@ -2366,19 +2366,19 @@ namespace OpenIddict.Abstractions.Tests.Primitives
[Theory]
[InlineData(null, false)]
[InlineData("unknown", false)]
[InlineData(TokenUsages.AccessToken, false)]
[InlineData(TokenUsages.AuthorizationCode, false)]
[InlineData(TokenUsages.DeviceCode, false)]
[InlineData(TokenUsages.IdToken, false)]
[InlineData(TokenUsages.RefreshToken, false)]
[InlineData(TokenUsages.UserCode, true)]
public void IsUserCode_ReturnsExpectedResult(string usage, bool result)
[InlineData(TokenTypeHints.AccessToken, false)]
[InlineData(TokenTypeHints.AuthorizationCode, false)]
[InlineData(TokenTypeHints.DeviceCode, false)]
[InlineData(TokenTypeHints.IdToken, false)]
[InlineData(TokenTypeHints.RefreshToken, false)]
[InlineData(TokenTypeHints.UserCode, true)]
public void IsUserCode_ReturnsExpectedResult(string type, bool result)
{
// Arrange
var identity = new ClaimsIdentity();
var principal = new ClaimsPrincipal(identity);
principal.SetClaim(Claims.Private.TokenUsage, usage);
principal.SetClaim(Claims.Private.TokenType, type);
// Act and assert
Assert.Equal(result, principal.IsUserCode());
@ -2973,13 +2973,13 @@ namespace OpenIddict.Abstractions.Tests.Primitives
}
[Fact]
public void SetTokenUsage_ThrowsAnExceptionForNullPrincipal()
public void SetTokenType_ThrowsAnExceptionForNullPrincipal()
{
// Arrange
var principal = (ClaimsPrincipal) null;
// Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => principal.SetTokenUsage(null));
var exception = Assert.Throws<ArgumentNullException>(() => principal.SetTokenType(null));
Assert.Equal("principal", exception.ParamName);
}
@ -2987,17 +2987,17 @@ namespace OpenIddict.Abstractions.Tests.Primitives
[Theory]
[InlineData(null)]
[InlineData("access_token")]
public void SetTokenUsage_AddsUsage(string usage)
public void SetTokenType_AddsType(string type)
{
// Arrange
var identity = new ClaimsIdentity();
var principal = new ClaimsPrincipal(identity);
// Act
principal.SetTokenUsage(usage);
principal.SetTokenType(type);
// Assert
Assert.Equal(usage, principal.GetClaim(Claims.Private.TokenUsage));
Assert.Equal(type, principal.GetClaim(Claims.Private.TokenType));
}
private TimeSpan? ParseLifeTime(string lifetime)

64
test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.Exchange.cs

@ -398,7 +398,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetExpirationDate(DateTimeOffset.UtcNow - TimeSpan.FromDays(1));
@ -436,7 +436,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("8xLOxBtZp8", context.Token);
Assert.Equal(TokenUsages.RefreshToken, context.TokenType);
Assert.Equal(TokenTypeHints.RefreshToken, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetExpirationDate(DateTimeOffset.UtcNow - TimeSpan.FromDays(1));
@ -473,7 +473,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters(Enumerable.Empty<string>());
@ -512,7 +512,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Contoso");
@ -550,7 +550,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("8xLOxBtZp8", context.Token);
Assert.Equal(TokenUsages.RefreshToken, context.TokenType);
Assert.Equal(TokenTypeHints.RefreshToken, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Contoso");
@ -588,7 +588,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Fabrikam")
@ -628,7 +628,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Fabrikam")
@ -669,7 +669,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Fabrikam")
@ -712,7 +712,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Fabrikam")
@ -755,7 +755,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetClaim(Claims.Subject, "Bob le Magnifique")
@ -796,7 +796,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Fabrikam")
@ -836,7 +836,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Fabrikam")
@ -876,7 +876,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("8xLOxBtZp8", context.Token);
Assert.Equal(TokenUsages.RefreshToken, context.TokenType);
Assert.Equal(TokenTypeHints.RefreshToken, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetScopes(Enumerable.Empty<string>());
@ -914,7 +914,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("8xLOxBtZp8", context.Token);
Assert.Equal(TokenUsages.RefreshToken, context.TokenType);
Assert.Equal(TokenTypeHints.RefreshToken, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetScopes("profile", "email");
@ -1552,7 +1552,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Fabrikam")
@ -1604,7 +1604,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("8xLOxBtZp8", context.Token);
Assert.Equal(TokenUsages.RefreshToken, context.TokenType);
Assert.Equal(TokenTypeHints.RefreshToken, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetInternalTokenId("60FFF7EA-F98E-437B-937E-5073CC313103");
@ -1648,7 +1648,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetInternalTokenId("3E228451-1555-46F7-A471-951EFBA23A56");
@ -1706,7 +1706,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("8xLOxBtZp8", context.Token);
Assert.Equal(TokenUsages.RefreshToken, context.TokenType);
Assert.Equal(TokenTypeHints.RefreshToken, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Fabrikam")
@ -1760,7 +1760,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Fabrikam")
@ -1828,7 +1828,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("8xLOxBtZp8", context.Token);
Assert.Equal(TokenUsages.RefreshToken, context.TokenType);
Assert.Equal(TokenTypeHints.RefreshToken, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetInternalTokenId("60FFF7EA-F98E-437B-937E-5073CC313103");
@ -1876,7 +1876,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Fabrikam")
@ -1959,7 +1959,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("8xLOxBtZp8", context.Token);
Assert.Equal(TokenUsages.RefreshToken, context.TokenType);
Assert.Equal(TokenTypeHints.RefreshToken, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetInternalTokenId("60FFF7EA-F98E-437B-937E-5073CC313103")
@ -2049,7 +2049,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Fabrikam")
@ -2136,7 +2136,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("8xLOxBtZp8", context.Token);
Assert.Equal(TokenUsages.RefreshToken, context.TokenType);
Assert.Equal(TokenTypeHints.RefreshToken, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Fabrikam")
@ -2198,7 +2198,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Fabrikam")
@ -2271,7 +2271,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("8xLOxBtZp8", context.Token);
Assert.Equal(TokenUsages.RefreshToken, context.TokenType);
Assert.Equal(TokenTypeHints.RefreshToken, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Fabrikam")
@ -2319,7 +2319,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Fabrikam")
@ -2404,7 +2404,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("8xLOxBtZp8", context.Token);
Assert.Equal(TokenUsages.RefreshToken, context.TokenType);
Assert.Equal(TokenTypeHints.RefreshToken, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetInternalTokenId("60FFF7EA-F98E-437B-937E-5073CC313103")
@ -2471,7 +2471,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Fabrikam")
@ -2556,7 +2556,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetPresenters("Fabrikam")
@ -2637,7 +2637,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("8xLOxBtZp8", context.Token);
Assert.Equal(TokenUsages.RefreshToken, context.TokenType);
Assert.Equal(TokenTypeHints.RefreshToken, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetInternalTokenId("60FFF7EA-F98E-437B-937E-5073CC313103")
@ -2708,7 +2708,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("8xLOxBtZp8", context.Token);
Assert.Equal(TokenUsages.RefreshToken, context.TokenType);
Assert.Equal(TokenTypeHints.RefreshToken, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetInternalTokenId("60FFF7EA-F98E-437B-937E-5073CC313103")

6
test/OpenIddict.Server.IntegrationTests/OpenIddictServerIntegrationTests.cs

@ -191,7 +191,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("id_token", context.Token);
Assert.Equal(TokenUsages.IdToken, context.TokenType);
Assert.Equal(TokenTypeHints.IdToken, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetClaim(Claims.Subject, "Bob le Magnifique");
@ -295,7 +295,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("authorization_code", context.Token);
Assert.Equal(TokenUsages.AuthorizationCode, context.TokenType);
Assert.Equal(TokenTypeHints.AuthorizationCode, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetClaim(Claims.Subject, "Bob le Magnifique")
@ -400,7 +400,7 @@ namespace OpenIddict.Server.FunctionalTests
builder.UseInlineHandler(context =>
{
Assert.Equal("refresh_token", context.Token);
Assert.Equal(TokenUsages.RefreshToken, context.TokenType);
Assert.Equal(TokenTypeHints.RefreshToken, context.TokenType);
context.Principal = new ClaimsPrincipal(new ClaimsIdentity("Bearer"))
.SetClaim(Claims.Subject, "Bob le Magnifique");

Loading…
Cancel
Save