aws / aws-aspnet-cognito-identity-provider

ASP.NET Core Identity Provider for Amazon Cognito
https://aws.amazon.com/developer/language/net/
Apache License 2.0
215 stars 89 forks source link

PasswordSignInAsync or CheckPasswordSignInAsync and SignInAsync are not persisting auth cookie User.Identity.IsAuthenticated is false #234

Closed sanasz91mdev closed 1 year ago

sanasz91mdev commented 1 year ago

Describe the bug

Hi, i am using oidc for federated identity (sign up with SAML) and AddCognitoIdentity for custom sign up and sign in in one single application

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();
builder.Services.AddCognitoIdentity();

var Configuration = builder.Configuration;
var services = builder.Services;

services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
            })
            .AddOpenIdConnect(options =>
            {
                options.ResponseType = Configuration["Authentication:Cognito:ResponseType"];
                options.MetadataAddress = Configuration["Authentication:Cognito:MetadataAddress"];
                options.ClientId = Configuration["Authentication:Cognito:ClientId"];
                options.CallbackPath = PathString.FromUriComponent("/externalauthentication/callback/");
                options.Scope.Clear();
                options.Scope.Add("openid");
                options.ClientSecret = Configuration["Authentication:Cognito:ClientSecret"];
                options.SkipUnrecognizedRequests = true;

                options.Events = new OpenIdConnectEvents()
                {
                    OnRedirectToIdentityProviderForSignOut = (context) =>
                    {
                        context.ProtocolMessage.Scope = "openid";
                        context.ProtocolMessage.ResponseType = "code";

                        var cognitoDomain = Configuration["Authentication:Cognito:CognitoDomain"];

                        var clientId = Configuration["Authentication:Cognito:ClientId"];

                        var logoutUrl = $"{context.Request.Scheme}://{context.Request.Host}{Configuration["Authentication:Cognito:AppSignOutUrl"]}";

                        context.ProtocolMessage.IssuerAddress = $"{cognitoDomain}/logout?client_id={clientId}&logout_uri={logoutUrl}&redirect_uri={logoutUrl}";

                        // delete cookies
                        context.Properties.Items.Remove(CookieAuthenticationDefaults.AuthenticationScheme);
                        // close openid session
                        context.Properties.Items.Remove(OpenIdConnectDefaults.AuthenticationScheme);

                        return Task.CompletedTask;
                    }
                };
               })
            .AddCookie();

builder.Services.AddAuthorization(options =>
{
    options.FallbackPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();

app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();

var fileExtensionContentTypeProvider = new FileExtensionContentTypeProvider();
fileExtensionContentTypeProvider.Mappings[".yaml"] = "text/yaml";
fileExtensionContentTypeProvider.Mappings[".yml"] = "text/yaml";

var fsoptions = new FileServerOptions();
fsoptions.StaticFileOptions.ContentTypeProvider = fileExtensionContentTypeProvider;
fsoptions.FileProvider = new PhysicalFileProvider(
           Path.Combine(builder.Environment.ContentRootPath, "staticfiles"));
fsoptions.RequestPath = "/staticfiles";

app.UseFileServer(fsoptions);

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}");

app.Run();

i have a signin with microsoft option to which i redirect as follows:

    function redirectToCognito() {
        window.location.href = 'https://abc-portal.auth.ap-south-1.amazoncognito.com/login?client_id=xxxxxxxxxxxxxxxxxxxxxxxx&response_type=code&scope=openid&redirect_uri=https://localhost:7041/externalauthentication/callback/'
    }

and i also have a custom login and sign up page where i use custom attributes to sign up and email, password to login

The problem is that either of these flows are unable to persist any auth cookie in .net despite of successful authentication from SAML/cognito. Callback URL is also invoked.

The following always returns false, even after next redirect:

if (User.Identity.IsAuthenticated)

This always returns successful sign in , but persists nothing in cookie and User.Identity.IsAuthenticated always false

[HttpPost]
    public async Task<IActionResult> Index(LoginViewModel user)
    {
        _logger.LogInformation(User.Identity.IsAuthenticated.ToString());
        if (User.Identity.IsAuthenticated)
        {
            return RedirectToAction("Index", "Home");
        }

        if (!ModelState.IsValid)
        {
            return View(user);
        }
        try
        {
            var cognitoUser = await _userManager.FindByEmailAsync(user.email);
            var signInResult = await _signInManager.CheckPasswordSignInAsync(cognitoUser, user.password, lockoutOnFailure: false);
            if (signInResult.Succeeded)
            {
                await _signInManager.SignInAsync(cognitoUser,
                    new AuthenticationProperties()
                    {
                        AllowRefresh = true,
                        IssuedUtc = DateTime.UtcNow,
                        ExpiresUtc = DateTime.UtcNow.AddDays(15),
                        IsPersistent = true
                    });
            }
            //_signInManager.ExternalLoginSignInAsync()
            //var result = await _signInManager.PasswordSignInAsync(user.email, user.password, true, false);
            TempData["email"] = user.email;
            if (signInResult.Succeeded)
            {
                _logger.LogInformation("User logged in.");
                return RedirectToAction("Index", "Home");
            }
}

Am i doing something wrong? Because i followed the entire documentation

Expected Behavior

if (User.Identity.IsAuthenticated)

should return true

Current Behavior

if (User.Identity.IsAuthenticated)

returning false even after successful authentication

Reproduction Steps

You can take code as described in description

Possible Solution

No response

Additional Information/Context

No response

AWS .NET SDK and/or Package version used

amazon.aspnetcore.identity.cognito 3.0.1

amazon.extensions.cognitoauthentication 2.5.1

microsoft.aspnetcore.authentication.openidconnect 6.0.13

Targeted .NET Platform

.NET 7

Operating System and version

Windows 10

ashishdhingra commented 1 year ago

@sanasz91mdev Good morning. Are you using external provider to signing in? Please refer existing feature request https://github.com/aws/aws-aspnet-cognito-identity-provider/issues/225 if it matches your use case.

sanasz91mdev commented 1 year ago

@sanasz91mdev Good morning. Are you using external provider to signing in? Please refer existing feature request #225 if it matches your use case.

No it doesn't... the signinasync successfully signs in but does not persist cookie due to which user.isAuthenticated is always false in .net 7 asp.ner core

ashishdhingra commented 1 year ago

@sanasz91mdev Good morning. Are you using external provider to signing in? Please refer existing feature request #225 if it matches your use case.

No it doesn't... the signinasync successfully signs in but does not persist cookie due to which user.isAuthenticated is always false in .net 7 asp.ner core

@sanasz91mdev Good afternoon. I do we missing block below after app.UseAuthentication():

app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });

Most of the online code samples and issues related to User.Identity.IsAuthenticated have been solved by online community by correcting the order of:

app.UseAuthentication();
app.UseAuthorization();

Thanks, Ashish

github-actions[bot] commented 1 year ago

This issue has not received a response in 5 days. If you want to keep this issue open, please just leave a comment below and auto-close will be canceled.

sanasz91mdev commented 1 year ago

Most of the online code samples and issues related to User.Identity.IsAuthenticated have been solved by online community by correcting the order of:

@ashishdhingra I use the same order ... still it does not update the User.Identity.IsAuthenticated ..

sanasz91mdev commented 1 year ago

This issue has not received a response in 5 days. If you want to keep this issue open, please just leave a comment below and auto-close will be canceled.

please re open issue as it still persis