finished OpenID integration

This commit is contained in:
2024-12-22 14:28:49 +01:00
parent 9b38a10797
commit bee771a30e
15 changed files with 110 additions and 82 deletions

View File

@@ -1,7 +1,6 @@
using System.Security.Claims;
using HopFrame.Database.Repositories;
using HopFrame.Security.Authentication;
using HopFrame.Security.Claims;
using HopFrame.Web.Services;
using Microsoft.AspNetCore.Http;
@@ -20,16 +19,10 @@ public sealed class AuthMiddleware(IAuthService auth, IPermissionRepository perm
next?.Invoke(context);
return;
}
var claims = new List<Claim> {
new(HopFrameClaimTypes.AccessTokenId, token.TokenId.ToString()),
new(HopFrameClaimTypes.UserId, token.Owner.Id.ToString())
};
var permissions = await perms.GetFullPermissions(token);
claims.AddRange(permissions.Select(perm => new Claim(HopFrameClaimTypes.Permission, perm)));
context.User.AddIdentity(new ClaimsIdentity(claims, HopFrameAuthentication.SchemeName));
var principal = await HopFrameAuthentication.GenerateClaims(token, perms);
if (principal?.Identity is ClaimsIdentity identity)
context.User.AddIdentity(identity);
}
await next?.Invoke(context);

View File

@@ -1,6 +1,8 @@
using HopFrame.Database.Models;
using HopFrame.Database.Repositories;
using HopFrame.Security.Authentication;
using HopFrame.Security.Authentication.OpenID;
using HopFrame.Security.Authentication.OpenID.Options;
using HopFrame.Security.Claims;
using HopFrame.Security.Models;
using Microsoft.AspNetCore.Http;
@@ -13,10 +15,15 @@ internal class AuthService(
IHttpContextAccessor httpAccessor,
ITokenRepository tokens,
ITokenContext context,
IOptions<HopFrameAuthenticationOptions> options)
IOptions<HopFrameAuthenticationOptions> options,
IOptions<OpenIdOptions> openIdOptions,
IOpenIdAccessor accessor,
IUserRepository users)
: IAuthService {
public async Task Register(UserRegister register) {
if (!options.Value.DefaultAuthentication) return;
var user = await userService.AddUser(new User {
Username = register.Username,
Email = register.Email,
@@ -41,6 +48,8 @@ internal class AuthService(
}
public async Task<bool> Login(UserLogin login) {
if (!options.Value.DefaultAuthentication) return false;
var user = await userService.GetUserByEmail(login.Email);
if (user == null) return false;
@@ -75,6 +84,45 @@ internal class AuthService(
if (string.IsNullOrWhiteSpace(refreshToken)) return null;
if (openIdOptions.Value.Enabled && !Guid.TryParse(refreshToken, out _)) {
var openIdToken = await accessor.RefreshAccessToken(refreshToken);
if (openIdToken is null)
return null;
var inspection = await accessor.InspectToken(openIdToken.AccessToken);
var email = inspection.Email;
if (string.IsNullOrEmpty(email))
return null;
var user = await users.GetUserByEmail(email);
if (user is null) {
if (!openIdOptions.Value.GenerateUsers)
return null;
var username = inspection.PreferredUsername;
user = await users.AddUser(new User {
Email = email,
Username = username
});
}
httpAccessor.HttpContext?.Response.Cookies.Append(ITokenContext.AccessTokenType, openIdToken.AccessToken, new CookieOptions {
MaxAge = TimeSpan.FromSeconds(openIdToken.ExpiresIn),
HttpOnly = false,
Secure = true
});
return new() {
Owner = user,
CreatedAt = DateTime.Now,
Type = Token.OpenIdTokenType
};
}
if (!options.Value.DefaultAuthentication)
return null;
var token = await tokens.GetToken(refreshToken);
if (token is null || token.Type != Token.RefreshTokenType) return null;
@@ -96,7 +144,7 @@ internal class AuthService(
var accessToken = context.AccessToken;
if (accessToken is null) return false;
if (accessToken.Type != Token.AccessTokenType) return false;
if (accessToken.Type != Token.AccessTokenType && accessToken.Type != Token.OpenIdTokenType) return false;
if (accessToken.CreatedAt + options.Value.AccessTokenTime < DateTime.Now) return false;
if (accessToken.Owner is null) return false;