This walkthrough configures an ASP.NET MVC .NET Core Web App using Amazon Cognito
In this walk-through, you’ll build the following – An Amazon Cognito User Pool to authenticate, store and manage users and configure a ASP.NET MVC .NET Core Web App that can be hosted in AWS as well as how to do role based authentication in Amazon Cognito using Cognito Groups
An AWS account with Administrative rights
Select the us-east-1 (N.Virginia) Region
Visual Studio 2019 Community Edition or better with the AWS toolkit installed
.NET Core 3.1 runtime
In this task, you’ll create and configure User Pool from AWS Management Console
Follow the steps one by one in this section, and/or alternately, you can leverage the below cloud formation template to automate the Cognito Configuration
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Creates and configures cognito resources for the demo application.",
"Parameters": {
"AuthName": {
"Type": "String",
"Description": "Unique Auth Name for Cognito Resources"
},
"CallbackUrl": {
"Type": "String",
"Description": "Enter your callback URLS that you will include in your sign in and sign out requests."
},
"SignoutUrl": {
"Type": "String",
"Description": "Enter your sign out URLS that you will include in your sign in and sign out requests"
}
},
"Resources": {
"DemoUserPool": {
"Type": "AWS::Cognito::UserPool",
"Properties": {
"UserPoolName": "NetCoreDemoAppUsersv1"
}
},
"DemoUserPoolClient": {
"Type": "AWS::Cognito::UserPoolClient",
"Properties": {
"ClientName": "NetCoreDemoAppClientv1",
"ExplicitAuthFlows": [
"ALLOW_USER_PASSWORD_AUTH",
"ALLOW_REFRESH_TOKEN_AUTH"
],
"GenerateSecret": false,
"RefreshTokenValidity": "30",
"UserPoolId": {"Ref": "DemoUserPool"},
"SupportedIdentityProviders": [
"COGNITO"
],
"AllowedOAuthFlows": [
"code"
],
"AllowedOAuthScopes": [
"email",
"openid",
"profile"
],
"CallbackURLs": [
{
"Ref": "CallbackUrl"
}
],
"LogoutURLs": [
{
"Ref": "SignoutUrl"
}
]
}
},
"DemoUserPoolDomain": {
"Type": "AWS::Cognito::UserPoolDomain",
"Properties": {
"Domain": { "Fn::Sub": "${AuthName}-demoappclient" },
"UserPoolId": {
"Ref": "DemoUserPool"
}
}
}
},
"Outputs": {
"UserPoolId": {
"Description": "Id of api user pool",
"Value": {
"Ref": "DemoUserPool"
},
"Export": {
"Name": "local-UserPoolId"
}
},
"UserPoolClientId": {
"Description": "Id of api user pool client",
"Value": {
"Ref": "DemoUserPoolClient"
},
"Export": {
"Name": "local-UserPoolClientId"
}
},
"UserPoolDomain": {
"Description": "UserPoolDomain name",
"Value": {
"Ref": "DemoUserPoolDomain"
},
"Export": {
"Name": "local-UserPoolDomain"
}
},
"DemoRegion" : { "Description": "AWS Region name", "Value" : { "Ref" : "AWS::Region" } }
}
}
Step 6: Enter the following and click Create app client – App Client Name: NetCoreDemoAppClient and Uncheck the Generate client secret checkbox
Check the box – Select all, Cognito User Pool
Enter the callback url from your .NET App ex: https://localhost:44314/externalauthentication/callback
Under OAuth 2.0, check the following options
Under Allowed OAuth Scopes, check the following options
We will use this interface provided by Cognito to sign up and log in users. If you plan to build your own UI, this is possible, and this step can be skipped but this is outside the scope of this exercise
Note: For the purpose of this lab, we are using the US-EAST-1 (N.Virginia) region, please make a note of which region you are working in we creating Url’s and configuring applications.
Make a note of the following:
App Client ID
Pool Id
Callback Url
Sign Out Url
Cognito Domain (fully qualified cognito domain url)
In this task you’ll be creating a .NET Core ASP.NET MVC Web Application. This is a sample project which will demonstrate the seamless integration of Amazon Cognito
Pre-requisites:
Visual Studio 2019 Community Edition or higher
.NET Core 3.1
AWS Toolkit for Visual Studio
C# Coding Skills
Note: You can do all of this on Mac OSX or Linux also. Once you have the .NET Core Framework installed, you can install the AWS templates with the dotnet new command.
Info: This bucket or repository contains the .NET Core ASP.NET MVC Web Application Solution using OpenID. This is a simple web application to demonstrate Amazon Cognito integration with the ASP.NET MVC Core Web App using Microsot.AspNetCore.Authentication.OpenIdConnect
{
"Logging":{
"LogLevel":{
"Default":"Warning"
}
},
"AllowedHosts":"\\*",
"Authentication":{
"Cognito": {
"ClientId": "\\<app client id from AWS Cognito\\>",
"IncludeErrorDetails": true,
"MetadataAddress": "https://cognito-idp.\\<your region\\>.amazonaws.com/\\<your-pool id\\>/.well-known/openid-configuration",
"RequireHttpsMetadata": false,
"ResponseType": "code",
"SaveToken": true,
"TokenValidationParameters": {
"ValidateIssuer": true
},
"AppSignOutUrl": "\\<sign out relative url goes here \\>",
"CognitoDomain": "\\<cognito domain goes here>\\"
}
}
}
There are few placeholders in the example above.
App client id from Amazon Cognito: This is your app client id which can be found by clicking App Clients under General Settings
Region: This is the aws region in which you configured amazon cognito resources
Pool Id: This is the pool id , can be found in the Cognito dashboard by clicking General Settings under the title Pool Id
Make sure you review these values for correctness.
The sample application shows how to use the OpenID Connect ASP.NET Core middleware to sign-in users using Amazon Cognito User Pool. The middleware is initialized in the Startup.cs file by passing the Client Id and the Cognito Metadata Url which is configured with the Pool Id from the above. The middleware takes care of downloading the Cognito metadata, and processing the OpenID requests and responses for sign up and sign in. You can trigger the middleware to send an OpenID Connect Sign-in request by decorating the class or an action method with the [Authorize] attribute.
Refer to the configuration details below.
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
options.ResponseType = Configuration["Authentication:Cognito:ResponseType"];
options.MetadataAddress = Configuration["Authentication:Cognito:MetadataAddress"];
options.ClientId = Configuration["Authentication:Cognito:ClientId"];
options.Events = new OpenIdConnectEvents()
{
OnRedirectToIdentityProviderForSignOut = OnRedirectToIdentityProviderForSignOut
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("AdminOnly", policy =>
policy.RequireAssertion(context =>
context.User.HasClaim(c => c.Type == "cognito:groups" && c.Value == "Admin")));
});
}
private Task OnRedirectToIdentityProviderForSignOut(RedirectContext 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;
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
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();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "products",
pattern: "products/{action}/{id?}",
defaults: new { controller = "Products", action = "Index" });
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
Once you've logged in, you can view some of the attributes of the logged in user as below
And also test for logout feature (which will redirect you to the home page after you click logout link in the top nav)
And you can view and manage all the users from the aws console
If you try to access the /admin page with the login that you've created with Step 23, you'll not be able to login as this user is part of the Admin Cognito group. But if you login using the user you've created using Step 26, and added this user to the Cognito Admin group in Step 10, you can now access the admin page as shown below.
In quick steps, we have demonstrated how you could integrate with Amazon Cognito seamlessly for authentication and policy based authorization. In addition to this, you can also integrate with federated identity providers, social logins to make it easier for the users to login and register.
See CONTRIBUTING for more information.
This library is licensed under the MIT-0 License. See the LICENSE file.