.Net Core 3.1 OpenIdConnect with AWS Cognito

Viewed 2698

I've been trying to get AWS Incognito working with ASP.NET Core 3.1 all day and am missing sime essential piece.

The code below is close because:

It Will

  • Let the user go through the built-in ASP.NET Identity user registration and login pages
  • That will result in records for the user in both the AspNetUsers table and the AspNetUserLogins table.
  • Appear to log the user in when they pass through the ASP.Net Identity UI ExternalLogin.cshml page's Callback method: enter image description here

  • But in reality ASP.Net Identity is unaware of this user enter image description here

  • In addition it will result in an infinite loop if you try to access an authorized page, bouncing between the requested page, the AWS Cognito server, and the "signin-oidc" built-in route.

enter image description here

The line I suspect the most is:

options.SignInScheme = IdentityConstants.ExternalScheme;

As the code comments mention, commentng out this line will break the built-in registration, but solve the infiniteloop problem (as well as let the openid claims cookie stay populated).

It's pretty clear that it's close, but there's something not quite linked up to bring it all together.

var awsCognitoRegion = "us-east-1";
var awsCognitoPoolId = "******";
var metaDataAddress = $"https://cognito-idp.{awsCognitoRegion}.amazonaws.com/{awsCognitoPoolId}/.well-known/openid-configuration";
//var awsCognitoResponseType = "code";
var awsCognitoMetaAddress = metaDataAddress;
var awsCognitoClientId = "*******************";
var awsCognitoSecret = "**********************";

services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
    //fixes "Error loading external login information" error on Identity Login page / callback
    //after external login...but breaks identity/cookie/claims?
    //
    //Also Causes infinite redirect problem via signin-oidc
    options.SignInScheme = IdentityConstants.ExternalScheme;

    //show all claims since MS filters some out...
    options.ClaimActions.Clear();

    //Tell .Net Core identity where to find the "name"
    //options.TokenValidationParameters.NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress";
    options.TokenValidationParameters.NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier";

    options.ResponseType = "code";
    options.MetadataAddress = metaDataAddress;
    options.ClientId = awsCognitoClientId;
    options.ClientSecret = awsCognitoSecret;

    options.SaveTokens = true;
    options.GetClaimsFromUserInfoEndpoint = true;

    //I think all I need here is email
    options.Scope.Add("email");
    options.Scope.Add("profile");
    options.Scope.Add("openid");
    //options.Scope.Add("aws.cognito.signin.user.admin");
});
1 Answers

As these authentication things always are, it ended up being one property missing/set wrong.

In this case it was that the SigninManager was checking if the Identity had principal.Identities.Any(i => i.AuthenticationType == IdentityConstants.ApplicationScheme); (https://github.com/aspnet/Identity/blob/master/src/Identity/SignInManager.cs). This is why even though the Identity would have IsAuthentictated = true, the built-in ASP.Net Identity pages were broken, because that value was set to AuthenticationTypes.Federation.

After more digging around I discovered that in the options of the .AddOpenIdConnect method there is a way to set that:

options.TokenValidationParameters.AuthenticationType = IdentityConstants.ApplicationScheme;

That finally made ASP.Net Identity aware that I was logged in (through OpenId).

Related