From 0f24d25b36bc15375d4cbd5a4626ff6ac85d1d0e Mon Sep 17 00:00:00 2001 From: Kirill Kovalev <125643929+kirill-abblix@users.noreply.github.com> Date: Mon, 15 Apr 2024 10:06:48 +0300 Subject: [PATCH] Added ctor to AuthSession with required props --- .../AuthenticationSchemeAdapter.cs | 9 +++---- .../AuthorizationCodeGrantHandlerTests.cs | 9 ++----- .../Common/AuthorizationContext.cs | 26 +++++++++---------- .../UserAuthentication/AuthSession.cs | 8 +++--- .../AuthSessionExtensions.cs | 8 +++--- 5 files changed, 27 insertions(+), 33 deletions(-) diff --git a/Abblix.Oidc.Server.Mvc/AuthenticationSchemeAdapter.cs b/Abblix.Oidc.Server.Mvc/AuthenticationSchemeAdapter.cs index 15e9da50..3bc24fd0 100644 --- a/Abblix.Oidc.Server.Mvc/AuthenticationSchemeAdapter.cs +++ b/Abblix.Oidc.Server.Mvc/AuthenticationSchemeAdapter.cs @@ -116,13 +116,12 @@ public async IAsyncEnumerable GetAvailableAuthSessions() return null; // TODO think about the support for a list of several user accounts below - var authSession = new AuthSession + var authSession = new AuthSession( + principal.FindFirstValue(JwtClaimTypes.Subject).NotNull(JwtClaimTypes.Subject), + sessionId, + DateTimeOffset.FromUnixTimeSeconds(long.Parse(authenticationTime))) { IdentityProvider = principal.Identity!.AuthenticationType, - Subject = principal.FindFirstValue(JwtClaimTypes.Subject).NotNull(JwtClaimTypes.Subject), - - SessionId = sessionId, - AuthenticationTime = DateTimeOffset.FromUnixTimeSeconds(long.Parse(authenticationTime)), AuthContextClassRef = properties.GetString(JwtClaimTypes.AuthContextClassRef), }; diff --git a/Abblix.Oidc.Server.UnitTests/Endpoints/Token/AuthorizationCodeGrantHandlerTests.cs b/Abblix.Oidc.Server.UnitTests/Endpoints/Token/AuthorizationCodeGrantHandlerTests.cs index 870f390c..d2117444 100644 --- a/Abblix.Oidc.Server.UnitTests/Endpoints/Token/AuthorizationCodeGrantHandlerTests.cs +++ b/Abblix.Oidc.Server.UnitTests/Endpoints/Token/AuthorizationCodeGrantHandlerTests.cs @@ -100,13 +100,8 @@ private async Task PkceTest(string codeChallengeMethod .Setup(_ => _.AuthorizeByCodeAsync(tokenRequest.Code)) .ReturnsAsync( new AuthorizedGrantResult( - new AuthSession - { - Subject = "123", - SessionId = "session1", - AuthenticationTime = DateTimeOffset.UtcNow, - }, - new AuthorizationContext(clientInfo.ClientId, new[] { Scopes.OpenId }, null) + new AuthSession("123", "session1", DateTimeOffset.UtcNow), + Context: new AuthorizationContext(clientInfo.ClientId, [Scopes.OpenId], null) { CodeChallenge = codeChallenge, CodeChallengeMethod = codeChallengeMethod, diff --git a/Abblix.Oidc.Server/Common/AuthorizationContext.cs b/Abblix.Oidc.Server/Common/AuthorizationContext.cs index 7494bb4d..49989206 100644 --- a/Abblix.Oidc.Server/Common/AuthorizationContext.cs +++ b/Abblix.Oidc.Server/Common/AuthorizationContext.cs @@ -53,6 +53,19 @@ public record AuthorizationContext(string ClientId, string[] Scope, RequestedCla /// public string ClientId { get; init; } = ClientId; + /// + /// Defines the scope of access requested by the client. Scopes are used to specify the level of access or permissions + /// that the client is requesting on the user's behalf. They play a key role in enforcing principle of least privilege. + /// + public string[] Scope { get; init; } = Scope; + + /// + /// Optional. Specifies the individual Claims requested by the client, providing detailed instructions + /// for the authorization server on the Claims to be returned, either in the ID Token or via the UserInfo endpoint. + /// This mechanism supports clients in obtaining consented user information in a structured and controlled manner. + /// + public RequestedClaims? RequestedClaims { get; init; } = RequestedClaims; + /// /// The URI where the authorization response should be sent. This URI must match one of the registered redirect URIs /// for the client application, ensuring that authorization responses are delivered to the correct destination securely. @@ -77,17 +90,4 @@ public record AuthorizationContext(string ClientId, string[] Scope, RequestedCla /// enhancing the security of PKCE by allowing the authorization server to verify the code exchange authenticity. /// public string? CodeChallengeMethod { get; init; } - - /// - /// Defines the scope of access requested by the client. Scopes are used to specify the level of access or permissions - /// that the client is requesting on the user's behalf. They play a key role in enforcing principle of least privilege. - /// - public string[] Scope { get; init; } = Scope; - - /// - /// Optional. Specifies the individual Claims requested by the client, providing detailed instructions - /// for the authorization server on the Claims to be returned, either in the ID Token or via the UserInfo endpoint. - /// This mechanism supports clients in obtaining consented user information in a structured and controlled manner. - /// - public RequestedClaims? RequestedClaims { get; init; } = RequestedClaims; } diff --git a/Abblix.Oidc.Server/Features/UserAuthentication/AuthSession.cs b/Abblix.Oidc.Server/Features/UserAuthentication/AuthSession.cs index 53ff963e..870c6a79 100644 --- a/Abblix.Oidc.Server/Features/UserAuthentication/AuthSession.cs +++ b/Abblix.Oidc.Server/Features/UserAuthentication/AuthSession.cs @@ -33,25 +33,25 @@ namespace Abblix.Oidc.Server.Features.UserAuthentication; /// Represents a model of an authentication session for a logged-in user, capturing essential details about the user's /// authentication state and interactions within the system. /// -public record AuthSession +public record AuthSession(string Subject, string SessionId, DateTimeOffset AuthenticationTime) { /// /// The unique identifier for the user in the session. This is typically a user-specific identifier that can be /// used to retrieve user details or verify the user's identity across different parts of the application. /// - public string Subject { get; init; } = null!; + public string Subject { get; init; } = Subject; /// /// The unique identifier of the session, used to track the session across requests and possibly across /// different services. /// - public string SessionId { get; init; } = null!; + public string SessionId { get; init; } = SessionId; /// /// The timestamp indicating when the user was authenticated. This is used for session management purposes such as /// session expiration and activity logging. /// - public DateTimeOffset AuthenticationTime { get; init; } + public DateTimeOffset AuthenticationTime { get; init; } = AuthenticationTime; /// /// The provider used to authenticate the user's identity. This could be a local database, an external identity diff --git a/Abblix.Oidc.Server/Features/UserAuthentication/AuthSessionExtensions.cs b/Abblix.Oidc.Server/Features/UserAuthentication/AuthSessionExtensions.cs index a300e619..fc1e4f14 100644 --- a/Abblix.Oidc.Server/Features/UserAuthentication/AuthSessionExtensions.cs +++ b/Abblix.Oidc.Server/Features/UserAuthentication/AuthSessionExtensions.cs @@ -65,11 +65,11 @@ public static void ApplyTo(this AuthSession authSession, JsonWebTokenPayload pay /// This method allows for the reconstruction of an authentication session from the claims encoded in a JWT. /// It is particularly useful when processing JWTs to extract authentication and user session details. /// - public static AuthSession ToAuthSession(this JsonWebTokenPayload payload) => new() + public static AuthSession ToAuthSession(this JsonWebTokenPayload payload) => new( + payload.Subject.NotNull(nameof(payload.Subject)), + payload.SessionId.NotNull(nameof(payload.SessionId)), + payload.AuthenticationTime.NotNull(nameof(payload.AuthenticationTime))) { - Subject = payload.Subject.NotNull(nameof(payload.Subject)), - SessionId = payload.SessionId.NotNull(nameof(payload.SessionId)), IdentityProvider = payload.IdentityProvider, - AuthenticationTime = payload.AuthenticationTime.NotNull(nameof(payload.AuthenticationTime)), }; }