diff --git a/src/HopFrame.Api/Controller/OpenIdController.cs b/src/HopFrame.Api/Controller/OpenIdController.cs index 2892d98..37912a7 100644 --- a/src/HopFrame.Api/Controller/OpenIdController.cs +++ b/src/HopFrame.Api/Controller/OpenIdController.cs @@ -9,7 +9,7 @@ using Microsoft.Extensions.Options; namespace HopFrame.Api.Controller; [ApiController, Route("api/v1/openid")] -public class OpenIdController(IOpenIdAccessor accessor, IOptions options) : ControllerBase { +public class OpenIdController(IOpenIdAccessor accessor) : ControllerBase { public const string DefaultCallback = "api/v1/openid/callback"; [HttpGet("redirect")] @@ -35,16 +35,7 @@ public class OpenIdController(IOpenIdAccessor accessor, IOptions return Forbid("Authorization code is not valid"); } - Response.Cookies.Append(ITokenContext.AccessTokenType, token.AccessToken, new CookieOptions { - MaxAge = TimeSpan.FromSeconds(token.ExpiresIn), - HttpOnly = false, - Secure = true - }); - Response.Cookies.Append(ITokenContext.RefreshTokenType, token.RefreshToken, new CookieOptions { - MaxAge = options.Value.RefreshToken.ConstructTimeSpan, - HttpOnly = false, - Secure = true - }); + accessor.SetAuthenticationCookies(token); if (string.IsNullOrEmpty(state)) { return Ok(new SingleValueResult(token.AccessToken)); @@ -65,11 +56,7 @@ public class OpenIdController(IOpenIdAccessor accessor, IOptions if (token is null) return NotFound("Refresh token not valid"); - Response.Cookies.Append(ITokenContext.AccessTokenType, token.AccessToken, new CookieOptions { - MaxAge = TimeSpan.FromSeconds(token.ExpiresIn), - HttpOnly = false, - Secure = true - }); + accessor.SetAuthenticationCookies(token); return Ok(new SingleValueResult(token.AccessToken)); } diff --git a/src/HopFrame.Security/Authentication/OpenID/IOpenIdAccessor.cs b/src/HopFrame.Security/Authentication/OpenID/IOpenIdAccessor.cs index 8045b70..4dc41c4 100644 --- a/src/HopFrame.Security/Authentication/OpenID/IOpenIdAccessor.cs +++ b/src/HopFrame.Security/Authentication/OpenID/IOpenIdAccessor.cs @@ -10,4 +10,5 @@ public interface IOpenIdAccessor { Task ConstructAuthUri(string state = null); Task InspectToken(string token); Task RefreshAccessToken(string refreshToken); + void SetAuthenticationCookies(OpenIdToken token); } \ No newline at end of file diff --git a/src/HopFrame.Security/Authentication/OpenID/Implementation/OpenIdAccessor.cs b/src/HopFrame.Security/Authentication/OpenID/Implementation/OpenIdAccessor.cs index 31fe0c0..bbe2b8c 100644 --- a/src/HopFrame.Security/Authentication/OpenID/Implementation/OpenIdAccessor.cs +++ b/src/HopFrame.Security/Authentication/OpenID/Implementation/OpenIdAccessor.cs @@ -1,6 +1,7 @@ using System.Text.Json; using HopFrame.Security.Authentication.OpenID.Models; using HopFrame.Security.Authentication.OpenID.Options; +using HopFrame.Security.Claims; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Options; @@ -18,7 +19,7 @@ internal class OpenIdAccessor(IHttpClientFactory clientFactory, IOptions ConstructAuthUri(string state = null) { var protocol = accessor.HttpContext!.Request.IsHttps ? "https" : "http"; - var callback = options.Value.Callback ?? Path.Combine($"{protocol}://{accessor.HttpContext!.Request.Host.Value}", IOpenIdAccessor.DefaultCallback); + var callback = options.Value.Callback ?? Path.Combine($"{protocol}://{accessor.HttpContext!.Request.Host.Value}", IOpenIdAccessor.DefaultCallback).Replace("\\", "/"); var configuration = await LoadConfiguration(); return $"{configuration.AuthorizationEndpoint}?response_type=code&client_id={options.Value.ClientId}&redirect_uri={callback}&scope=openid%20profile%20email%20offline_access&state={state}"; @@ -120,4 +121,20 @@ internal class OpenIdAccessor(IHttpClientFactory clientFactory, IOptions(await response.Content.ReadAsStreamAsync()); } + + public void SetAuthenticationCookies(OpenIdToken token) { + if (token.AccessToken is not null) + accessor.HttpContext!.Response.Cookies.Append(ITokenContext.AccessTokenType, token.AccessToken, new CookieOptions { + MaxAge = TimeSpan.FromSeconds(token.ExpiresIn), + HttpOnly = false, + Secure = true + }); + + if (token.RefreshToken is not null) + accessor.HttpContext!.Response.Cookies.Append(ITokenContext.RefreshTokenType, token.RefreshToken, new CookieOptions { + MaxAge = options.Value.RefreshToken.ConstructTimeSpan, + HttpOnly = false, + Secure = true + }); + } } \ No newline at end of file diff --git a/src/HopFrame.Web/Services/Implementation/AuthService.cs b/src/HopFrame.Web/Services/Implementation/AuthService.cs index 5c95a8f..ddb10d5 100644 --- a/src/HopFrame.Web/Services/Implementation/AuthService.cs +++ b/src/HopFrame.Web/Services/Implementation/AuthService.cs @@ -108,11 +108,7 @@ internal class AuthService( }); } - httpAccessor.HttpContext?.Response.Cookies.Append(ITokenContext.AccessTokenType, openIdToken.AccessToken, new CookieOptions { - MaxAge = TimeSpan.FromSeconds(openIdToken.ExpiresIn), - HttpOnly = false, - Secure = true - }); + accessor.SetAuthenticationCookies(openIdToken); return new() { Owner = user, CreatedAt = DateTime.Now,