Skip to content

Commit b07161f

Browse files
committed
Added ISessionValidator
1 parent 00b1e50 commit b07161f

File tree

11 files changed

+304
-417
lines changed

11 files changed

+304
-417
lines changed

src/CodeBeam.UltimateAuth.Server/Abstractions/IHttpSessionIssuer.cs

Lines changed: 0 additions & 19 deletions
This file was deleted.

src/CodeBeam.UltimateAuth.Server/Auth/Context/AuthFlowContextFactory.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ internal sealed class DefaultAuthFlowContextFactory : IAuthFlowContextFactory
2222
private readonly IAuthResponseResolver _authResponseResolver;
2323
private readonly IDeviceResolver _deviceResolver;
2424
private readonly IDeviceContextFactory _deviceContextFactory;
25-
private readonly ISessionQueryService _sessionQueryService;
25+
private readonly ISessionValidator _sessionValidator;
2626

2727
public DefaultAuthFlowContextFactory(
2828
IClientProfileReader clientProfileReader,
@@ -31,15 +31,15 @@ public DefaultAuthFlowContextFactory(
3131
IAuthResponseResolver authResponseResolver,
3232
IDeviceResolver deviceResolver,
3333
IDeviceContextFactory deviceContextFactory,
34-
ISessionQueryService sessionQueryService)
34+
ISessionValidator sessionValidator)
3535
{
3636
_clientProfileReader = clientProfileReader;
3737
_primaryTokenResolver = primaryTokenResolver;
3838
_serverOptionsProvider = serverOptionsProvider;
3939
_authResponseResolver = authResponseResolver;
4040
_deviceResolver = deviceResolver;
4141
_deviceContextFactory = deviceContextFactory;
42-
_sessionQueryService = sessionQueryService;
42+
_sessionValidator = sessionValidator;
4343
}
4444

