You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The application I work with utilizes two seperate authentication schemes:
Microsoft entra id for internal users + Cookie
An external OIDC identity provider for external users + Cookie
Regarding routing, this is the general structure:
In addition, any blazor page whose path starts with "/internal" is authorized on page with custom authorization policies to check for specific claims, for example ...RequireClaim(ctx=> ctx.FindFirst(InternalUserIdClaimType) is not null)
Same goes for internal users.
For authenticated users, they simply dont use the same paths/route in the application.
However, they share the same entry point, route ("/"), which is the landing page for the application. This is configured with [AllowAnonymous].
My configuration looks something like this:
##Configuration
Authentication:
services.AddAuthentication(opts =>{ opts.DefaultScheme ="multischeme";}).AddPolicyScheme("multischeme","Internal or External",opts =>{ opts.ForwardDefaultSelector =ctx =>{if(ctx.Request.Path.StartsWithSegments("/auth/internal")|| ctx.Request.Path.StartsWithSegments("/internal/somepage")){return"InternalScheme";}// Does not allowed undefined, so we have to return one of the schemesreturn"ExternalScheme";};}).AddOpenIdConnect("InternalScheme","Internal auth scheme",options =>{ options.SignInScheme ="InternalCookieScheme";// <---- CUSTOM COOKIE SCHEME options.Authority ="xxxxxxxxx"; options.ClientId ="xxxxxxxxxxxxx"; options.ClientSecret ="xxxxxxxxxx"; options.CallbackPath =new PathString("/xxxx/return"); options.ResponseType ="code"; options.RequireHttpsMetadata =true; options.Events =new OpenIdConnectEvents{OnTokenValidated=ctx =>{// abbreviated, reading some claims, adding some custom claims to a new custom identity// custom claim is used to authorize internal usersreturn Task.CompletedTask;}};}).AddCookie("InternalCookieScheme","Internal auth cookie scheme",options =>{ options.Cookie.Name ="InternalAuthCookie";// abbreviated...}).AddOpenIdConnect("ExternalScheme","External auth scheme",options =>{ options.SignInScheme ="ExternalCookieScheme";// <---- CUSTOM COOKIE SCHEME options.Authority ="XXXXXXXXXXXXX"; options.ClientId ="xxxxxx"; options.ClientSecret ="xxxxx"; options.CallbackPath =new PathString("/xxxxxx/callback"); options.ResponseType ="code"; options.Scope.Clear(); options.Scope.Add("openid"); options.RequireHttpsMetadata =true; options.Events =new OpenIdConnectEvents{OnTokenValidated=async ctx =>{// abbreviated, reading some claims, adding some custom claims to a new custom identity// custom claim is used to authorize external usersreturn Task.CompletedTask;}};}).AddCookie("ExternalCookieScheme","External auth cookie scheme",options =>{ options.Cookie.Name ="ExternalAuthCookie";// abbreviated...});
Authorization:
services.AddAuthorization(config =>{// INTERNAL user policies config.AddPolicy(PolicyNames.IS_INTERNAL_USER,policy =>{ policy.AddRequirements(new IsInternalUserRequirement());});// EXTERNAL user policies config.AddPolicy(PolicyNames.IS_EXTERNAL_USER,policy =>{ policy.AddRequirements(new IsExternalUserRequirement());});});
In summary, I have one combined scheme ("Multischeme") that wraps around "InternalScheme" and "Externalscheme", which both respectively connects to "InternalCookieScheme" and "ExternalCookieScheme".
Endpoints
In addition, i have 2 controller endpoints for each specific scheme:
/auth/external/login
/auth/external/signout
/auth/internal/login
/auth/internal/signout
Main configuration (program.cs):
Auth handlers are registered earlier
Controllers are added
Routes.Razor:
Has AuthorizeRouteView
App.Razor:
As long as "ExternalScheme" is the default scheme, I can sign in / sign-out with the external OIDC provider and authorize just fine with it.
However, I cant authorize with internal user. I manage to sign in with it, Cookie gets set with values, but under ...context.User.Identittesthere is no user with those claims available in authorization.
Appreciate any help with this. I'm stomped! 😣
Expected Behavior
The claims from both schemes should be available when signing in.
Authhandlers should be able to find the claims for both signed in schemes when executing authorization handlers & requirements.
Only the default identity provided from the default scheme seems to be available when dooing authorization (both in authorizationhandlers, but also in controllers!)
Steps To Reproduce
Unfortunately i'm not at liberty to expose the external providers provided. I hope the code i've provided will be sufficient to reproduce the issue.
To use the .RequireAuthorization (config=> config.addPolicySchemes(Multischeme) for the app. I've found that this creates other issues..
Disabled one scheme entirely (works fine with one auth scheme + one cookie scheme just fine).
Attempted to do `context.SignInAsync("NON-defaultscheme") in controllers as I cant get the auth state available for whichever schema is not defaulted. so, for internalSchema: auth/internal/login --> Cant find claims/ identity to the internal user since externalscheme is default....
Swapped the default scheme to ensure claims actually gets set and is configured right with respect to the identity providers. ✅
Is there an existing issue for this?
Describe the bug
The application I work with utilizes two seperate authentication schemes:
Regarding routing, this is the general structure:
...RequireClaim(ctx=> ctx.FindFirst(InternalUserIdClaimType) is not null)
However, they share the same entry point, route ("/"), which is the landing page for the application. This is configured with
[AllowAnonymous]
.I've followed the instructions here for configuring multiple policy schemes:
https://learn.microsoft.com/en-us/aspnet/core/security/authentication/policyschemes?view=aspnetcore-8.0
My configuration looks something like this:
##Configuration
Authentication:
Authorization:
In summary, I have one combined scheme ("Multischeme") that wraps around "InternalScheme" and "Externalscheme", which both respectively connects to "InternalCookieScheme" and "ExternalCookieScheme".
Endpoints
In addition, i have 2 controller endpoints for each specific scheme:
Main configuration (program.cs):
Routes.Razor:
App.Razor:
As long as "ExternalScheme" is the default scheme, I can sign in / sign-out with the external OIDC provider and authorize just fine with it.
However, I cant authorize with internal user. I manage to sign in with it, Cookie gets set with values, but under
...context.User.Identittes
there is no user with those claims available in authorization.Appreciate any help with this. I'm stomped! 😣
Expected Behavior
The claims from both schemes should be available when signing in.
Authhandlers should be able to find the claims for both signed in schemes when executing authorization handlers & requirements.
Only the default identity provided from the default scheme seems to be available when dooing authorization (both in authorizationhandlers, but also in controllers!)
Steps To Reproduce
Unfortunately i'm not at liberty to expose the external providers provided. I hope the code i've provided will be sufficient to reproduce the issue.
Exceptions (if any)
None.
.NET Version
8.0.303
Anything else?
Another person on stackover flow seems to have a similar issue (unresolved). He only used a single oidc, but seemed to want another cookie.
https://stackoverflow.com/questions/78533634/asp-net-core-blazor-multiple-authentication-schemes-oidc-custom-cookies
dotnet info output:
![image](https://private-user-images.githubusercontent.com/21339565/352576268-04b972e3-7def-46e9-99e1-243d2b2982c9.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjIxNDQ3NTYsIm5iZiI6MTcyMjE0NDQ1NiwicGF0aCI6Ii8yMTMzOTU2NS8zNTI1NzYyNjgtMDRiOTcyZTMtN2RlZi00NmU5LTk5ZTEtMjQzZDJiMjk4MmM5LnBuZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MjglMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzI4VDA1MjczNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWY5MzIzNWM5ZWU0YTYyMTQ5NTJmMmJiY2FmNmZjMTI2ZDcwZDVhNDA4YzlmMDVmZWYxZjUzOTEyMDA0OGQ2NmImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.egycfDT144Aoe3ziYciorMIf_xZ-dKdnUEpyfjTUj9Q)
The text was updated successfully, but these errors were encountered: