I'm using OIDC with Identity Server 4 which is authenticating with Okta.
I'm calling var result = await HttpContext.AuthenticateAsync("Identity.External");
in a callback method.
I chose Identity.External
as the scheme because I noticed that was the name of the cookie in the request to the callback method:
However, I realised I could rename this cookie using this code in Startup.ConfigureServices()
:
services.ConfigureExternalCookie(config =>
{
config.Cookie.Name = "test12";
});
But after renaming the cookie, the call to HttpContext.AuthenticateAsync("Identity.External")
still works, so it appears that the scheme name has nothing to do with this cookie name.
How do we know what string value to put in there?
Is there a list of acceptable values somewhere?
Here's my Startup.ConfigureServices()
:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; // "Cookies"
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
options.DefaultSignOutScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect("oidc", "OpenIdConnect", options =>
{
options.Authority = "oktaUrlHere";
options.ClientId = "clientIdHere";
options.ClientSecret = "clientSecretHere";
options.SaveTokens = true;
options.ResponseType = "code";
options.Scope.Add("groups");
options.Scope.Add("email");
options.Events = new CustomOpenIdConnectEvents
{
...
};
});
UPDATE:
I tried prepending the scheme with "1" just to see what would happen:
var result = await HttpContext.AuthenticateAsync("1Identity.External");
It returned this error which contains a list of registered schemes:
An unhandled exception occurred while processing the request.
InvalidOperationException: No authentication handler is registered for the scheme '1Identity.External'.
The registered schemes are: Identity.Application, Identity.External, Identity.TwoFactorRememberMe, Identity.TwoFactorUserId, idsrv, idsrv.external, Cookies, oidc. Did you forget to call AddAuthentication().Add[SomeAuthHandler]("1Identity.External",...)?
Are these schemes all registered by default?
Is this documented anywhere?
UPDATE:
I put a breakpoint in the following code to view the values for the properties on options
:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
options.DefaultSignOutScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
I can see the default value for DefaultAuthenticateScheme
is Identity.Application
, and the default value for DefaultSignInScheme
is Identity.External
.
Since options.DefaultAuthenticateScheme
has a value, options.DefaultScheme
("Cookies"
) will not be used.
According to msdn, DefaultAuthenticateScheme
is:
used as the default scheme by AuthenticateAsync(HttpContext, String).
If that's the case, why does the scheme passed to AuthenticateAsync()
need to be the value for DefaultSignInScheme
("Identity.External"
) and not DefaultAuthenticateScheme
("Identity.Application"
)?
UPDATE:
In this Duende example, they use:
services.AddAuthentication()
.AddOpenIdConnect("AAD", "Employee Login", options =>
{
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme;
// other options omitted
});
and authenticate using:
var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);
which also goes against what the Microsoft documentation says.
the name of the cookie is unrelated to what you are trying to do.
In your Client configuration, you typically have something like this:
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
}).AddCookie(opt =>
{
...
}).AddOpenIdConnect(options =>
{
...
});
What you put inside this method
HttpContext.AuthenticateAsync("Identity.External")
Is the name of the scheme.
But, typically, when you use OpenIDConnect, you want to challenge the user via the OpenIDConnect handler, so if what you are trying to achieve is to ask the user to login, then you should use something like this:
HttpContext.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme)
To, summarize:
you can name the handlers whatever you like, and then you register what handler to handle which event.
services.AddAuthentication(options =>
{
options.DefaultScheme = "MyCookieScheme"; //Do use the cookie handler for everyhthing except Challenge
options.DefaultChallengeScheme = "MyOIDCScheme";
}).AddCookie("MyCookieScheme", opt =>
{
}).AddOpenIdConnect("MyOIDCScheme",options =>
{
});
Then later in the code when you want to ask the user to login.
//Please use the handler with the MyOIDCScheme name to challenge the user
HttpContext.AuthenticateAsync("MyOIDCScheme");
About the question about those specific names, the names are registered internally by IdentityServer, for example, see the log here: https://github.com/DuendeSoftware/Support/issues/477
IT says in the log output:
[13:35:16 Information] Duende.IdentityServer.Startup
Using the default authentication scheme Identity.Application for IdentityServer
[13:35:16 Debug] Duende.IdentityServer.Startup
Using Identity.Application as default ASP.NET Core scheme for authentication
[13:35:16 Debug] Duende.IdentityServer.Startup
Using Identity.External as default ASP.NET Core scheme for sign-in
[13:35:16 Debug] Duende.IdentityServer.Startup
Using Identity.External as default ASP.NET Core scheme for sign-out
[13:35:16 Debug] Duende.IdentityServer.Startup
Using Identity.Application as default ASP.NET Core scheme for challenge
[13:35:16 Debug] Duende.IdentityServer.Startup
Using Identity.Application as default ASP.NET Core scheme for forbid