4
4
using System ;
5
5
using System . Collections . Generic ;
6
6
using System . Linq ;
7
+ using System . Security . Claims ;
7
8
using System . Text . Json ;
8
9
using System . Threading ;
9
10
using System . Threading . Tasks ;
11
+ using Microsoft . AspNetCore . Components . WebAssembly . Authentication . Internal ;
10
12
using Microsoft . Extensions . Options ;
11
13
using Microsoft . JSInterop ;
14
+ using Moq ;
12
15
using Xunit ;
13
16
14
17
namespace Microsoft . AspNetCore . Components . WebAssembly . Authentication
@@ -21,10 +24,11 @@ public async Task RemoteAuthenticationService_SignIn_UpdatesUserOnSuccess()
21
24
// Arrange
22
25
var testJsRuntime = new TestJsRuntime ( ) ;
23
26
var options = CreateOptions ( ) ;
24
- var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , OidcProviderOptions > (
27
+ var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , RemoteUserAccount , OidcProviderOptions > (
25
28
testJsRuntime ,
26
29
options ,
27
- new TestNavigationManager ( ) ) ;
30
+ new TestNavigationManager ( ) ,
31
+ new UserFactory < RemoteUserAccount > ( Mock . Of < IAccessTokenProviderAccessor > ( ) ) ) ;
28
32
29
33
var state = new RemoteAuthenticationState ( ) ;
30
34
testJsRuntime . SignInResult = new InternalRemoteAuthenticationResult < RemoteAuthenticationState >
@@ -51,10 +55,11 @@ public async Task RemoteAuthenticationService_SignIn_DoesNotUpdateUserOnOtherRes
51
55
// Arrange
52
56
var testJsRuntime = new TestJsRuntime ( ) ;
53
57
var options = CreateOptions ( ) ;
54
- var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , OidcProviderOptions > (
58
+ var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , RemoteUserAccount , OidcProviderOptions > (
55
59
testJsRuntime ,
56
60
options ,
57
- new TestNavigationManager ( ) ) ;
61
+ new TestNavigationManager ( ) ,
62
+ new UserFactory < RemoteUserAccount > ( Mock . Of < IAccessTokenProviderAccessor > ( ) ) ) ;
58
63
59
64
var state = new RemoteAuthenticationState ( ) ;
60
65
testJsRuntime . SignInResult = new InternalRemoteAuthenticationResult < RemoteAuthenticationState >
@@ -77,10 +82,11 @@ public async Task RemoteAuthenticationService_CompleteSignInAsync_UpdatesUserOnS
77
82
// Arrange
78
83
var testJsRuntime = new TestJsRuntime ( ) ;
79
84
var options = CreateOptions ( ) ;
80
- var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , OidcProviderOptions > (
85
+ var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , RemoteUserAccount , OidcProviderOptions > (
81
86
testJsRuntime ,
82
87
options ,
83
- new TestNavigationManager ( ) ) ;
88
+ new TestNavigationManager ( ) ,
89
+ new UserFactory < RemoteUserAccount > ( Mock . Of < IAccessTokenProviderAccessor > ( ) ) ) ;
84
90
85
91
var state = new RemoteAuthenticationState ( ) ;
86
92
testJsRuntime . CompleteSignInResult = new InternalRemoteAuthenticationResult < RemoteAuthenticationState >
@@ -107,10 +113,11 @@ public async Task RemoteAuthenticationService_CompleteSignInAsync_DoesNotUpdateU
107
113
// Arrange
108
114
var testJsRuntime = new TestJsRuntime ( ) ;
109
115
var options = CreateOptions ( ) ;
110
- var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , OidcProviderOptions > (
116
+ var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , RemoteUserAccount , OidcProviderOptions > (
111
117
testJsRuntime ,
112
118
options ,
113
- new TestNavigationManager ( ) ) ;
119
+ new TestNavigationManager ( ) ,
120
+ new UserFactory < RemoteUserAccount > ( Mock . Of < IAccessTokenProviderAccessor > ( ) ) ) ;
114
121
115
122
var state = new RemoteAuthenticationState ( ) ;
116
123
testJsRuntime . CompleteSignInResult = new InternalRemoteAuthenticationResult < RemoteAuthenticationState >
@@ -133,10 +140,11 @@ public async Task RemoteAuthenticationService_SignOut_UpdatesUserOnSuccess()
133
140
// Arrange
134
141
var testJsRuntime = new TestJsRuntime ( ) ;
135
142
var options = CreateOptions ( ) ;
136
- var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , OidcProviderOptions > (
143
+ var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , RemoteUserAccount , OidcProviderOptions > (
137
144
testJsRuntime ,
138
145
options ,
139
- new TestNavigationManager ( ) ) ;
146
+ new TestNavigationManager ( ) ,
147
+ new UserFactory < RemoteUserAccount > ( Mock . Of < IAccessTokenProviderAccessor > ( ) ) ) ;
140
148
141
149
var state = new RemoteAuthenticationState ( ) ;
142
150
testJsRuntime . SignOutResult = new InternalRemoteAuthenticationResult < RemoteAuthenticationState >
@@ -163,10 +171,11 @@ public async Task RemoteAuthenticationService_SignOut_DoesNotUpdateUserOnOtherRe
163
171
// Arrange
164
172
var testJsRuntime = new TestJsRuntime ( ) ;
165
173
var options = CreateOptions ( ) ;
166
- var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , OidcProviderOptions > (
174
+ var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , RemoteUserAccount , OidcProviderOptions > (
167
175
testJsRuntime ,
168
176
options ,
169
- new TestNavigationManager ( ) ) ;
177
+ new TestNavigationManager ( ) ,
178
+ new UserFactory < RemoteUserAccount > ( Mock . Of < IAccessTokenProviderAccessor > ( ) ) ) ;
170
179
171
180
var state = new RemoteAuthenticationState ( ) ;
172
181
testJsRuntime . SignOutResult = new InternalRemoteAuthenticationResult < RemoteAuthenticationState >
@@ -189,10 +198,11 @@ public async Task RemoteAuthenticationService_CompleteSignOutAsync_UpdatesUserOn
189
198
// Arrange
190
199
var testJsRuntime = new TestJsRuntime ( ) ;
191
200
var options = CreateOptions ( ) ;
192
- var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , OidcProviderOptions > (
201
+ var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , RemoteUserAccount , OidcProviderOptions > (
193
202
testJsRuntime ,
194
203
options ,
195
- new TestNavigationManager ( ) ) ;
204
+ new TestNavigationManager ( ) ,
205
+ new UserFactory < RemoteUserAccount > ( Mock . Of < IAccessTokenProviderAccessor > ( ) ) ) ;
196
206
197
207
var state = new RemoteAuthenticationState ( ) ;
198
208
testJsRuntime . CompleteSignOutResult = new InternalRemoteAuthenticationResult < RemoteAuthenticationState >
@@ -219,10 +229,11 @@ public async Task RemoteAuthenticationService_CompleteSignOutAsync_DoesNotUpdate
219
229
// Arrange
220
230
var testJsRuntime = new TestJsRuntime ( ) ;
221
231
var options = CreateOptions ( ) ;
222
- var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , OidcProviderOptions > (
232
+ var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , RemoteUserAccount , OidcProviderOptions > (
223
233
testJsRuntime ,
224
234
options ,
225
- new TestNavigationManager ( ) ) ;
235
+ new TestNavigationManager ( ) ,
236
+ new UserFactory < RemoteUserAccount > ( Mock . Of < IAccessTokenProviderAccessor > ( ) ) ) ;
226
237
227
238
var state = new RemoteAuthenticationState ( ) ;
228
239
testJsRuntime . CompleteSignOutResult = new InternalRemoteAuthenticationResult < RemoteAuthenticationState >
@@ -245,10 +256,11 @@ public async Task RemoteAuthenticationService_GetAccessToken_ReturnsAccessTokenR
245
256
// Arrange
246
257
var testJsRuntime = new TestJsRuntime ( ) ;
247
258
var options = CreateOptions ( ) ;
248
- var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , OidcProviderOptions > (
259
+ var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , RemoteUserAccount , OidcProviderOptions > (
249
260
testJsRuntime ,
250
261
options ,
251
- new TestNavigationManager ( ) ) ;
262
+ new TestNavigationManager ( ) ,
263
+ new UserFactory < RemoteUserAccount > ( Mock . Of < IAccessTokenProviderAccessor > ( ) ) ) ;
252
264
253
265
var state = new RemoteAuthenticationState ( ) ;
254
266
testJsRuntime . GetAccessTokenResult = new InternalAccessTokenResult
@@ -282,10 +294,11 @@ public async Task RemoteAuthenticationService_GetAccessToken_PassesDownOptions()
282
294
// Arrange
283
295
var testJsRuntime = new TestJsRuntime ( ) ;
284
296
var options = CreateOptions ( ) ;
285
- var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , OidcProviderOptions > (
297
+ var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , RemoteUserAccount , OidcProviderOptions > (
286
298
testJsRuntime ,
287
299
options ,
288
- new TestNavigationManager ( ) ) ;
300
+ new TestNavigationManager ( ) ,
301
+ new UserFactory < RemoteUserAccount > ( Mock . Of < IAccessTokenProviderAccessor > ( ) ) ) ;
289
302
290
303
var state = new RemoteAuthenticationState ( ) ;
291
304
testJsRuntime . GetAccessTokenResult = new InternalAccessTokenResult
@@ -321,10 +334,11 @@ public async Task RemoteAuthenticationService_GetAccessToken_ComputesDefaultRetu
321
334
// Arrange
322
335
var testJsRuntime = new TestJsRuntime ( ) ;
323
336
var options = CreateOptions ( ) ;
324
- var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , OidcProviderOptions > (
337
+ var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , RemoteUserAccount , OidcProviderOptions > (
325
338
testJsRuntime ,
326
339
options ,
327
- new TestNavigationManager ( ) ) ;
340
+ new TestNavigationManager ( ) ,
341
+ new UserFactory < RemoteUserAccount > ( Mock . Of < IAccessTokenProviderAccessor > ( ) ) ) ;
328
342
329
343
var state = new RemoteAuthenticationState ( ) ;
330
344
testJsRuntime . GetAccessTokenResult = new InternalAccessTokenResult
@@ -361,12 +375,13 @@ public async Task RemoteAuthenticationService_GetUser_ReturnsAnonymousClaimsPrin
361
375
// Arrange
362
376
var testJsRuntime = new TestJsRuntime ( ) ;
363
377
var options = CreateOptions ( ) ;
364
- var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , OidcProviderOptions > (
378
+ var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , RemoteUserAccount , OidcProviderOptions > (
365
379
testJsRuntime ,
366
380
options ,
367
- new TestNavigationManager ( ) ) ;
381
+ new TestNavigationManager ( ) ,
382
+ new UserFactory < RemoteUserAccount > ( Mock . Of < IAccessTokenProviderAccessor > ( ) ) ) ;
368
383
369
- testJsRuntime . GetUserResult = null ;
384
+ testJsRuntime . GetUserResult = default ;
370
385
371
386
// Act
372
387
var result = await runtime . GetAuthenticatedUser ( ) ;
@@ -387,19 +402,22 @@ public async Task RemoteAuthenticationService_GetUser_ReturnsUser_ForAuthenticat
387
402
// Arrange
388
403
var testJsRuntime = new TestJsRuntime ( ) ;
389
404
var options = CreateOptions ( ) ;
390
- var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , OidcProviderOptions > (
405
+ var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , CoolRoleAccount , OidcProviderOptions > (
391
406
testJsRuntime ,
392
407
options ,
393
- new TestNavigationManager ( ) ) ;
408
+ new TestNavigationManager ( ) ,
409
+ new TestUserFactory ( Mock . Of < IAccessTokenProviderAccessor > ( ) ) ) ;
394
410
395
- var serializationOptions = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy . CamelCase , PropertyNameCaseInsensitive = true } ;
396
- var serializedUser = JsonSerializer . Serialize ( new
411
+ var account = new CoolRoleAccount
397
412
{
398
- CoolName = "Alfred" ,
399
- CoolRole = new [ ] { "admin" , "cool" , "fantastic" }
400
- } , serializationOptions ) ;
413
+ CoolRole = new [ ] { "admin" , "cool" , "fantastic" } ,
414
+ AdditionalProperties = new Dictionary < string , object >
415
+ {
416
+ [ "CoolName" ] = JsonSerializer . Deserialize < JsonElement > ( JsonSerializer . Serialize ( "Alfred" ) )
417
+ }
418
+ } ;
401
419
402
- testJsRuntime . GetUserResult = JsonSerializer . Deserialize < IDictionary < string , object > > ( serializedUser ) ;
420
+ testJsRuntime . GetUserResult = account ;
403
421
404
422
// Act
405
423
var result = await runtime . GetAuthenticatedUser ( ) ;
@@ -420,19 +438,22 @@ public async Task RemoteAuthenticationService_GetUser_DoesNotMapScopesToRoles()
420
438
// Arrange
421
439
var testJsRuntime = new TestJsRuntime ( ) ;
422
440
var options = CreateOptions ( "scope" ) ;
423
- var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , OidcProviderOptions > (
441
+ var runtime = new RemoteAuthenticationService < RemoteAuthenticationState , CoolRoleAccount , OidcProviderOptions > (
424
442
testJsRuntime ,
425
443
options ,
426
- new TestNavigationManager ( ) ) ;
444
+ new TestNavigationManager ( ) ,
445
+ new TestUserFactory ( Mock . Of < IAccessTokenProviderAccessor > ( ) ) ) ;
427
446
428
- var serializationOptions = new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy . CamelCase , PropertyNameCaseInsensitive = true } ;
429
- var serializedUser = JsonSerializer . Serialize ( new
447
+ var account = new CoolRoleAccount
430
448
{
431
- CoolName = "Alfred" ,
432
- CoolRole = new [ ] { "admin" , "cool" , "fantastic" }
433
- } , serializationOptions ) ;
449
+ CoolRole = new [ ] { "admin" , "cool" , "fantastic" } ,
450
+ AdditionalProperties = new Dictionary < string , object >
451
+ {
452
+ [ "CoolName" ] = JsonSerializer . Deserialize < JsonElement > ( JsonSerializer . Serialize ( "Alfred" ) ) ,
453
+ }
454
+ } ;
434
455
435
- testJsRuntime . GetUserResult = JsonSerializer . Deserialize < IDictionary < string , object > > ( serializedUser ) ;
456
+ testJsRuntime . GetUserResult = account ;
436
457
testJsRuntime . GetAccessTokenResult = new InternalAccessTokenResult
437
458
{
438
459
Status = "success" ,
@@ -509,22 +530,21 @@ private class TestJsRuntime : IJSRuntime
509
530
510
531
public InternalAccessTokenResult GetAccessTokenResult { get ; set ; }
511
532
512
- public IDictionary < string , object > GetUserResult { get ; set ; }
533
+ public RemoteUserAccount GetUserResult { get ; set ; }
513
534
514
535
public ValueTask < TValue > InvokeAsync < TValue > ( string identifier , object [ ] args )
515
536
{
516
537
PastInvocations . Add ( ( identifier , args ) ) ;
517
- return new ValueTask < TValue > ( ( TValue ) GetInvocationResult < TValue > ( identifier ) ) ;
538
+ return new ValueTask < TValue > ( ( TValue ) GetInvocationResult ( identifier ) ) ;
518
539
}
519
540
520
-
521
541
public ValueTask < TValue > InvokeAsync < TValue > ( string identifier , CancellationToken cancellationToken , object [ ] args )
522
542
{
523
543
PastInvocations . Add ( ( identifier , args ) ) ;
524
- return new ValueTask < TValue > ( ( TValue ) GetInvocationResult < TValue > ( identifier ) ) ;
544
+ return new ValueTask < TValue > ( ( TValue ) GetInvocationResult ( identifier ) ) ;
525
545
}
526
546
527
- private object GetInvocationResult < TValue > ( string identifier )
547
+ private object GetInvocationResult ( string identifier )
528
548
{
529
549
switch ( identifier )
530
550
{
@@ -551,6 +571,35 @@ private object GetInvocationResult<TValue>(string identifier)
551
571
}
552
572
}
553
573
574
+ internal class TestUserFactory : UserFactory < CoolRoleAccount >
575
+ {
576
+ public TestUserFactory ( IAccessTokenProviderAccessor accessor ) : base ( accessor )
577
+ {
578
+ }
579
+
580
+ public override async ValueTask < ClaimsPrincipal > CreateUserAsync (
581
+ CoolRoleAccount account ,
582
+ RemoteAuthenticationUserOptions options )
583
+ {
584
+ var user = await base . CreateUserAsync ( account , options ) ;
585
+
586
+ if ( account . CoolRole != null )
587
+ {
588
+ foreach ( var role in account . CoolRole )
589
+ {
590
+ ( ( ClaimsIdentity ) user . Identity ) . AddClaim ( new Claim ( "CoolRole" , role ) ) ;
591
+ }
592
+ }
593
+
594
+ return user ;
595
+ }
596
+ }
597
+
598
+ internal class CoolRoleAccount : RemoteUserAccount
599
+ {
600
+ public string [ ] CoolRole { get ; set ; }
601
+ }
602
+
554
603
internal class TestNavigationManager : NavigationManager
555
604
{
556
605
public TestNavigationManager ( ) =>
0 commit comments