4
4
using System . Security . Claims ;
5
5
using System . Text . Encodings . Web ;
6
6
using Microsoft . AspNetCore . Authentication . BearerToken . DTO ;
7
- using Microsoft . AspNetCore . DataProtection ;
8
7
using Microsoft . AspNetCore . Http ;
9
8
using Microsoft . Extensions . Logging ;
10
9
using Microsoft . Extensions . Options ;
11
10
using Microsoft . Net . Http . Headers ;
12
11
13
12
namespace Microsoft . AspNetCore . Authentication . BearerToken ;
14
13
15
- internal sealed class BearerTokenHandler (
16
- IOptionsMonitor < BearerTokenOptions > optionsMonitor ,
17
- ILoggerFactory loggerFactory ,
18
- UrlEncoder urlEncoder ,
19
- IDataProtectionProvider dataProtectionProvider )
14
+ internal sealed class BearerTokenHandler ( IOptionsMonitor < BearerTokenOptions > optionsMonitor , ILoggerFactory loggerFactory , UrlEncoder urlEncoder )
20
15
: SignInAuthenticationHandler < BearerTokenOptions > ( optionsMonitor , loggerFactory , urlEncoder )
21
16
{
22
- private const string BearerTokenPurpose = "BearerToken" ;
23
- private const string RefreshTokenPurpose = "RefreshToken" ;
24
-
25
17
private static readonly long OneSecondTicks = TimeSpan . FromSeconds ( 1 ) . Ticks ;
26
18
27
19
private static readonly AuthenticateResult FailedUnprotectingToken = AuthenticateResult . Fail ( "Unprotected token failed" ) ;
28
20
private static readonly AuthenticateResult TokenExpired = AuthenticateResult . Fail ( "Token expired" ) ;
29
21
30
- private ISecureDataFormat < AuthenticationTicket > TokenProtector
31
- => Options . TokenProtector ?? new TicketDataFormat ( dataProtectionProvider . CreateProtector ( "Microsoft.AspNetCore.Authentication.BearerToken" , Scheme . Name ) ) ;
32
-
33
22
private new BearerTokenEvents Events => ( BearerTokenEvents ) base . Events ! ;
34
23
35
24
protected override async Task < AuthenticateResult > HandleAuthenticateAsync ( )
@@ -51,7 +40,7 @@ protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
51
40
return AuthenticateResult . NoResult ( ) ;
52
41
}
53
42
54
- var ticket = TokenProtector . Unprotect ( token , BearerTokenPurpose ) ;
43
+ var ticket = Options . BearerTokenProtector . Unprotect ( token ) ;
55
44
56
45
if ( ticket ? . Properties ? . ExpiresUtc is not { } expiresUtc )
57
46
{
@@ -78,48 +67,17 @@ protected override async Task HandleSignInAsync(ClaimsPrincipal user, Authentica
78
67
79
68
properties ??= new ( ) ;
80
69
properties . ExpiresUtc ??= utcNow + Options . BearerTokenExpiration ;
81
- var isRefresh = properties . RefreshToken is not null ;
82
-
83
- if ( isRefresh )
84
- {
85
- var refreshTicket = TokenProtector . Unprotect ( properties . RefreshToken , RefreshTokenPurpose ) ;
86
-
87
- if ( refreshTicket ? . Properties ? . ExpiresUtc is not { } expiresUtc || TimeProvider . GetUtcNow ( ) >= expiresUtc )
88
- {
89
- await ChallengeAsync ( properties ) ;
90
- return ;
91
- }
92
-
93
- user = refreshTicket . Principal ;
94
- }
95
-
96
- var signingInContext = new SigningInContext ( Context , Scheme , Options , user , properties ) ;
97
-
98
- await Events . SigningInAsync ( signingInContext ) ;
99
-
100
- if ( signingInContext . Principal ? . Identity ? . Name is null )
101
- {
102
- await ChallengeAsync ( properties ) ;
103
- return ;
104
- }
105
70
106
71
var response = new AccessTokenResponse
107
72
{
108
- AccessToken = signingInContext . AccessToken ?? TokenProtector . Protect ( CreateAccessTicket ( signingInContext ) , BearerTokenPurpose ) ,
109
- ExpiresInSeconds = CalculateExpiresInSeconds ( utcNow , signingInContext . Properties . ExpiresUtc ) ,
110
- RefreshToken = signingInContext . RefreshToken ?? TokenProtector . Protect ( CreateRefreshTicket ( user , utcNow ) , RefreshTokenPurpose ) ,
73
+ AccessToken = Options . BearerTokenProtector . Protect ( CreateBearerTicket ( user , properties ) ) ,
74
+ ExpiresInSeconds = CalculateExpiresInSeconds ( utcNow , properties . ExpiresUtc ) ,
75
+ RefreshToken = Options . RefreshTokenProtector . Protect ( CreateRefreshTicket ( user , utcNow ) ) ,
111
76
} ;
112
77
113
- await Context . Response . WriteAsJsonAsync ( response , BearerTokenJsonSerializerContext . Default . AccessTokenResponse ) ;
78
+ Logger . AuthenticationSchemeSignedIn ( Scheme . Name ) ;
114
79
115
- if ( isRefresh )
116
- {
117
- Logger . AuthenticationSchemeSignedInWithRefreshToken ( Scheme . Name ) ;
118
- }
119
- else
120
- {
121
- Logger . AuthenticationSchemeSignedIn ( Scheme . Name ) ;
122
- }
80
+ await Context . Response . WriteAsJsonAsync ( response , BearerTokenJsonSerializerContext . Default . AccessTokenResponse ) ;
123
81
}
124
82
125
83
// No-op to avoid interfering with any mass sign-out logic.
@@ -152,8 +110,8 @@ static DateTimeOffset FloorSeconds(DateTimeOffset dateTimeOffset)
152
110
} ) ;
153
111
}
154
112
155
- private static AuthenticationTicket CreateAccessTicket ( SigningInContext context )
156
- => new ( context . Principal ! , context . Properties , context . Scheme . Name ) ;
113
+ private AuthenticationTicket CreateBearerTicket ( ClaimsPrincipal user , AuthenticationProperties properties )
114
+ => new ( user , properties , $ " { Scheme . Name } :AccessToken" ) ;
157
115
158
116
private AuthenticationTicket CreateRefreshTicket ( ClaimsPrincipal user , DateTimeOffset utcNow )
159
117
{
@@ -162,6 +120,6 @@ private AuthenticationTicket CreateRefreshTicket(ClaimsPrincipal user, DateTimeO
162
120
ExpiresUtc = utcNow + Options . RefreshTokenExpiration
163
121
} ;
164
122
165
- return new AuthenticationTicket ( user , refreshProperties , $ "{ Scheme . Name } :{ RefreshTokenPurpose } ") ;
123
+ return new AuthenticationTicket ( user , refreshProperties , $ "{ Scheme . Name } :RefreshToken ") ;
166
124
}
167
125
}
0 commit comments