How to configure an MVC 5 application with Cognito federated authentication

Viewed 1123

I'm trying to get an MVC 5 application authenticating with a configured SAML Provider in Amazon Cognito via OWIN middleware.

In my Startup class I have:

app.Use(typeof(AuthenticationMiddleware));
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
    AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
    LoginPath = new PathString("/Account/Login"),
    Provider = new CookieAuthenticationProvider
    {
        OnValidateIdentity = MyCustomValidateIdentity
    },
    SlidingExpiration = true,
    ExpireTimeSpan = TimeSpan.FromMinutes(timespan)
});

var config = ConfigHelper.CognitoConfigSection;
var signingCert = new X509Certificate2(Encoding.ASCII.GetBytes(config.cert));
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    AuthenticationType = "Cognito",
    AuthenticationMode = AuthenticationMode.Passive,
    Authority = $"https://cognito-idp.{config.Region}.amazonaws.com/{config.UserPoolId}",
    ResponseType = "code",
    ClientId = config.UserpoolClientId,
    ClientSecret = config.UserpoolClientSecret,
    Scope = String.Join(" ", "openid", "profile", "email"),
    MetadataAddress = $"https://cognito-idp.{config.Region}.amazonaws.com/{config.UserPoolId}/.well-known/openid-configuration",
    RedirectUri = "http://localhost:12345",
    TokenValidationParameters = new TokenValidationParameters
    {
        SaveSigninToken = true,
        RequireSignedTokens = true,
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new X509SecurityKey(signingCert),
        ValidateLifetime = true,
        ValidateAudience = false,
        ValidateIssuer = false,
        ValidIssuer = $"https://cognito-idp.{config.Region}.amazonaws.com/{config.UserPoolId}",
        ClockSkew = TimeSpan.FromMinutes(0)
    },
    SignInAsAuthenticationType = "Cookies",
    Notifications = new OpenIdConnectAuthenticationNotifications
    {
        // Defined all of these with break points to see what hit and what didn't
        RedirectToIdentityProvider = (ctx) =>
        {
            // This break point hits when auth challenge is initiated
            return Task.FromResult(0);
        },
        MessageReceived = (ctx) =>
        {
            // This break point and all the rest never hit.
            return Task.FromResult(0);
        },
        AuthorizationCodeReceived = (ctx) =>
        {
            return Task.FromResult(0);
        },
        AuthenticationFailed = (ctx) =>
        {
            return Task.FromResult(0);
        },
        SecurityTokenReceived = (ctx) =>
        {
            return Task.FromResult(0);
        },
        SecurityTokenValidated = (ctx) =>
        {
            var identity = ctx.AuthenticationTicket.Identity;
            return Task.FromResult(0);
        }
    }
});

In my AccountController's Login view, I have a link

<a href="@Url.Action("Login", "Account", new { returnUrl = ViewBag.ReturnUrl, authType = "Cognito" })">Corporate Login</a>

And in the Controller's action for the Login view, I have this snippet:

HttpContext.GetOwinContext().Authentication.Challenge(new AuthenticationProperties { RedirectUri = returnUrl }, authType);

With this all setup as-is, I'm able to click the link, initiate the authentication challenge, the RedirectToIdentityProvider Notification breakpoint hits (I resume), I'm redirected to the Cognito UserPool that then redirects to the configured SAML Identity Provider's login page, I authenticate (succeeds with valid credentials), redirects back to the application with the authentication code in in the URL, and that's it. None of the other Notification break points hit, and the user is still not authenticated.

0 Answers
Related