DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
Building Scalable Real-Time Apps with AstraDB and Vaadin
Register Now

Trending

  • Application Architecture Design Principles
  • Top Six React Development Tools
  • What Is Envoy Proxy?
  • Building a Flask Web Application With Docker: A Step-by-Step Guide

Trending

  • Application Architecture Design Principles
  • Top Six React Development Tools
  • What Is Envoy Proxy?
  • Building a Flask Web Application With Docker: A Step-by-Step Guide
  1. DZone
  2. Data Engineering
  3. Databases
  4. Identity as a Service (IDaaS) :  ASP.NET Core API and AWS Cognito

Identity as a Service (IDaaS) :  ASP.NET Core API and AWS Cognito

In this post, we learn how to add authentication to a web application by using the ASP.NET Core API and the AWS Cognito service.

Lucas Lopez user avatar by
Lucas Lopez
·
Jun. 03, 18 · Tutorial
Like (3)
Save
Tweet
Share
11.95K Views

Join the DZone community and get the full member experience.

Join For Free

This is another article in a series on Identity as a Service. In this article, we are going to see how to configure an ASP.NET Core API to validate the identities of the users using AWS Cognito.

For this example, we need the app that we developed in the previous article — Identity as a service (IDaaS): AWS Cognito and ASP.NET Core. In addition, we will continue using Visual Studio 2017 Community Edition.

All code for this example is available on  GitHub.

Protecting API Access

The objective of these examples is to add the necessary validations in the API developed in ASP.NET Core to allow only invocations from apps that have a valid user connected.

This example uses web apps but it is very simple to do the same for single page apps using JavaScript or for a mobile app. The important thing is the propagation of the token from the client to the API, which will validate it before returning the result of the invocation.

This is one of the best aspects of the  OAuth2.0 and  OIDC model. Each layer of our apps do not have to trust whoever contacts them, there is only a relationship of trust with the identity provider. The key element of the model are the  JWTs  ( JSON Web Tokens).

This relationship of trust is achieved through the publication of configuration parameters that are public for any service that wants to use them. New services and layers can be added to our ecosystem without modifying existing services.

Something to keep in mind when we create or modify an API Controller in ASP.NET Core is that the [Authorize] attribute can be applied to a particular method or to the whole class. When applied to the entire class, then all methods will require you to meet the access criteria before responding.

Web API Using AWS Cognito

Let’s start by creating and configuring an ASP.NET Core API to use AWS Cognito as an identity provider. Again, most of the changes have to be made in startup.cs, although, in this example, we will also create a new controller to return one of the JWT token values.

Startup.cs Changes

The first changes necessary are the using

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;

Most of the changes are in the ConfigureServices method. Some comments before reviewing the code.

First, instead of harcoding the properties of the JWT validation in the code, we use appsettings.jsonor more flexibility.

Then you have to useAddAuthentication to indicate the Authentication and AddJwtBearer schema to indicate the validation parameters of the JWT, by far the most important section of the code. The MetaDataAddress value depends on our AWS Cognito account, the same value that we use in our Web App.

It is mandatory that our web app and API use the same MetaDataAddress to be able to propagate the identities. TheMetaDataAddress value is the same regardless of the web app registered in AWS Cognito.

Something distinctive about AWS Cognito is that the tokens do not have the Audience claim, so it is necessary to indicate to the ASP.NET validation routines that they must ignore it. If ValidateAudience = false is not included, each validation will give an error.

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<JwtBearerOptions>(Configuration.GetSection("Authentication:Cognito"));

    var serviceProvider = services.BuildServiceProvider();
    var authOptions = serviceProvider.GetService<IOptions<JwtBearerOptions>>();

    services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
        options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;

    }).AddJwtBearer(options =>
    {
        options.MetadataAddress = authOptions.Value.MetadataAddress;
        options.SaveToken = authOptions.Value.SaveToken;

        options.IncludeErrorDetails = authOptions.Value.IncludeErrorDetails;
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateAudience = authOptions.Value.TokenValidationParameters.ValidateAudience
        };
    });

    services.AddMvc();
}

And, finally, modify the Configure method to use the Authentication model that we configured in the previous step.

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseAuthentication();

    // The rest of the Configure Method

}

Note: Since I was refactoring the API example using Okta, I forgot to include this line... I spent 15 minutes reviewing the rest of the code before I found the error. In each test, the answer was Invalid Token without further explanation in the error message or in the debug log.

New API Controller

Each new API project in VS 2017 creates a default controller API ValuesController. Instead of modifying it, we are going to create a new controller. This will allow us to see that the ValuesController invocations will not require the JWT but it will be necessary for the new controller.

We will call the new API Controller, TokenController, and we will only implement the action GET that simply returns the date when the token expires. The [Authorize] attribute indicates that a valid user is required to invoke any method of this class.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

using Microsoft.AspNetCore.Authorization;

namespace APICognito.Controllers
{
    [Produces("application/json")]
    [Route("api/Token")]
    [Authorize]
    public class TokenController : Controller
    {
        // GET: api/Token
        [HttpGet]
        public string Get()
        {
            string exp = User.Claims.Where(c => c.Type == "exp").First().Value;

            return "Your token is valid until " + (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).AddSeconds(Double.Parse(exp)).ToString();
        }
    }
}

After the invocation, we can take the answer and show it on the screen.

Thanks for reading!

All views expressed are my own and do not represent opinions of any entity whatsoever with which I have been, am now, or will be affiliated.

API AWS Web Service

Opinions expressed by DZone contributors are their own.

Trending

  • Application Architecture Design Principles
  • Top Six React Development Tools
  • What Is Envoy Proxy?
  • Building a Flask Web Application With Docker: A Step-by-Step Guide

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com

Let's be friends: