Started implementing oauth2 based on MoonCore helper services
Its more or less a test how well the helper services improve the implementation. I havent implemented anything fancy here atm. Just testing the oauth2 flow
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
using System.Text.Json;
|
||||
using MoonCore.Extended.Abstractions;
|
||||
using MoonCore.Extended.Helpers;
|
||||
using MoonCore.Extended.Models;
|
||||
using MoonCore.Extended.OAuth2.ApiServer;
|
||||
using MoonCore.Services;
|
||||
using Moonlight.ApiServer.Configuration;
|
||||
using Moonlight.ApiServer.Database.Entities;
|
||||
@@ -28,12 +30,88 @@ public class AuthenticationMiddleware
|
||||
private async Task Authenticate(HttpContext context)
|
||||
{
|
||||
var request = context.Request;
|
||||
|
||||
if (!request.Cookies.TryGetValue("ml-access", out var accessToken) ||
|
||||
!request.Cookies.TryGetValue("ml-refresh", out var refreshToken))
|
||||
return;
|
||||
|
||||
if(string.IsNullOrEmpty(accessToken) || string.IsNullOrEmpty(refreshToken))
|
||||
return;
|
||||
|
||||
// TODO: Validate if both are valid jwts (maybe)
|
||||
|
||||
//
|
||||
var tokenHelper = context.RequestServices.GetRequiredService<TokenHelper>();
|
||||
var configService = context.RequestServices.GetRequiredService<ConfigService<AppConfiguration>>();
|
||||
|
||||
User? user = null;
|
||||
|
||||
if (!await tokenHelper.IsValidAccessToken(accessToken, configService.Get().Authentication.MlAccessSecret,
|
||||
data =>
|
||||
{
|
||||
if (!data.TryGetValue("userId", out var userIdStr))
|
||||
return false;
|
||||
|
||||
if (!int.TryParse(userIdStr, out var userId))
|
||||
return false;
|
||||
|
||||
var userRepo = context.RequestServices.GetRequiredService<DatabaseRepository<User>>();
|
||||
|
||||
user = userRepo.Get().FirstOrDefault(x => x.Id == userId);
|
||||
|
||||
return user != null;
|
||||
}))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(user == null)
|
||||
return;
|
||||
|
||||
// Validate external access
|
||||
if (DateTime.UtcNow > user.RefreshTimestamp)
|
||||
{
|
||||
var tokenConsumer = new TokenConsumer(user.AccessToken, user.RefreshToken, user.RefreshTimestamp,
|
||||
async refreshToken =>
|
||||
{
|
||||
var oauth2Service = context.RequestServices.GetRequiredService<OAuth2Service>();
|
||||
|
||||
var accessData = await oauth2Service.RefreshAccess(refreshToken);
|
||||
|
||||
user.AccessToken = accessData.AccessToken;
|
||||
user.RefreshToken = accessData.RefreshToken;
|
||||
user.RefreshTimestamp = DateTime.UtcNow.AddSeconds(accessData.ExpiresIn);
|
||||
|
||||
var userRepo = context.RequestServices.GetRequiredService<DatabaseRepository<User>>();
|
||||
|
||||
userRepo.Update(user);
|
||||
|
||||
return new TokenPair()
|
||||
{
|
||||
AccessToken = user.AccessToken,
|
||||
RefreshToken = user.RefreshToken
|
||||
};
|
||||
});
|
||||
|
||||
await tokenConsumer.GetAccessToken();
|
||||
//TODO: API CALL
|
||||
}
|
||||
|
||||
// Load permissions, handle empty values
|
||||
var permissions = JsonSerializer.Deserialize<string[]>(
|
||||
string.IsNullOrEmpty(user.PermissionsJson) ? "[]" : user.PermissionsJson
|
||||
) ?? [];
|
||||
|
||||
// Save permission state
|
||||
context.User = new PermClaimsPrinciple(permissions, user);
|
||||
|
||||
/*
|
||||
string? token = null;
|
||||
|
||||
// Cookie for Moonlight.Client
|
||||
if (request.Cookies.ContainsKey("token") && !string.IsNullOrEmpty(request.Cookies["token"]))
|
||||
token = request.Cookies["token"];
|
||||
|
||||
|
||||
// Header for api clients
|
||||
if (request.Headers.ContainsKey("Authorization") && !string.IsNullOrEmpty(request.Cookies["Authorization"]))
|
||||
{
|
||||
@@ -47,10 +125,10 @@ public class AuthenticationMiddleware
|
||||
token = headerParts[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(token == null)
|
||||
return;
|
||||
|
||||
|
||||
// Validate token
|
||||
if (token.Length > 300)
|
||||
{
|
||||
@@ -62,7 +140,7 @@ public class AuthenticationMiddleware
|
||||
if (token.Count(x => x == '.') == 2) // JWT only has two dots
|
||||
await AuthenticateUser(context, token);
|
||||
else
|
||||
await AuthenticateApiKey(context, token);
|
||||
await AuthenticateApiKey(context, token);*/
|
||||
}
|
||||
|
||||
private async Task AuthenticateUser(HttpContext context, string jwt)
|
||||
@@ -70,13 +148,13 @@ public class AuthenticationMiddleware
|
||||
var jwtHelper = context.RequestServices.GetRequiredService<JwtHelper>();
|
||||
var configService = context.RequestServices.GetRequiredService<ConfigService<AppConfiguration>>();
|
||||
var secret = configService.Get().Authentication.Secret;
|
||||
|
||||
if(!await jwtHelper.Validate(secret, jwt, "login"))
|
||||
|
||||
if (!await jwtHelper.Validate(secret, jwt, "login"))
|
||||
return;
|
||||
|
||||
var data = await jwtHelper.Decode(secret, jwt);
|
||||
|
||||
if(!data.TryGetValue("iat", out var issuedAtString) || !data.TryGetValue("userId", out var userIdString))
|
||||
|
||||
if (!data.TryGetValue("iat", out var issuedAtString) || !data.TryGetValue("userId", out var userIdString))
|
||||
return;
|
||||
|
||||
var userId = int.Parse(userIdString);
|
||||
@@ -84,12 +162,12 @@ public class AuthenticationMiddleware
|
||||
|
||||
var userRepo = context.RequestServices.GetRequiredService<DatabaseRepository<User>>();
|
||||
var user = userRepo.Get().FirstOrDefault(x => x.Id == userId);
|
||||
|
||||
if(user == null)
|
||||
|
||||
if (user == null)
|
||||
return;
|
||||
|
||||
|
||||
// Check if token is in the past
|
||||
if(user.TokenValidTimestamp > issuedAt)
|
||||
if (user.TokenValidTimestamp > issuedAt)
|
||||
return;
|
||||
|
||||
// Load permissions, handle empty values
|
||||
@@ -103,6 +181,5 @@ public class AuthenticationMiddleware
|
||||
|
||||
private async Task AuthenticateApiKey(HttpContext context, string apiKey)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user