@@ -49,7 +49,7 @@ Add the following to the appsettings.json with the scopes you made above and you
49
49
"Authority" : " https://mysite.catglobe.com/" ,
50
50
"ClientId" : " Production id" ,
51
51
"ResponseType" : " code" ,
52
- "DefaultScopes " : [ " email" , " offline_access" , " roles" , " and others from above, except profile and openid " ],
52
+ "Scope " : [ " email" , " offline_access" , " roles" , " and others from above, except profile and openid " ],
53
53
"SaveTokens" : true
54
54
},
55
55
"CatglobeApi" : {
@@ -103,7 +103,6 @@ services.AddAuthentication(SCHEMENAME)
103
103
builder .Configuration .GetSection (SCHEMENAME ).Bind (oidcOptions );
104
104
oidcOptions .SignInScheme = CookieAuthenticationDefaults .AuthenticationScheme ;
105
105
oidcOptions .TokenValidationParameters .NameClaimType = " name" ;
106
- oidcOptions .TokenValidationParameters .RoleClaimType = " cg_roles" ;
107
106
})
108
107
.AddCookie (CookieAuthenticationDefaults .AuthenticationScheme );
109
108
services .AddCgScript (builder .Configuration .GetSection (" CatglobeApi" ), builder .Environment .IsDevelopment ());
@@ -221,7 +220,6 @@ services.AddAuthentication(SCHEMENAME)
221
220
builder .Configuration .GetSection (SCHEMENAME ).Bind (oidcOptions );
222
221
oidcOptions .SignInScheme = CookieAuthenticationDefaults .AuthenticationScheme ;
223
222
oidcOptions .TokenValidationParameters .NameClaimType = " name" ;
224
- oidcOptions .TokenValidationParameters .RoleClaimType = " cg_roles" ;
225
223
226
224
oidcOptions .Events .OnRedirectToIdentityProvider = context => {
227
225
if (context .Properties .Items .TryGetValue (" respondent" , out var resp ) &&
@@ -252,6 +250,85 @@ services.AddAuthentication(SCHEMENAME)
252
250
gotoUrl("https://siteurl.com/authentication/login?respondent=" + User_getCurrentUser().ResourceGuid + "&respondent_secret=" + qas.AccessCode);");
253
251
```
254
252
253
+ ## I18n and email
254
+
255
+ Users language, culture, timezone and email is stored in Catglobe. To use in your app, add the following:
256
+
257
+ ``` csharp
258
+ .AddOpenIdConnect (SCHEMENAME , oidcOptions => {
259
+ .. .
260
+ // to get the locale/culture
261
+ oidcOptions .ClaimActions .MapUniqueJsonKey (" locale" , " locale" );
262
+ oidcOptions .ClaimActions .MapUniqueJsonKey (" culture" , " culture" );
263
+
264
+ // must be true to get the zoneinfo and email claims
265
+ oidcOptions .GetClaimsFromUserInfoEndpoint = true ;
266
+ oidcOptions .ClaimActions .MapUniqueJsonKey (" zoneinfo" , " zoneinfo" );
267
+ })
268
+ ```
269
+
270
+ If you use Blazor WASM, you need to also send these claims to the WASM and parse them:
271
+
272
+ ``` csharp
273
+ // in SERVER program.cs:
274
+ .. .
275
+ .AddAuthenticationStateSerialization (o => o .SerializeAllClaims = true );
276
+ ```
277
+
278
+ ``` csharp
279
+ builder .Services .AddAuthenticationStateDeserialization (o => o .DeserializationCallback = ProcessLanguageAndCultureFromClaims (o .DeserializationCallback ));
280
+
281
+ static Func < AuthenticationStateData ? , Task < AuthenticationState >> ProcessLanguageAndCultureFromClaims (Func < AuthenticationStateData ? , Task < AuthenticationState >> authenticationStateData ) =>
282
+ state => {
283
+ var tsk = authenticationStateData (state );
284
+ if (! tsk .IsCompletedSuccessfully ) return tsk ;
285
+ var authState = tsk .Result ;
286
+ if (authState ? .User is not { } user ) return tsk ;
287
+ var userCulture = user .FindFirst (" culture" )? .Value ;
288
+ var userUiCulture = user .FindFirst (" locale" )? .Value ?? userCulture ;
289
+ if (userUiCulture == null ) return tsk ;
290
+
291
+ CultureInfo .DefaultThreadCurrentCulture = new (userCulture ?? userUiCulture );
292
+ CultureInfo .DefaultThreadCurrentUICulture = new (userUiCulture );
293
+ return tsk ;
294
+ };
295
+
296
+ ```
297
+
298
+ You can adapt something like https://www.meziantou.net/convert-datetime-to-user-s-time-zone-with-server-side-blazor-time-provider.htm for timezone
299
+
300
+ ## Role based authorization in your app
301
+
302
+ If you want to use roles in your app, you need to request roles from oidc:
303
+ ``` json
304
+ "CatglobeOidc" : {
305
+ ...
306
+ "Scope" : [ ... "roles", ],
307
+ },
308
+ ```
309
+
310
+ Next, you need to make a script that detect the users roles:
311
+
312
+ ``` cgscript
313
+ array scopesRequested = Workflow_getParameters()[0]["scopes"];
314
+ ...do some magic to figure out the roles...
315
+ return {"thisUserIsAdmin"};
316
+ ```
317
+
318
+ You can make this script public.
319
+
320
+ ``` cgscript
321
+ OidcAuthenticationFlow client = OidcAuthenticationFlow_createOrUpdate("some id, a guid works, but any string is acceptable");
322
+ client.AppRolesScriptId = 424242; // the script that returns the roles
323
+ ...
324
+ ```
325
+
326
+ and finally in any page, you can add either ` @attribute [Authorize(Roles = "thisUserIsAdmin")] ` or ` <AuthorizeView Roles="thisUserIsAdmin">Only visible to admins<AuthorizeView> ` .
327
+
328
+ Why can the script NOT be in the app? Because it needs to run __ before__ the app is ever deployed.
329
+
330
+ ** NOTICE!** We may change the way to setup the script in the future to avoid the bootstrapping issue.
331
+
255
332
# Usage of the library
256
333
257
334
## Development
0 commit comments