-
Notifications
You must be signed in to change notification settings - Fork 598
Multiple OIDC handlers will get in each others way. #348
Comments
Isn't each oidc MW instance having its own authenticationScheme sufficient? |
This is handled fine by all the other middlewares today, this should just work... |
It's fine for challenges, the collision occurs on the (optional) callback path. The other middelware would have the same problem. You either need to set unique callback paths or implement the MessageReceived notification and manually filter them. |
@brentschmaltz out of curiosity, why not using @HaoK fine is probably not the most appropriate term 😄 Consider this snippet: app.UseOAuthAuthentication("Scheme1", options => {
options.Caption = "Caption1";
options.ClientId = "ClientId1";
options.ClientSecret = "ClientSecret1";
options.AuthorizationEndpoint = "AuthorizationEndpoint1";
options.TokenEndpoint = "TokenEndpoint1";
});
app.UseOAuthAuthentication("Scheme2", options => {
options.Caption = "Caption2";
options.ClientId = "ClientId2";
options.ClientSecret = "ClientSecret2";
options.AuthorizationEndpoint = "AuthorizationEndpoint2";
options.TokenEndpoint = "TokenEndpoint2";
});
app.Run(async context => {
foreach (var scheme in context.Authentication.GetAuthenticationSchemes()) {
await context.Response.WriteAsync($"{scheme.AuthenticationScheme}: {scheme.Caption}");
}
}); It will work just fine ( But this snippet will miserably fail and only return the options used for the first Google middleware: app.UseGoogleAuthentication(options => {
options.AuthenticationScheme = "Scheme1";
options.Caption = "Caption1";
options.ClientId = "ClientId1";
options.ClientSecret = "ClientSecret1";
options.AuthorizationEndpoint = "AuthorizationEndpoint1";
options.TokenEndpoint = "TokenEndpoint1";
});
app.UseGoogleAuthentication(options => {
options.AuthenticationScheme = "Scheme2";
options.Caption = "Caption2";
options.ClientId = "ClientId2";
options.ClientSecret = "ClientSecret2";
options.AuthorizationEndpoint = "AuthorizationEndpoint2";
options.TokenEndpoint = "TokenEndpoint2";
});
app.Run(async context => {
foreach (var scheme in context.Authentication.GetAuthenticationSchemes()) {
await context.Response.WriteAsync($"{scheme.AuthenticationScheme}: {scheme.Caption}");
}
}); Of course, this can be fixed using the second parameter (that sets the options instance name), but it's not terribly obvious for a beginner, specially for those who used this pattern with Katana. |
Yeah that pain point is well known to me since I ran into (and is what prompted named options in the first place). If you have any suggestions on how to improve that scenario, definitely willing to make it better. Its super hard to discover today, even if you were to look at identity code which is the only one that relies on this, its super subtle and easy to miss... |
The issue is actually in the sugar methods, they are implicitly providing "Google"/option names which is why if you don't specify the name, they collide. |
@HaoK, actually, I wonder if we shouldn't simply stop retrieving the options from the DI when using the |
We could certainly stop using IOptions for middlewares, as not all of them do, but there's a consistency issue there where Options are sometimes singletons then, and sometimes instances... Probably should rename them to be Settings and not options just to disambiguate that they aren't like the rest of the options in the framework... |
@Tratcher yes the issue is on the way in. In fact un-initiated login updates may occur. |
This is no longer an issue because we require a callback path now, so each middleware can have its own path. |
Considering the case where a user has two OIDC Middleware each with a different authority and hence different config (keys, issuer, etc).
One will fail, possibly triggering an update to the IDP for new config, throw, add error logs, etc. The other will succeed. Depends on who gets the message first.
We need a way for a MW to know it should handle the signin message.
Solutions could be as simple as using state to add logic: "yes" this is for me. This means crypto for each MW. A "dispatcher / router" or "handlers multiplexing options", etc .. at this layer seems complicated.
The text was updated successfully, but these errors were encountered: