Skip to content

Commit

Permalink
Added IPersistentStorage and different stores
Browse files Browse the repository at this point in the history
  • Loading branch information
kirill-abblix committed Apr 17, 2024
1 parent 0f24d25 commit 4176dfe
Show file tree
Hide file tree
Showing 37 changed files with 1,038 additions and 84 deletions.
6 changes: 3 additions & 3 deletions Abblix.Oidc.Server.Mvc/Attributes/AllowedValuesAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public AllowedValuesAttribute(params string[] allowedValues)
null => ValidationResult.Success,
string[][] stringValues => IsValid(stringValues.SelectMany(stringValue => stringValue), context),
string[] stringValues => IsValid(stringValues, context),
string stringValue => IsValid(stringValue, context),
string stringValue => IsValid(stringValue),
_ => throw new InvalidOperationException($"The type {value.GetType()} is not supported by {nameof(AllowedValuesAttribute)}"),
};
}
Expand All @@ -78,15 +78,15 @@ public AllowedValuesAttribute(params string[] allowedValues)
{
foreach (var value in values)
{
var result = IsValid(value, context);
var result = IsValid(value);
if (result != ValidationResult.Success)
return result;
}

return ValidationResult.Success;
}

private ValidationResult? IsValid(string value, ValidationContext context)
private ValidationResult? IsValid(string value)
{
if (!_allowedValues.Contains(value, StringComparer.OrdinalIgnoreCase))
return new ValidationResult($"The value '{value}' is invalid");
Expand Down
1 change: 0 additions & 1 deletion Abblix.Oidc.Server.Mvc/AuthenticationSchemeAdapter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,6 @@ public Task SignInAsync(AuthSession authSession)
return HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, properties);
}


/// <summary>
/// Signs out the current user from the application, ending their authenticated session.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
using Abblix.Oidc.Server.Common.Configuration;
using Abblix.Oidc.Server.Common.Constants;
using Abblix.Oidc.Server.Common.Exceptions;
using Abblix.Oidc.Server.Common.Interfaces;
using Abblix.Oidc.Server.Endpoints.Authorization.Interfaces;
using Abblix.Oidc.Server.Features.SessionManagement;
using Abblix.Oidc.Server.Features.Storages;
using Abblix.Oidc.Server.Model;
using Abblix.Oidc.Server.Mvc.ActionResults;
using Abblix.Oidc.Server.Mvc.Binders;
Expand Down
2 changes: 1 addition & 1 deletion Abblix.Oidc.Server.Mvc/Path.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ namespace Abblix.Oidc.Server.Mvc;
/// Contains constants for various OpenID Connect and OAuth2 endpoint paths.
/// This class centralizes the paths used throughout the application for consistency and maintainability.
/// </summary>
internal static class Path
public static class Path
{
private const string Base = "~/connect";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
using Abblix.Oidc.Server.Endpoints.Token.Grants;
using Abblix.Oidc.Server.Endpoints.Token.Interfaces;
using Abblix.Oidc.Server.Features.ClientInformation;
using Abblix.Oidc.Server.Features.Storages;
using Abblix.Oidc.Server.Features.UserAuthentication;
using Abblix.Oidc.Server.Model;

Expand All @@ -48,9 +49,9 @@ namespace Abblix.Oidc.Server.UnitTests.Endpoints.Token;

public class AuthorizationCodeGrantHandlerTests
{
private Mock<IAuthorizationCodeService> _authCodeService;
private Mock<IParameterValidator> _parameterValidator;
private AuthorizationCodeGrantHandler _handler;
private readonly Mock<IAuthorizationCodeService> _authCodeService;
private readonly Mock<IParameterValidator> _parameterValidator;
private readonly AuthorizationCodeGrantHandler _handler;

public AuthorizationCodeGrantHandlerTests()
{
Expand Down
4 changes: 4 additions & 0 deletions Abblix.Oidc.Server/Common/Configuration/OidcOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,8 @@ public record OidcOptions
/// compliance.
/// </summary>
public string? LicenseJwt { get; set; }

public int AuthorizationCodeLength { get; set; } = 64;

public int RequestUriLength { get; set; } = 64;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Abblix OpenID Connect Server Library
// Copyright (c) 2024 by Abblix LLP
//
// This software is provided 'as-is', without any express or implied warranty. In no
// event will the authors be held liable for any damages arising from the use of this
// software.
//
// Permitted Use: This software is open for use and extension by non-profit,
// educational and community projects under the condition that it remains unmodified
// and used in its entirety through official Nuget packages. Any unauthorized
// modification, forking of the whole repository, or altering individual files is
// strictly prohibited to ensure development occurs solely within the official Abblix LLP
// repository.
//
// Prohibited Actions: Redistribution, modification, incorporation of this software or
// any part thereof into other products, and creation of derivative works are not
// permitted without obtaining a commercial license from Abblix LLP.
//
// Commercial Use: A separate license is required for commercial use, including
// functionalities extended beyond the original software. For information on obtaining
// a commercial license, please contact Abblix LLP.
//
// Enforcement: Unauthorized redistribution, modification, or use of this software in
// other projects or products is strictly prohibited without prior written permission
// from the copyright holder. Violations may be subject to legal action.
//
// For more information, please refer to the license agreement located at:
// https://github.com/Abblix/Oidc.Server/blob/master/README.md

using System.Text;
using System.Text.Json;
using Abblix.Oidc.Server.Common.Interfaces;

namespace Abblix.Oidc.Server.Common.Implementation;

public class Utf8JsonBinarySerializer : IBinarySerializer
{
public byte[] Serialize<T>(T obj)
{
var json = JsonSerializer.Serialize(obj);
return Encoding.UTF8.GetBytes(json);
}

public T? Deserialize<T>(byte[] bytes)
{
var json = Encoding.UTF8.GetString(bytes);
return JsonSerializer.Deserialize<T>(json);
}
}
53 changes: 53 additions & 0 deletions Abblix.Oidc.Server/Common/Interfaces/IBinarySerializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Abblix OpenID Connect Server Library
// Copyright (c) 2024 by Abblix LLP
//
// This software is provided 'as-is', without any express or implied warranty. In no
// event will the authors be held liable for any damages arising from the use of this
// software.
//
// Permitted Use: This software is open for use and extension by non-profit,
// educational and community projects under the condition that it remains unmodified
// and used in its entirety through official Nuget packages. Any unauthorized
// modification, forking of the whole repository, or altering individual files is
// strictly prohibited to ensure development occurs solely within the official Abblix LLP
// repository.
//
// Prohibited Actions: Redistribution, modification, incorporation of this software or
// any part thereof into other products, and creation of derivative works are not
// permitted without obtaining a commercial license from Abblix LLP.
//
// Commercial Use: A separate license is required for commercial use, including
// functionalities extended beyond the original software. For information on obtaining
// a commercial license, please contact Abblix LLP.
//
// Enforcement: Unauthorized redistribution, modification, or use of this software in
// other projects or products is strictly prohibited without prior written permission
// from the copyright holder. Violations may be subject to legal action.
//
// For more information, please refer to the license agreement located at:
// https://github.com/Abblix/Oidc.Server/blob/master/README.md

namespace Abblix.Oidc.Server.Common.Interfaces;

/// <summary>
/// Defines the contract for a binary serializer that supports serialization and deserialization of objects
/// to and from binary format.
/// </summary>
public interface IBinarySerializer
{
/// <summary>
/// Serializes an object of type <typeparamref name="T"/> to a binary array.
/// </summary>
/// <typeparam name="T">The type of the object to serialize.</typeparam>
/// <param name="obj">The object to serialize.</param>
/// <returns>A binary array representing the serialized object.</returns>
byte[] Serialize<T>(T obj);

/// <summary>
/// Deserializes a binary array to an object of type <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">The type of the object to deserialize to.</typeparam>
/// <param name="bytes">The binary array to deserialize from.</param>
/// <returns>The deserialized object of type <typeparamref name="T"/>.</returns>
T? Deserialize<T>(byte[] bytes);
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@

using Abblix.Oidc.Server.Common;
using Abblix.Oidc.Server.Common.Constants;
using Abblix.Oidc.Server.Common.Interfaces;
using Abblix.Oidc.Server.Endpoints.Authorization.Interfaces;
using Abblix.Oidc.Server.Features.Consents;
using Abblix.Oidc.Server.Features.Licensing;
using Abblix.Oidc.Server.Features.Storages;
using Abblix.Oidc.Server.Features.Tokens;
using Abblix.Oidc.Server.Features.UserAuthentication;
using Abblix.Oidc.Server.Model;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Abblix.Oidc.Server.Common.Constants;
using Abblix.Oidc.Server.Common.Interfaces;
using Abblix.Oidc.Server.Endpoints.Authorization.Validation;
using Abblix.Oidc.Server.Features.Storages;
using Abblix.Oidc.Server.Model;

namespace Abblix.Oidc.Server.Endpoints.Authorization.RequestFetching;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
// https://github.com/Abblix/Oidc.Server/blob/master/README.md

using Abblix.Oidc.Server.Common.Configuration;
using Abblix.Oidc.Server.Common.Interfaces;
using Abblix.Oidc.Server.Endpoints.Authorization.Interfaces;
using Abblix.Oidc.Server.Endpoints.PushedAuthorization.Interfaces;
using Abblix.Oidc.Server.Features.Storages;
using Microsoft.Extensions.Options;

namespace Abblix.Oidc.Server.Endpoints.PushedAuthorization;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
// https://github.com/Abblix/Oidc.Server/blob/master/README.md

using Abblix.Oidc.Server.Endpoints.Revocation.Interfaces;
using Abblix.Oidc.Server.Features.Storages;
using Abblix.Oidc.Server.Features.Tokens.Revocation;
using Abblix.Utils;


namespace Abblix.Oidc.Server.Endpoints.Revocation;
Expand Down Expand Up @@ -65,8 +65,8 @@ public RevocationRequestProcessor(ITokenRegistry tokenRegistry)
public async Task<RevocationResponse> ProcessAsync(ValidRevocationRequest request)
{
var payload = request.Token?.Payload;
if (payload != null && payload.JwtId.HasValue())
await _tokenRegistry.SetStatusAsync(payload.JwtId, payload.ExpiresAt, JsonWebTokenStatus.Revoked);
if (payload is { JwtId: {} jwtId, ExpiresAt: {} expiresAt })
await _tokenRegistry.SetStatusAsync(jwtId, JsonWebTokenStatus.Revoked, expiresAt);

return new TokenRevokedResponse();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@

using Abblix.Jwt;
using Abblix.Oidc.Server.Common.Constants;
using Abblix.Oidc.Server.Common.Interfaces;
using Abblix.Oidc.Server.Endpoints.Token.Interfaces;
using Abblix.Oidc.Server.Features.Storages;
using Abblix.Oidc.Server.Features.Tokens.Revocation;

namespace Abblix.Oidc.Server.Endpoints.Token;
Expand Down Expand Up @@ -89,7 +89,10 @@ public async Task<TokenResponse> ProcessAsync(ValidTokenRequest request)

foreach (var (jwtId, expiresAt) in tokens)
{
await _tokenRegistry.SetStatusAsync(jwtId, expiresAt, JsonWebTokenStatus.Revoked);
if (expiresAt.HasValue)
{
await _tokenRegistry.SetStatusAsync(jwtId, JsonWebTokenStatus.Revoked, expiresAt.Value);
}
}

return new TokenErrorResponse(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,24 @@
using Abblix.Oidc.Server.Common.Interfaces;
using Abblix.Oidc.Server.Endpoints.Token.Interfaces;
using Abblix.Oidc.Server.Features.ClientInformation;
using Abblix.Oidc.Server.Features.Storages;
using Abblix.Oidc.Server.Model;
using Abblix.Utils;



namespace Abblix.Oidc.Server.Endpoints.Token.Grants;

/// <summary>
/// This class is responsible for handling the authorization code grant type
/// as part of the IAuthorizationGrantHandler process.
/// Handles the authorization code grant type for OAuth 2.0.
/// This class validates the provided authorization code against stored codes,
/// checks the client details, and implements PKCE verification when necessary.
/// </summary>
public class AuthorizationCodeGrantHandler : IAuthorizationGrantHandler
{
/// <summary>
/// Initializes a new instance of the <see cref="AuthorizationCodeGrantHandler"/> class.
/// </summary>
/// <param name="parameterValidator">The service to validate request parameters.</param>
/// <param name="authorizationCodeService">The service to manage authorization codes.</param>
public AuthorizationCodeGrantHandler(
IParameterValidator parameterValidator,
IAuthorizationCodeService authorizationCodeService)
Expand All @@ -58,7 +63,7 @@ public AuthorizationCodeGrantHandler(
private readonly IAuthorizationCodeService _authorizationCodeService;

/// <summary>
/// Gets the grant type this handler supports.
/// Gets the grant type this handler supports, which is the authorization code grant type.
/// </summary>
public IEnumerable<string> GrantTypesSupported
{
Expand All @@ -67,17 +72,19 @@ public IEnumerable<string> GrantTypesSupported

/// <summary>
/// Authorizes the token request asynchronously using the authorization code grant type.
/// Validates the authorization code, verifies the client information, and ensures compliance with PKCE if used.
/// </summary>
/// <param name="request">The token request to authorize.</param>
/// <param name="request">The token request containing the authorization code.</param>
/// <param name="clientInfo">The client information associated with the request.</param>
/// <returns>A task representing the result of the authorization process, containing a GrantAuthorizationResult object.</returns>
/// <returns>A task representing the result of the authorization process,
/// containing a <see cref="GrantAuthorizationResult"/>.</returns>
public async Task<GrantAuthorizationResult> AuthorizeAsync(TokenRequest request, ClientInfo clientInfo)
{
_parameterValidator.Required(request.Code, nameof(request.Code));

var authorizationResult = await _authorizationCodeService.AuthorizeByCodeAsync(request.Code);
var grantResult = await _authorizationCodeService.AuthorizeByCodeAsync(request.Code);

return authorizationResult switch
return grantResult switch
{
AuthorizedGrantResult { Context.ClientId: var clientId } when clientId != clientInfo.ClientId
=> new InvalidGrantResult(ErrorCodes.UnauthorizedClient, "Code was issued for another client"),
Expand All @@ -89,17 +96,17 @@ public async Task<GrantAuthorizationResult> AuthorizeAsync(TokenRequest request,
when !string.Equals(challenge, CalculateChallenge(method, request.CodeVerifier), StringComparison.OrdinalIgnoreCase)
=> new InvalidGrantResult(ErrorCodes.InvalidGrant, "Code verifier is not valid"),

_ => authorizationResult,
_ => grantResult,
};
}

/// <summary>
/// Calculates the code challenge based on the provided method and code verifier.
/// Supports 'plain' and 'S256' challenge methods.
/// </summary>
/// <param name="method">The code challenge method to use.</param>
/// <param name="codeVerifier">The code verifier string.</param>
/// <returns>The calculated code challenge.</returns>
/// <exception cref="ArgumentOutOfRangeException">Thrown when an unknown code challenge method is encountered.</exception>
/// <param name="method">The code challenge method used during authorization request.</param>
/// <param name="codeVerifier">The code verifier submitted by the client.</param>
/// <returns>The calculated code challenge string.</returns>
private static string CalculateChallenge(string method, string codeVerifier) => method switch
{
CodeChallengeMethods.S256 => HttpServerUtility.UrlTokenEncode(SHA256.HashData(Encoding.ASCII.GetBytes(codeVerifier))),
Expand Down
6 changes: 4 additions & 2 deletions Abblix.Oidc.Server/Endpoints/Token/TokenRequestProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
using Abblix.Oidc.Server.Common.Constants;
using Abblix.Oidc.Server.Endpoints.Token.Interfaces;
using Abblix.Oidc.Server.Features.Licensing;
using Abblix.Oidc.Server.Features.Storages;
using Abblix.Oidc.Server.Features.Tokens;
using Abblix.Oidc.Server.Features.Tokens.Revocation;

Expand Down Expand Up @@ -110,10 +111,11 @@ public async Task<TokenResponse> ProcessAsync(ValidTokenRequest request)

if (request is {
ClientInfo.RefreshToken.AllowReuse: false,
RefreshToken.Payload: { JwtId: { } jwtId, ExpiresAt: var expiresAt }})
RefreshToken.Payload: { JwtId: { } jwtId, ExpiresAt: {} expiresAt }
})
{
// Revokes used refresh token to prevent its reuse
await _tokenRegistry.SetStatusAsync(jwtId, expiresAt, JsonWebTokenStatus.Revoked);
await _tokenRegistry.SetStatusAsync(jwtId, JsonWebTokenStatus.Revoked, expiresAt);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
using Abblix.Oidc.Server.Common.Interfaces;
using Abblix.Oidc.Server.Features.ClientInformation;
using Abblix.Oidc.Server.Features.Licensing;
using Abblix.Oidc.Server.Features.Storages;
using Abblix.Oidc.Server.Features.Tokens.Revocation;
using Abblix.Oidc.Server.Model;
using Abblix.Utils;
Expand Down Expand Up @@ -162,9 +163,9 @@ public IEnumerable<string> ClientAuthenticationMethodsSupported
return null;
}

if (token is { Payload: { JwtId: { } jwtId, ExpiresAt: var expiresAt } })
if (token is { Payload: { JwtId: { } jwtId, ExpiresAt: {} expiresAt } })
{
await _tokenRegistry.SetStatusAsync(jwtId, expiresAt, JsonWebTokenStatus.Used);
await _tokenRegistry.SetStatusAsync(jwtId, JsonWebTokenStatus.Used, expiresAt);
}

return issuerValidator.ClientInfo;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@
using Abblix.Oidc.Server.Endpoints.Authorization.Interfaces;
using Abblix.Oidc.Server.Features.UserAuthentication;


namespace Abblix.Oidc.Server.Common.Interfaces;
namespace Abblix.Oidc.Server.Features.Consents;

/// <summary>
/// Provides methods to determine whether user consent is to proceed with authentication.
Expand Down
Loading

0 comments on commit 4176dfe

Please sign in to comment.