4545
public async ValueTask<AuthFlowContext> CreateAsync(HttpContext ctx, AuthFlowType flowType, CancellationToken ct = default)
@@ -64,7 +64,7 @@ public async ValueTask<AuthFlowContext> CreateAsync(HttpContext ctx, AuthFlowTyp
6464

6565
if (!sessionCtx.IsAnonymous)
6666
{
67-
var validation = await _sessionQueryService.ValidateSessionAsync(
67+
var validation = await _sessionValidator.ValidateSessionAsync(
6868
new SessionValidationContext
6969
{
7070
TenantId = sessionCtx.TenantId,

src/CodeBeam.UltimateAuth.Server/Authentication/UAuthAuthenticationHandler.cs

Lines changed: 4 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,16 @@
44
using CodeBeam.UltimateAuth.Core.Extensions;
55
using CodeBeam.UltimateAuth.Server.Defaults;
66
using CodeBeam.UltimateAuth.Server.Infrastructure;
7-
using CodeBeam.UltimateAuth.Server.Services;
87
using Microsoft.AspNetCore.Authentication;
98
using Microsoft.Extensions.Logging;
109
using Microsoft.Extensions.Options;
11-
using System.Security.Claims;
1210

1311
namespace CodeBeam.UltimateAuth.Server.Authentication;
1412

1513
internal sealed class UAuthAuthenticationHandler : AuthenticationHandler<UAuthAuthenticationCookieOptions>
1614
{
1715
private readonly ITransportCredentialResolver _transportCredentialResolver;
18-
private readonly ISessionQueryService _sessionQuery;
16+
private readonly ISessionValidator _sessionValidator;
1917
private readonly IDeviceContextFactory _deviceContextFactory;
2018
private readonly IClock _clock;
2119

@@ -25,13 +23,13 @@ public UAuthAuthenticationHandler(
2523
ILoggerFactory logger,
2624
System.Text.Encodings.Web.UrlEncoder encoder,
2725
ISystemClock clock,
28-
ISessionQueryService sessionQuery,
26+
ISessionValidator sessionValidator,
2927
IDeviceContextFactory deviceContextFactory,
3028
IClock uauthClock)
3129
: base(options, logger, encoder, clock)
3230
{
3331
_transportCredentialResolver = transportCredentialResolver;
34-
_sessionQuery = sessionQuery;
32+
_sessionValidator = sessionValidator;
3533
_deviceContextFactory = deviceContextFactory;
3634
_clock = uauthClock;
3735
}
@@ -45,7 +43,7 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
4543
if (!AuthSessionId.TryCreate(credential.Value, out var sessionId))
4644
return AuthenticateResult.Fail("Invalid credential");
4745

48-
var result = await _sessionQuery.ValidateSessionAsync(
46+
var result = await _sessionValidator.ValidateSessionAsync(
4947
new SessionValidationContext
5048
{
5149
TenantId = credential.TenantId,
@@ -59,46 +57,5 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
5957

6058
var principal = result.Claims.ToClaimsPrincipal(UAuthCookieDefaults.AuthenticationScheme);
6159
return AuthenticateResult.Success(new AuthenticationTicket(principal, UAuthCookieDefaults.AuthenticationScheme));
62-
63-
64-
//var principal = CreatePrincipal(result);
65-
//var ticket = new AuthenticationTicket(principal,UAuthCookieDefaults.AuthenticationScheme);
66-
67-
//return AuthenticateResult.Success(ticket);
6860
}
69-
70-
private static ClaimsPrincipal CreatePrincipal(SessionValidationResult result)
71-
{
72-
//var claims = new List<Claim>
73-
//{
74-
// new Claim(ClaimTypes.NameIdentifier, result.UserKey.Value),
75-
// new Claim("uauth:session_id", result.SessionId.ToString())
76-
//};
77-
78-
//if (!string.IsNullOrEmpty(result.TenantId))
79-
//{
80-
// claims.Add(new Claim("uauth:tenant", result.TenantId));
81-
//}
82-
83-
//// Session claims (snapshot)
84-
//foreach (var (key, value) in result.Claims.AsDictionary())
85-
//{
86-
// if (key == "http://schemas.microsoft.com/ws/2008/06/identity/claims/role")
87-
// {
88-
// foreach (var role in value.Split(','))
89-
// claims.Add(new Claim(ClaimTypes.Role, role));
90-
// }
91-
// else
92-
// {
93-
// claims.Add(new Claim(key, value));
94-
// }
95-
//}
96-
97-
//var identity = new ClaimsIdentity(claims, UAuthCookieDefaults.AuthenticationScheme);
98-
//return new ClaimsPrincipal(identity);
99-
100-
var identity = new ClaimsIdentity(result.Claims.ToClaims(), UAuthCookieDefaults.AuthenticationScheme);
101-
return new ClaimsPrincipal(identity);
102-
}
103-
10461
}
Lines changed: 64 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,94 @@
11
using CodeBeam.UltimateAuth.Core.Abstractions;
22
using CodeBeam.UltimateAuth.Core.Contracts;
33
using CodeBeam.UltimateAuth.Core.Domain;
4-
using CodeBeam.UltimateAuth.Core.Extensions;
54
using CodeBeam.UltimateAuth.Server.Auth;
65
using CodeBeam.UltimateAuth.Server.Infrastructure;
7-
using CodeBeam.UltimateAuth.Server.Services;
86
using Microsoft.AspNetCore.Http;
97

10-
namespace CodeBeam.UltimateAuth.Server.Endpoints
8+
namespace CodeBeam.UltimateAuth.Server.Endpoints;
9+
10+
internal sealed class DefaultValidateEndpointHandler : IValidateEndpointHandler
1111
{
12-
internal sealed class DefaultValidateEndpointHandler : IValidateEndpointHandler
12+
private readonly IAuthFlowContextAccessor _authContext;
13+
private readonly IFlowCredentialResolver _credentialResolver;
14+
private readonly ISessionValidator _sessionValidator;
15+
private readonly IClock _clock;
16+
17+
public DefaultValidateEndpointHandler(
18+
IAuthFlowContextAccessor authContext,
19+
IFlowCredentialResolver credentialResolver,
20+
ISessionValidator sessionValidator,
21+
IClock clock)
22+
{
23+
_authContext = authContext;
24+
_credentialResolver = credentialResolver;
25+
_sessionValidator = sessionValidator;
26+
_clock = clock;
27+
}
28+
29+
public async Task<IResult> ValidateAsync(HttpContext context, CancellationToken ct = default)
1330
{
14-
private readonly IAuthFlowContextAccessor _authContext;
15-
private readonly IFlowCredentialResolver _credentialResolver;
16-
private readonly ISessionQueryService _sessionValidator;
17-
private readonly IClock _clock;
31+
var auth = _authContext.Current;
32+
var credential = _credentialResolver.Resolve(context, auth.Response);
1833

19-
public DefaultValidateEndpointHandler(
20-
IAuthFlowContextAccessor authContext,
21-
IFlowCredentialResolver credentialResolver,
22-
ISessionQueryService sessionValidator,
23-
IClock clock)
34+
if (credential is null)
2435
{
25-
_authContext = authContext;
26-
_credentialResolver = credentialResolver;
27-
_sessionValidator = sessionValidator;
28-
_clock = clock;
36+
return Results.Json(
37+
new AuthValidationResult
38+
{
39+
IsValid = false,
40+
State = "missing"
41+
},
42+
statusCode: StatusCodes.Status401Unauthorized
43+
);
2944
}
3045

31-
public async Task<IResult> ValidateAsync(HttpContext context, CancellationToken ct = default)
46+
if (credential.Kind == PrimaryCredentialKind.Stateful)
3247
{
33-
var auth = _authContext.Current;
34-
var credential = _credentialResolver.Resolve(context, auth.Response);
35-
36-
if (credential is null)
48+
if (!AuthSessionId.TryCreate(credential.Value, out var sessionId))
3749
{
3850
return Results.Json(
3951
new AuthValidationResult
4052
{
4153
IsValid = false,
42-
State = "missing"
54+
State = "invalid"
4355
},
4456
statusCode: StatusCodes.Status401Unauthorized
4557
);
4658
}
4759

48-
if (credential.Kind == PrimaryCredentialKind.Stateful)
49-
{
50-
if (!AuthSessionId.TryCreate(credential.Value, out var sessionId))
60+
var result = await _sessionValidator.ValidateSessionAsync(
61+
new SessionValidationContext
5162
{
52-
return Results.Json(
53-
new AuthValidationResult
54-
{
55-
IsValid = false,
56-
State = "invalid"
57-
},
58-
statusCode: StatusCodes.Status401Unauthorized
59-
);
60-
}
61-
62-
var result = await _sessionValidator.ValidateSessionAsync(
63-
new SessionValidationContext
64-
{
65-
TenantId = credential.TenantId,
66-
SessionId = sessionId,
67-
Now = _clock.UtcNow,
68-
Device = auth.Device
69-
},
70-
ct);
71-
72-
return Results.Ok(new AuthValidationResult
73-
{
74-
IsValid = result.IsValid,
75-
State = result.IsValid ? "active" : result.State.ToString().ToLowerInvariant(),
76-
Snapshot = new AuthStateSnapshot
77-
{
78-
UserId = result.UserKey,
79-
TenantId = result.TenantId,
80-
Claims = result.Claims,
81-
AuthenticatedAt = _clock.UtcNow,
82-
}
83-
});
84-
}
63+
TenantId = credential.TenantId,
64+
SessionId = sessionId,
65+
Now = _clock.UtcNow,
66+
Device = auth.Device
67+
},
68+
ct);
8569

86-
// Stateless (JWT / Opaque) – 0.0.1 no support yet
87-
return Results.Json(
88-
new AuthValidationResult
70+
return Results.Ok(new AuthValidationResult
71+
{
72+
IsValid = result.IsValid,
73+
State = result.IsValid ? "active" : result.State.ToString().ToLowerInvariant(),
74+
Snapshot = new AuthStateSnapshot
8975
{
90-
IsValid = false,
91-
State = "unsupported"
92-
},
93-
statusCode: StatusCodes.Status401Unauthorized
94-
);
76+
UserId = result.UserKey,
77+
TenantId = result.TenantId,
78+
Claims = result.Claims,
79+
AuthenticatedAt = _clock.UtcNow,
80+
}
81+
});
9582
}
83+
84+
// Stateless (JWT / Opaque) – 0.0.1 no support yet
85+
return Results.Json(
86+
new AuthValidationResult
87+
{
88+
IsValid = false,
89+
State = "unsupported"
90+
},
91+
statusCode: StatusCodes.Status401Unauthorized
92+
);
9693
}
9794
}

src/CodeBeam.UltimateAuth.Server/Extensions/UAuthServerServiceCollectionExtensions.cs

Lines changed: 1 addition & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ private static IServiceCollection AddUltimateAuthServerInternal(this IServiceCol
179179
services.TryAddScoped(typeof(ISessionQueryService), typeof(UAuthSessionQueryService));
180180
services.TryAddScoped(typeof(IRefreshTokenResolver), typeof(DefaultRefreshTokenResolver));
181181
services.TryAddScoped(typeof(ISessionTouchService), typeof(DefaultSessionTouchService));
182+
services.TryAddScoped<ISessionValidator, UAuthSessionValidator>();
182183
services.TryAddScoped<IDeviceResolver, DefaultDeviceResolver>();
183184
services.TryAddScoped<ICredentialResponseWriter, DefaultCredentialResponseWriter>();
184185
services.TryAddScoped<IFlowCredentialResolver, DefaultFlowCredentialResolver>();
@@ -229,7 +230,6 @@ private static IServiceCollection AddUltimateAuthServerInternal(this IServiceCol
229230

230231
services.TryAddScoped<AuthFlowEndpointFilter>();
231232

232-
233233
services.TryAddSingleton<IAuthEndpointRegistrar, UAuthEndpointRegistrar>();
234234

235235
// Endpoint handlers
@@ -247,43 +247,10 @@ private static IServiceCollection AddUltimateAuthServerInternal(this IServiceCol
247247

248248
services.TryAddScoped<DefaultPkceEndpointHandler<UserKey>>();
249249
services.TryAddScoped<IPkceEndpointHandler, PkceEndpointHandlerBridge>();
250-
//services.TryAddScoped<IReauthEndpointHandler, ReauthEndpointHandler>();
251-
//services.TryAddScoped<ITokenEndpointHandler, TokenEndpointHandler>();
252-
//services.TryAddScoped<IUserInfoEndpointHandler, UserInfoEndpointHandler>();
253250

254251
return services;
255252
}
256253

257-
//internal static IServiceCollection AddUltimateAuthPolicies(this IServiceCollection services, Action<AccessPolicyRegistry>? configure = null)
258-
//{
259-
// if (services.Any(d => d.ServiceType == typeof(AccessPolicyRegistry)))
260-
// throw new InvalidOperationException("UltimateAuth policies already registered.");
261-
262-
// var registry = new AccessPolicyRegistry();
263-
264-
// DefaultPolicySet.Register(registry);
265-
// configure?.Invoke(registry);
266-
// services.AddSingleton(registry);
267-
// services.AddSingleton<IAccessPolicyProvider>(sp =>
268-
// {
269-
// var compiled = registry.Build();
270-
// return new DefaultAccessPolicyProvider(compiled, sp);
271-
// });
272-
273-
// services.TryAddScoped<IAccessAuthority>(sp =>
274-
// {
275-
// var invariants = sp.GetServices<IAccessInvariant>();
276-
// var globalPolicies = sp.GetServices<IAccessPolicy>();
277-
278-
// return new DefaultAccessAuthority(invariants, globalPolicies);
279-
// });
280-
281-
// services.TryAddScoped<IAccessOrchestrator, UAuthAccessOrchestrator>();
282-
283-
284-
// return services;
285-
//}
286-
287254
internal static IServiceCollection AddUltimateAuthPolicies(this IServiceCollection services, Action<AccessPolicyRegistry>? configure = null)
288255
{
289256
if (services.Any(d => d.ServiceType == typeof(AccessPolicyRegistry)))

0 commit comments

Comments
 (0)