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

1

0

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.

Interjacent answered 10/5, 2023 at 7:33 Comment(0)
W
1

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
Warton answered 10/5, 2023 at 7:49 Comment(9)
I'm using asking the user to log in by redirecting them via return Challenge(props, provider); which seems to be working fine. Is that the same as using HttpContext.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme)?Interjacent
I'm using "Cookies" as the DefaultScheme, not "Identity.External". If the value passed to AuthenticateAsync() needs to match what I have in ConfigureServices(), which is "Cookies", then how does the AuthenticateAsync() call still succeed? I've updated my question with my Startup.cs code.Interjacent
I just debugged services.AddAuthentication() and can see options.DefaultSignInScheme is Identity.External, but options.DefaultAuthenticateScheme is Identity.Application. Now I'm really confused because it would appear that I should use AuthenticateAsync("Identity.Application") which results in result.Succeeded = false in the callback.Interjacent
return Challenge(props, provider) or ChallengeAsync is the same thing, asking the user to authenticate.Warton
In the client application, the Authenticate function is managed by the cookie handler and its job is to convert the incoming cookie (if found and valid) into a ClainsPrincipal user, that'all. You typically don't call Authenticate in your code.Warton
But I might have read your question wrong, what I wrote is about the client application talking to IdentityServer. For Federated, see this page docs.duendesoftware.com/identityserver/v6/ui/login/externalWarton
In your answer you say HttpContext.AuthenticateAsync("Identity.External") but how did you know to use "Identity.External"? Does this have to be set in Startup.cs? If so, where?Interjacent
Its just a custom name of an authentication handler, similar to you set AAD to be the name of the handler in this code snippet: .AddOpenIdConnect("AAD"....,) somewhere you added handler with then name Identity.External.Warton
But there's also idsrv, idsrv.external, Identity.External, OpenIdConnect etc, how did you know to use Identity.External and not the others?Interjacent

© 2022 - 2024 — McMap. All rights reserved.