oauth-2.0identityserver4.net-6.0openid-connectokta-api

What to put for the scheme in AuthenticationHttpContextExtensions.AuthenticateAsync()


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: enter image description here

However, I realised I could rename this cookie using this code in Startup.ConfigureServices():

    services.ConfigureExternalCookie(config =>
    {                
        config.Cookie.Name = "test12";
    });

enter image description here

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.


Solution

  • 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