HttpContext.User.Identity.IsAuthenticated is false after calling HttpContext.SignInAsync("schema-name", claimsPrincipal);

1.1k Views Asked by At

I am using multiple authentication schemes. Here is my Startup.cs code -

public void ConfigureServices(IServiceCollection services)
    {
        //code

        services.AddAuthentication(options =>
        {
            options.DefaultAuthenticateScheme = "Default";
            options.DefaultSignInScheme = "Default";
            options.DefaultChallengeScheme = "O365OpenId";
        })
                .AddCookie("Default",options =>
                {
                    options.LoginPath = "/";
                    options.LogoutPath = "/Logout";
                    options.Cookie.Name = "ip" + guid.ToString();
                    options.AccessDeniedPath = "/Auth/Denied";
                    
                })
                .AddCookie("External", options =>
                 {
                     options.LoginPath = "/Auth/External";
                     options.LogoutPath = "/Logout";
                     options.Cookie.Name = "ip" + guid.ToString();
                     options.AccessDeniedPath = "/Auth/Denied";
                 })
                .AddOAuth("O365OpenId", options =>
                {
                    //options.Authority = "given";
                    options.ClientId = "given";
                    options.ClientSecret = "given";
                    options.CallbackPath = "/auth/callback";
                    options.AuthorizationEndpoint = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize";
                    options.AuthorizationEndpoint += "?prompt=select_account";
                    options.TokenEndpoint = "https://login.microsoftonline.com/common/oauth2/v2.0/token";
                    options.UserInformationEndpoint = "https://graph.microsoft.com/oidc/userinfo";
                    options.AccessDeniedPath = "/Auth/Denied";
                    options.Scope.Add("openid");
                    options.Scope.Add("email");
                    //options.Scope.Add("profile");
                    //options.Scope.Add("offline_access");
                    //options.Scope.Add("user.read");
                    //options.Scope.Add("calendars.read");
                    options.SaveTokens = false;
                    //options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id");
                    //options.ClaimActions.MapJsonKey(ClaimTypes.GivenName, "given_name");
                    //options.ClaimActions.MapJsonKey(ClaimTypes.Surname, "family_name");
                    //options.ClaimActions.MapJsonKey(ClaimTypes.Name, "name");
                    options.ClaimActions.MapJsonKey(ClaimTypes.Email, "email");
                    //options.ClaimActions.MapJsonKey(ClaimTypes., "picture");
                    options.Events = new OAuthEvents
                    {
                        OnCreatingTicket = async context =>
                        {
                            if (context.AccessToken is { })
                            {
                                context.Identity?.AddClaim(new Claim("access_token", context.AccessToken));
                            }
                            var request = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint);
                            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
                            var response = await context.Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, context.HttpContext.RequestAborted);
                            response.EnsureSuccessStatusCode();
                            var json = JsonDocument.Parse(await response.Content.ReadAsStringAsync());
                            context.RunClaimActions(json.RootElement);
                            
                    };
                });

        services.AddAuthorization(options =>
        {

            options.AddPolicy("Admin", policy =>
            {
                policy.AuthenticationSchemes.Add(CookieAuthenticationDefaults.AuthenticationScheme);
                policy.RequireAuthenticatedUser();
                policy.RequireRole("Admin");
            });

            options.AddPolicy("Regular&Admin", policy =>
            {
                policy.AuthenticationSchemes.Add(CookieAuthenticationDefaults.AuthenticationScheme);
                policy.RequireAuthenticatedUser();
                policy.RequireRole("Regular");
            });

            options.AddPolicy("External", policy =>
            {
                policy.AuthenticationSchemes.Add("External");
                policy.RequireAuthenticatedUser();
                policy.RequireRole("External");
            });
        });
        
    }

When I sign in user using the "Default" scheme, I find that the HttpContext.User.Identity.IsAuthenticated is true after HttpContext.SignInAsync("schema-name", claimsPrincipal); method call. Here is the code for signing in -

public async Task<IActionResult> Success(string returnUrl)
    {
        // code

                var claimIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
                var claimsPrincipal = new ClaimsPrincipal(claimIdentity);
                await HttpContext.SignInAsync("Default",claimsPrincipal);

                // more code
    }

isAuthenticated is true

But When I sign in user using "External" scheme, HttpContext.User.Identity.IsAuthenticated is false after HttpContext.SignInAsync("schema-name", claimsPrincipal); call. Here is the code for signing in -

    public async Task<IActionResult> External([FromQuery] string ReturnUrl, LoginOTP loginOTP, string email)
    {
        //code

            var claimIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
            var claimsPrincipal = new ClaimsPrincipal(claimIdentity);
            
            await HttpContext.SignInAsync("External", claimsPrincipal);

            //code
    }

IsAuthenticated is false.

I cannot understand what I am doing wrong. Why is the IsAuthenticated returning false? Please help. Thank you.

1

There are 1 best solutions below

2
YoussefSell On

you have 3 authentication schemes

  • the first one is cookie-based and you named it: "Default",
  • the second one is also cookie-based and you named it: "External",
  • the third one is OAhut-based and you named it: "O365OpenId",

when referring to one of these schemes you should use the names that you have created.

now the issue is, that you're creating a ClaimeIdentity with one scheme but you signing the user with a different scheme.

for the external method it should be like this:

var claimIdentity = new ClaimsIdentity(claims, "External");
var claimsPrincipal = new ClaimsPrincipal(claimIdentity);

// code ... 

await HttpContext.SignInAsync("External", claimsPrincipal);

now the claims principal will be associated with the "External" scheme and the user will be authenticated.