-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAuthorizationCodeGrantHandler.cs
More file actions
90 lines (71 loc) · 3.53 KB
/
Copy pathAuthorizationCodeGrantHandler.cs
File metadata and controls
90 lines (71 loc) · 3.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
namespace HttpsRichardy.Federation.Application.Handlers.Authorization;
public sealed class AuthorizationCodeGrantHandler(IRealmCollection realmCollection, IUserCollection userCollection, IClientCollection clientCollection, ISecurityTokenService tokenService, ITokenCollection tokenCollection) :
IAuthorizationFlowHandler
{
public Grant Grant => Grant.AuthorizationCode;
public async Task<Result<ClientAuthenticationResult>> HandleAsync(
ClientAuthenticationCredentials parameters, CancellationToken cancellation = default)
{
var filters = new TokenFiltersBuilder()
.WithValue(parameters.Code)
.WithType(TokenType.AuthorizationCode)
.Build();
var tokens = await tokenCollection.GetTokensAsync(filters, cancellation: cancellation);
var token = tokens.FirstOrDefault();
if (token is null)
{
return Result<ClientAuthenticationResult>.Failure(AuthorizationErrors.InvalidAuthorizationCode);
}
if (token.IsExpired)
{
return Result<ClientAuthenticationResult>.Failure(AuthorizationErrors.AuthorizationCodeExpired);
}
var realmFilters = new RealmFiltersBuilder()
.WithIdentifier(token.RealmId)
.Build();
var realms = await realmCollection.GetRealmsAsync(realmFilters, cancellation: cancellation);
var realm = realms.FirstOrDefault();
if (realm is null)
{
return Result<ClientAuthenticationResult>.Failure(AuthenticationErrors.ClientNotFound);
}
var clientFilters = new ClientFiltersBuilder()
.WithClientId(parameters.ClientId)
.Build();
var clients = await clientCollection.GetClientsAsync(clientFilters, cancellation: cancellation);
var client = clients.FirstOrDefault();
if (client is null || !string.Equals(client.RealmId, token.RealmId, StringComparison.Ordinal))
{
return Result<ClientAuthenticationResult>.Failure(AuthorizationErrors.InvalidAuthorizationCode);
}
var boundClientId = token.Metadata.GetValueOrDefault("client.id");
if (!string.Equals(boundClientId, parameters.ClientId, StringComparison.Ordinal))
{
return Result<ClientAuthenticationResult>.Failure(AuthorizationErrors.InvalidAuthorizationCode);
}
var codeChallenge = token.Metadata.GetValueOrDefault("code.challenge")!;
var codeChallengeMethod = token.Metadata.GetValueOrDefault("code.challenge.method")!;
if (!PkceCodeVerifier.Validate(parameters.CodeVerifier, codeChallenge, codeChallengeMethod))
{
return Result<ClientAuthenticationResult>.Failure(AuthorizationErrors.InvalidCodeVerifier);
}
var userFilters = new UserFiltersBuilder()
.WithIdentifier(token.UserId)
.Build();
var users = await userCollection.GetUsersAsync(userFilters, cancellation: cancellation);
var user = users.FirstOrDefault();
if (user is null)
{
return Result<ClientAuthenticationResult>.Failure(AuthenticationErrors.UserNotFound);
}
var tokenResult = await tokenService.GenerateAccessTokenAsync(user, client.Audiences, cancellation);
if (tokenResult.IsFailure || tokenResult.Data is null)
{
return Result<ClientAuthenticationResult>.Failure(tokenResult.Error);
}
return Result<ClientAuthenticationResult>.Success(new()
{
AccessToken = tokenResult.Data.Value
});
}
}