Browse Source

Refactor the OpenIddict primitives extensions class

pull/895/head
IgorHrabrov 6 years ago
committed by Kévin Chalet
parent
commit
201daf88ac
  1. 321
      src/OpenIddict.Abstractions/Primitives/OpenIddictExtensions.cs
  2. 22
      src/OpenIddict.Server/OpenIddictServerHandlers.Introspection.cs
  3. 20
      src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs
  4. 2
      src/OpenIddict.Server/OpenIddictServerHandlers.cs
  5. 178
      test/OpenIddict.Abstractions.Tests/Primitives/OpenIddictExtensionsTests.cs

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

@ -99,11 +99,6 @@ namespace OpenIddict.Abstractions
throw new ArgumentException("The value cannot be null or empty.", nameof(value));
}
if (string.IsNullOrEmpty(request.AcrValues))
{
return false;
}
return HasValue(request.AcrValues, value, Separators.Space);
}
@ -124,11 +119,6 @@ namespace OpenIddict.Abstractions
throw new ArgumentException("The prompt cannot be null or empty.", nameof(prompt));
}
if (string.IsNullOrEmpty(request.Prompt))
{
return false;
}
return HasValue(request.Prompt, prompt, Separators.Space);
}
@ -149,11 +139,6 @@ namespace OpenIddict.Abstractions
throw new ArgumentException("The response type cannot be null or empty.", nameof(type));
}
if (string.IsNullOrEmpty(request.ResponseType))
{
return false;
}
return HasValue(request.ResponseType, type, Separators.Space);
}
@ -174,11 +159,6 @@ namespace OpenIddict.Abstractions
throw new ArgumentException("The scope cannot be null or empty.", nameof(scope));
}
if (string.IsNullOrEmpty(request.Scope))
{
return false;
}
return HasValue(request.Scope, scope, Separators.Space);
}
@ -1192,25 +1172,7 @@ namespace OpenIddict.Abstractions
/// <param name="principal">The claims principal.</param>
/// <returns>The access token lifetime or <c>null</c> if the claim cannot be found.</returns>
public static TimeSpan? GetAccessTokenLifetime([NotNull] this ClaimsPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
var value = principal.GetClaim(Claims.Private.AccessTokenLifetime);
if (string.IsNullOrEmpty(value))
{
return null;
}
if (double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out double result))
{
return TimeSpan.FromSeconds(result);
}
return null;
}
=> GetLifetime(principal, Claims.Private.AccessTokenLifetime);
/// <summary>
/// Gets the authorization code lifetime associated with the claims principal.
@ -1218,25 +1180,7 @@ namespace OpenIddict.Abstractions
/// <param name="principal">The claims principal.</param>
/// <returns>The authorization code lifetime or <c>null</c> if the claim cannot be found.</returns>
public static TimeSpan? GetAuthorizationCodeLifetime([NotNull] this ClaimsPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
var value = principal.GetClaim(Claims.Private.AuthorizationCodeLifetime);
if (string.IsNullOrEmpty(value))
{
return null;
}
if (double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out double result))
{
return TimeSpan.FromSeconds(result);
}
return null;
}
=> GetLifetime(principal, Claims.Private.AuthorizationCodeLifetime);
/// <summary>
/// Gets the device code lifetime associated with the claims principal.
@ -1244,25 +1188,7 @@ namespace OpenIddict.Abstractions
/// <param name="principal">The claims principal.</param>
/// <returns>The device code lifetime or <c>null</c> if the claim cannot be found.</returns>
public static TimeSpan? GetDeviceCodeLifetime([NotNull] this ClaimsPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
var value = principal.GetClaim(Claims.Private.DeviceCodeLifetime);
if (string.IsNullOrEmpty(value))
{
return null;
}
if (double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out double result))
{
return TimeSpan.FromSeconds(result);
}
return null;
}
=> GetLifetime(principal, Claims.Private.DeviceCodeLifetime);
/// <summary>
/// Gets the identity token lifetime associated with the claims principal.
@ -1270,25 +1196,7 @@ namespace OpenIddict.Abstractions
/// <param name="principal">The claims principal.</param>
/// <returns>The identity token lifetime or <c>null</c> if the claim cannot be found.</returns>
public static TimeSpan? GetIdentityTokenLifetime([NotNull] this ClaimsPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
var value = principal.GetClaim(Claims.Private.IdentityTokenLifetime);
if (string.IsNullOrEmpty(value))
{
return null;
}
if (double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out double result))
{
return TimeSpan.FromSeconds(result);
}
return null;
}
=> GetLifetime(principal, Claims.Private.IdentityTokenLifetime);
/// <summary>
/// Gets the refresh token lifetime associated with the claims principal.
@ -1296,25 +1204,7 @@ namespace OpenIddict.Abstractions
/// <param name="principal">The claims principal.</param>
/// <returns>The refresh token lifetime or <c>null</c> if the claim cannot be found.</returns>
public static TimeSpan? GetRefreshTokenLifetime([NotNull] this ClaimsPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
var value = principal.GetClaim(Claims.Private.RefreshTokenLifetime);
if (string.IsNullOrEmpty(value))
{
return null;
}
if (double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out double result))
{
return TimeSpan.FromSeconds(result);
}
return null;
}
=> GetLifetime(principal, Claims.Private.RefreshTokenLifetime);
/// <summary>
/// Gets the user code lifetime associated with the claims principal.
@ -1322,25 +1212,7 @@ namespace OpenIddict.Abstractions
/// <param name="principal">The claims principal.</param>
/// <returns>The user code lifetime or <c>null</c> if the claim cannot be found.</returns>
public static TimeSpan? GetUserCodeLifetime([NotNull] this ClaimsPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
var value = principal.GetClaim(Claims.Private.UserCodeLifetime);
if (string.IsNullOrEmpty(value))
{
return null;
}
if (double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out double result))
{
return TimeSpan.FromSeconds(result);
}
return null;
}
=> GetLifetime(principal, Claims.Private.UserCodeLifetime);
/// <summary>
/// Gets the internal authorization identifier associated with the claims principal.
@ -1366,96 +1238,6 @@ namespace OpenIddict.Abstractions
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.
/// </summary>
/// <param name="principal">The claims principal.</param>
/// <returns><c>true</c> if the principal corresponds to an access token.</returns>
public static bool IsAccessToken([NotNull] this ClaimsPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
return string.Equals(principal.GetTokenType(), TokenTypeHints.AccessToken, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Gets a boolean value indicating whether the claims principal corresponds to an access token.
/// </summary>
/// <param name="principal">The claims principal.</param>
/// <returns><c>true</c> if the principal corresponds to an authorization code.</returns>
public static bool IsAuthorizationCode([NotNull] this ClaimsPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
return string.Equals(principal.GetTokenType(), TokenTypeHints.AuthorizationCode, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Gets a boolean value indicating whether the claims principal corresponds to a device code.
/// </summary>
/// <param name="principal">The claims principal.</param>
/// <returns><c>true</c> if the principal corresponds to a device code.</returns>
public static bool IsDeviceCode([NotNull] this ClaimsPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
return string.Equals(principal.GetTokenType(), TokenTypeHints.DeviceCode, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Gets a boolean value indicating whether the claims principal corresponds to an identity token.
/// </summary>
/// <param name="principal">The claims principal.</param>
/// <returns><c>true</c> if the principal corresponds to an identity token.</returns>
public static bool IsIdentityToken([NotNull] this ClaimsPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
return string.Equals(principal.GetTokenType(), TokenTypeHints.IdToken, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Gets a boolean value indicating whether the claims principal corresponds to a refresh token.
/// </summary>
/// <param name="principal">The claims principal.</param>
/// <returns><c>true</c> if the principal corresponds to a refresh token.</returns>
public static bool IsRefreshToken([NotNull] this ClaimsPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
return string.Equals(principal.GetTokenType(), TokenTypeHints.RefreshToken, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Gets a boolean value indicating whether the claims principal corresponds to a user code.
/// </summary>
/// <param name="principal">The claims principal.</param>
/// <returns><c>true</c> if the principal corresponds to a user code.</returns>
public static bool IsUserCode([NotNull] this ClaimsPrincipal principal)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
return string.Equals(principal.GetTokenType(), TokenTypeHints.UserCode, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Determines whether the claims principal contains at least one audience.
/// </summary>
@ -1633,30 +1415,35 @@ namespace OpenIddict.Abstractions
}
/// <summary>
/// Sets the creation date in the claims principal.
/// Determines whether the token type associated with the claims principal matches the specified type.
/// </summary>
/// <param name="principal">The claims principal.</param>
/// <param name="date">The creation date</param>
/// <returns>The claims principal.</returns>
public static ClaimsPrincipal SetCreationDate([NotNull] this ClaimsPrincipal principal, [CanBeNull] DateTimeOffset? date)
/// <param name="type">The token type.</param>
/// <returns><c>true</c> if the token type matches the specified type.</returns>
public static bool HasTokenType([NotNull] this ClaimsPrincipal principal, [NotNull] string type)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
principal.RemoveClaims(Claims.IssuedAt);
if (date.HasValue)
if (string.IsNullOrEmpty(type))
{
var value = date?.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture);
var claim = new Claim(Claims.IssuedAt, value, ClaimValueTypes.Integer64);
((ClaimsIdentity) principal.Identity).AddClaim(claim);
throw new ArgumentException("The token type cannot be null or empty.", nameof(type));
}
return principal;
return string.Equals(principal.GetTokenType(), type, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Sets the creation date in the claims principal.
/// </summary>
/// <param name="principal">The claims principal.</param>
/// <param name="date">The creation date</param>
/// <returns>The claims principal.</returns>
public static ClaimsPrincipal SetCreationDate([NotNull] this ClaimsPrincipal principal, [CanBeNull] DateTimeOffset? date)
=> SetDateClaim(principal, Claims.IssuedAt, date);
/// <summary>
/// Sets the expiration date in the claims principal.
/// </summary>
@ -1664,23 +1451,7 @@ namespace OpenIddict.Abstractions
/// <param name="date">The expiration date</param>
/// <returns>The claims principal.</returns>
public static ClaimsPrincipal SetExpirationDate([NotNull] this ClaimsPrincipal principal, [CanBeNull] DateTimeOffset? date)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
principal.RemoveClaims(Claims.ExpiresAt);
if (date.HasValue)
{
var value = date?.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture);
var claim = new Claim(Claims.ExpiresAt, value, ClaimValueTypes.Integer64);
((ClaimsIdentity) principal.Identity).AddClaim(claim);
}
return principal;
}
=> SetDateClaim(principal, Claims.ExpiresAt, date);
/// <summary>
/// Sets the audiences list in the claims principal.
@ -1916,7 +1687,11 @@ namespace OpenIddict.Abstractions
private static bool HasValue(string source, string value, char[] separators)
{
Debug.Assert(!string.IsNullOrEmpty(source), "The source string shouldn't be null or empty.");
if (string.IsNullOrEmpty(source))
{
return false;
}
Debug.Assert(!string.IsNullOrEmpty(value), "The value string shouldn't be null or empty.");
Debug.Assert(separators?.Length != 0, "The separators collection shouldn't be null or empty.");
@ -1996,5 +1771,45 @@ namespace OpenIddict.Abstractions
return false;
}
private static TimeSpan? GetLifetime(ClaimsPrincipal principal, string type)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
var value = principal.GetClaim(type);
if (string.IsNullOrEmpty(value))
{
return null;
}
if (double.TryParse(value, NumberStyles.Number, CultureInfo.InvariantCulture, out double result))
{
return TimeSpan.FromSeconds(result);
}
return null;
}
private static ClaimsPrincipal SetDateClaim(ClaimsPrincipal principal, string type, DateTimeOffset? date)
{
if (principal == null)
{
throw new ArgumentNullException(nameof(principal));
}
principal.RemoveClaims(type);
if (date.HasValue)
{
var value = date?.ToUnixTimeSeconds().ToString(CultureInfo.InvariantCulture);
var claim = new Claim(type, value, ClaimValueTypes.Integer64);
((ClaimsIdentity)principal.Identity).AddClaim(claim);
}
return principal;
}
}
}

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

@ -837,8 +837,10 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
if (!context.Principal.IsAccessToken() && !context.Principal.IsAuthorizationCode() &&
!context.Principal.IsIdentityToken() && !context.Principal.IsRefreshToken())
if (!context.Principal.HasTokenType(TokenTypeHints.AccessToken) &&
!context.Principal.HasTokenType(TokenTypeHints.AuthorizationCode) &&
!context.Principal.HasTokenType(TokenTypeHints.IdToken) &&
!context.Principal.HasTokenType(TokenTypeHints.RefreshToken))
{
context.Logger.LogError("The introspection request was rejected because " +
"the received token was of an unsupported type.");
@ -889,7 +891,7 @@ namespace OpenIddict.Server
// When the introspected token is an authorization code, the caller must be
// listed as a presenter (i.e the party the authorization code was issued to).
if (context.Principal.IsAuthorizationCode())
if (context.Principal.HasTokenType(TokenTypeHints.AuthorizationCode))
{
if (!context.Principal.HasPresenter())
{
@ -915,7 +917,7 @@ namespace OpenIddict.Server
// (i.e the party the token was issued to) or as an audience (i.e a resource server/API).
// If the access token doesn't contain any explicit presenter/audience, the token is assumed
// to be not specific to any resource server/client application and the check is bypassed.
if (context.Principal.IsAccessToken() &&
if (context.Principal.HasTokenType(TokenTypeHints.AccessToken) &&
context.Principal.HasAudience() && !context.Principal.HasAudience(context.ClientId) &&
context.Principal.HasPresenter() && !context.Principal.HasPresenter(context.ClientId))
{
@ -933,8 +935,8 @@ namespace OpenIddict.Server
// (i.e the client application the identity token was initially issued to).
// If the identity token doesn't contain any explicit audience, the token is
// assumed to be not specific to any client application and the check is bypassed.
if (context.Principal.IsIdentityToken() && context.Principal.HasAudience() &&
!context.Principal.HasAudience(context.ClientId))
if (context.Principal.HasTokenType(TokenTypeHints.IdToken) &&
context.Principal.HasAudience() && !context.Principal.HasAudience(context.ClientId))
{
context.Logger.LogError("The introspection request was rejected because the " +
"identity token was issued to a different client.");
@ -950,8 +952,8 @@ namespace OpenIddict.Server
// listed as a presenter (i.e the party the token was issued to).
// If the refresh token doesn't contain any explicit presenter, the token is
// assumed to be not specific to any client application and the check is bypassed.
if (context.Principal.IsRefreshToken() && context.Principal.HasPresenter() &&
!context.Principal.HasPresenter(context.ClientId))
if (context.Principal.HasTokenType(TokenTypeHints.RefreshToken) &&
context.Principal.HasPresenter() && !context.Principal.HasPresenter(context.ClientId))
{
context.Logger.LogError("The introspection request was rejected because the " +
"refresh token was issued to a different client.");
@ -1050,7 +1052,7 @@ namespace OpenIddict.Server
// Note: only set "token_type" when the received token is an access token.
// See https://tools.ietf.org/html/rfc7662#section-2.2
// and https://tools.ietf.org/html/rfc6749#section-5.1 for more information.
if (context.Principal.IsAccessToken())
if (context.Principal.HasTokenType(TokenTypeHints.AccessToken))
{
context.TokenType = TokenTypes.Bearer;
}
@ -1104,7 +1106,7 @@ namespace OpenIddict.Server
}
// Don't return application-specific claims if the token is not an access or identity token.
if (!context.Principal.IsAccessToken() && !context.Principal.IsIdentityToken())
if (!context.Principal.HasTokenType(TokenTypeHints.AccessToken) && !context.Principal.HasTokenType(TokenTypeHints.IdToken))
{
return;
}

20
src/OpenIddict.Server/OpenIddictServerHandlers.Revocation.cs

@ -783,9 +783,9 @@ namespace OpenIddict.Server
throw new ArgumentNullException(nameof(context));
}
if (!context.Principal.IsAccessToken() &&
!context.Principal.IsAuthorizationCode() &&
!context.Principal.IsRefreshToken())
if (!context.Principal.HasTokenType(TokenTypeHints.AccessToken) &&
!context.Principal.HasTokenType(TokenTypeHints.AuthorizationCode) &&
!context.Principal.HasTokenType(TokenTypeHints.RefreshToken))
{
context.Logger.LogError("The revocation request was rejected because " +
"the received token was of an unsupported type.");
@ -798,7 +798,7 @@ namespace OpenIddict.Server
}
// If the received token is an access token, return an error if reference tokens are not enabled.
if (!context.Options.UseReferenceAccessTokens && context.Principal.IsAccessToken())
if (!context.Options.UseReferenceAccessTokens && context.Principal.HasTokenType(TokenTypeHints.AccessToken))
{
context.Logger.LogError("The revocation request was rejected because the access token was not revocable.");
@ -848,7 +848,7 @@ namespace OpenIddict.Server
// When the revoked token is an authorization code, the caller must be
// listed as a presenter (i.e the party the authorization code was issued to).
if (context.Principal.IsAuthorizationCode())
if (context.Principal.HasTokenType(TokenTypeHints.AuthorizationCode))
{
if (!context.Principal.HasPresenter())
{
@ -874,7 +874,7 @@ namespace OpenIddict.Server
// (i.e the party the token was issued to) or as an audience (i.e a resource server/API).
// If the access token doesn't contain any explicit presenter/audience, the token is assumed
// to be not specific to any resource server/client application and the check is bypassed.
if (context.Principal.IsAccessToken() &&
if (context.Principal.HasTokenType(TokenTypeHints.AccessToken) &&
context.Principal.HasAudience() && !context.Principal.HasAudience(context.ClientId) &&
context.Principal.HasPresenter() && !context.Principal.HasPresenter(context.ClientId))
{
@ -892,8 +892,8 @@ namespace OpenIddict.Server
// (i.e the client application the identity token was initially issued to).
// If the identity token doesn't contain any explicit audience, the token is
// assumed to be not specific to any client application and the check is bypassed.
if (context.Principal.IsIdentityToken() && context.Principal.HasAudience() &&
!context.Principal.HasAudience(context.ClientId))
if (context.Principal.HasTokenType(TokenTypeHints.IdToken) &&
context.Principal.HasAudience() && !context.Principal.HasAudience(context.ClientId))
{
context.Logger.LogError("The revocation request was rejected because the " +
"identity token was issued to a different client.");
@ -909,8 +909,8 @@ namespace OpenIddict.Server
// listed as a presenter (i.e the party the token was issued to).
// If the refresh token doesn't contain any explicit presenter, the token is
// assumed to be not specific to any client application and the check is bypassed.
if (context.Principal.IsRefreshToken() && context.Principal.HasPresenter() &&
!context.Principal.HasPresenter(context.ClientId))
if (context.Principal.HasTokenType(TokenTypeHints.RefreshToken) &&
context.Principal.HasPresenter() && !context.Principal.HasPresenter(context.ClientId))
{
context.Logger.LogError("The revocation request was rejected because the " +
"refresh token was issued to a different client.");

2
src/OpenIddict.Server/OpenIddictServerHandlers.cs

@ -501,7 +501,7 @@ namespace OpenIddict.Server
context.Principal.SetDestinations(destinations);
}
if (context.Principal.IsAccessToken())
if (context.Principal.HasTokenType(TokenTypeHints.AccessToken))
{
// Map the standardized "azp" and "scope" claims to their "oi_" equivalent so that
// the ClaimsPrincipal extensions exposed by OpenIddict return consistent results.

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

@ -2189,199 +2189,45 @@ namespace OpenIddict.Abstractions.Tests.Primitives
}
[Fact]
public void IsAccessToken_ThrowsAnExceptionForNullPrincipal()
public void HasTokenType_ThrowsAnExceptionForNullPrincipal()
{
// Arrange
var principal = (ClaimsPrincipal) null;
// Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => principal.IsAccessToken());
var exception = Assert.Throws<ArgumentNullException>(() => principal.HasTokenType(TokenTypeHints.AccessToken));
Assert.Equal("principal", exception.ParamName);
}
[Theory]
[InlineData(null, false)]
[InlineData("unknown", false)]
[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.TokenType, type);
// Act and assert
Assert.Equal(result, principal.IsAccessToken());
}
[Fact]
public void IsAuthorizationCode_ThrowsAnExceptionForNullPrincipal()
{
// Arrange
var principal = (ClaimsPrincipal) null;
// Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => principal.IsAuthorizationCode());
Assert.Equal("principal", exception.ParamName);
}
[Theory]
[InlineData(null, false)]
[InlineData("unknown", false)]
[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.TokenType, type);
// Act and assert
Assert.Equal(result, principal.IsAuthorizationCode());
}
[Fact]
public void IsDeviceCode_ThrowsAnExceptionForNullPrincipal()
{
// Arrange
var principal = (ClaimsPrincipal) null;
// Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => principal.IsDeviceCode());
Assert.Equal("principal", exception.ParamName);
}
[Theory]
[InlineData(null, false)]
[InlineData("unknown", false)]
[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.TokenType, type);
// Act and assert
Assert.Equal(result, principal.IsDeviceCode());
}
[Fact]
public void IsIdentityToken_ThrowsAnExceptionForNullPrincipal()
{
// Arrange
var principal = (ClaimsPrincipal) null;
// Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => principal.IsIdentityToken());
Assert.Equal("principal", exception.ParamName);
}
[Theory]
[InlineData(null, false)]
[InlineData("unknown", false)]
[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)
[InlineData(null)]
[InlineData("")]
public void HasTokenType_ThrowsAnExceptionForNullOrEmptyTokenType(string type)
{
// Arrange
var identity = new ClaimsIdentity();
var principal = new ClaimsPrincipal(identity);
principal.SetClaim(Claims.Private.TokenType, type);
// Act and assert
Assert.Equal(result, principal.IsIdentityToken());
}
[Fact]
public void IsRefreshToken_ThrowsAnExceptionForNullPrincipal()
{
// Arrange
var principal = (ClaimsPrincipal) null;
// Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => principal.IsRefreshToken());
var exception = Assert.Throws<ArgumentException>(() => principal.HasTokenType(type));
Assert.Equal("principal", exception.ParamName);
}
[Theory]
[InlineData(null, false)]
[InlineData("unknown", false)]
[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.TokenType, type);
// Act and assert
Assert.Equal(result, principal.IsRefreshToken());
Assert.Equal("type", exception.ParamName);
Assert.StartsWith("The token type cannot be null or empty.", exception.Message);
}
[Fact]
public void IsUserCode_ThrowsAnExceptionForNullPrincipal()
{
// Arrange
var principal = (ClaimsPrincipal) null;
// Act and assert
var exception = Assert.Throws<ArgumentNullException>(() => principal.IsUserCode());
Assert.Equal("principal", exception.ParamName);
}
[Theory]
[InlineData(null, false)]
[InlineData("unknown", false)]
[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)
public void HasTokenType_ReturnsExpectedResult()
{
// Arrange
var identity = new ClaimsIdentity();
var principal = new ClaimsPrincipal(identity);
principal.SetClaim(Claims.Private.TokenType, type);
principal.SetClaim(Claims.Private.TokenType, TokenTypeHints.AccessToken);
// Act and assert
Assert.Equal(result, principal.IsUserCode());
Assert.True(principal.HasTokenType(TokenTypeHints.AccessToken));
Assert.False(principal.HasTokenType(TokenTypeHints.RefreshToken));
}
[Theory]

Loading…
Cancel
Save