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
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

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
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

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • How to Enhance the Performance of .NET Core Applications for Large Responses
  • Configuring SSO Using WSO2 Identity Server
  • 10 Ways To Keep Your Java Application Safe and Secure
  • Dependent Feature Flags

Trending

  • Endpoint Security Controls: Designing a Secure Endpoint Architecture, Part 1
  • Next Evolution in Integration: Architecting With Intent Using Model Context Protocol
  • Building Resilient Networks: Limiting the Risk and Scope of Cyber Attacks
  • Unlocking Data with Language: Real-World Applications of Text-to-SQL Interfaces
  1. DZone
  2. Coding
  3. Frameworks
  4. Secure Your ASP.NET Application With Authorization From Okta

Secure Your ASP.NET Application With Authorization From Okta

Secure authentication is only half of the battle. In this post, you’ll learn how to implement authorization in your ASP.NET Core MVC app simply.

By 
Lee Brandt user avatar
Lee Brandt
·
May. 06, 18 · Tutorial
Likes (1)
Comment
Save
Tweet
Share
7.3K Views

Join the DZone community and get the full member experience.

Join For Free

Let's be honest. Secure authentication is only half of the battle. Authorization is just as important to secure identity management but is often forgotten. In reality, almost every app needs more than just “is this user signed in?” Most times, you need to not know who the user is, AND what access they are supposed to have. In this tutorial, you’ll learn how to implement authorization in your ASP.NET Core MVC app simply, with Okta.

In the Okta world, users are separated into Groups. By default, however, ASP.NET only has handling for the Authorizeattribute to handle authorization using Roles. There are a couple of ways you could go about handling authorization using the Groups that come from Okta:

  • You can write your own custom AuthorizeAttribute and have it look at groups instead of roles.
  • You can map the Groups to Roles claims and let the regular ASP.NET AuthorizeAttribute handle authorization.

This second approach is far easier to implement, so that’s the approach this article will take.

Start by cloning the application from GitHub. This is the base application with authentication covered in my previous post. You’ll add authorization to this application.

Let ASP.NET Know Where Your Roles Are

In the startup.cs file, where the OpenIdConfigurationOptions are set, one of the items being set is the TokenValidationParameters. In the new TokenValidationParameters, add a property called RoleClaimTypewith a value of ClaimTypes.Role. This is an enumeration in the System.Security.Claims namespace that holds the URL that describes the “role” claim type. Ultimately, your TokenValidationParameters property should look like this.

TokenValidationParameters = new TokenValidationParameters
{
  ValidateIssuer = true,
  RoleClaimType = ClaimTypes.Role
}

Add a Claims Transformer

The Claims Transformer is a way to manipulate the ClaimsPrincipal, which is the main user in your ASP.NET application, once the user is authenticated.

Add a folder inside the Domain folder called Authorization. Then add a class called GroupsToRolesTransformer. The contents of the transformer should be:

using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Okta.Sdk;
using Okta.Sdk.Configuration;

namespace AspnetOkta.Domain.Authorization
{
  public class GroupsToRolesTransformer : IClaimsTransformer
  {
    private OktaClient client;

    public GroupsToRolesTransformer()
    {
        client = new OktaClient(new OktaClientConfiguration{
            OrgUrl = "https://{Your Okta Org Url}",
            Token = "JiBBerJabbER"
        });
    }

    public async Task<ClaimsPrincipal> TransformAsync(ClaimsTransformationContext context)
    {
      var idClaim = context.Principal.FindFirst(x=>x.Type == ClaimTypes.NameIdentifier);
      if(idClaim != null)
      {
          var user = await client.Users.GetUserAsync(idClaim.Value);
          if(user != null){
            var groups = user.Groups.ToEnumerable();
            foreach (var group in groups)
            {
                ((ClaimsIdentity)context.Principal.Identity).AddClaim(new Claim(ClaimTypes.Role, group.Profile.Name));
            }
          }
      }
      return context.Principal;
    }
  }
}

As you can see here, in the constructor, you are creating an OktaClient object to be stored in a class-level variable called client. You’ll need your OrgUrl from Okta (probably something like dev-1234.oktapreview.com) and an API token which you can get from the Okta Developer Dashboard under API > Tokens.

API Token Page

Be aware that you only get to see the API token when you create it, so make sure you save it somewhere so you can reference it later.

Once you’ve created a transformer, it will implement the IClaimsTransformer interface. There is only one method you’ll need to worry about, and that’s the TransformAsync method. It takes a ClaimsTransformationContext and returns a Task with a ClaimsPrincipal in it.

Note that if you use the key shortcuts to get Visual Studio (or Visual Studio Code) to implement the interface for you, it will not add the public or async keywords to the signature. You’ll have to add them manually.

In this method, you’ll get the currently authenticated user’s NameIdentifier property. This is the ID you’ll use to get the Okta user so that you can get their groups. Just a quick null check for the idClaim variable and then go and get the Groups from the user object. From there, simply loop through the Groups and add a Claim using the ClaimTypes.Roleenumeration and using the group.Profile.Name for the value of the claim.

Return the context.Principal no matter what. If you didn’t find the user’s identifier, or get a user back from the GetUserAsynccall, at least the application will still get the ClaimsPrincipal back into the flow of the application.

Tell the Application to Use Your Transformer

The only thing left is to configure your application to use the new transformer in your middleware pipeline.

Right below the OIDC setup in the Configure method of your startup.cs file, add the following code:

app.UseClaimsTransformation(new ClaimsTransformationOptions{
  Transformer = new GroupsToRolesTransformer()
});

This tells the application that you want to transform the claims and which claims transformer you want to use.

Prove That it Works

You’ll need to set up two users in two different groups in your Okta Developer Dashboard. Call one group “Admin” and the other “Enthusiast.”

Add Groups Page

Make sure the groups are assigned to your application:

Assing Groups To Application

Then create some routes in the UserController decorated with the AuthorizeAttribute.

  [Authorize(Roles = "Admin")]
  public IActionResult AdminOnly()
  {
    return View();
  }

  [Authorize(Roles = "Enthusiast")]
  public IActionResult EnthusiastOnly()
  {
    return View();
  }

Then create matching views for those routes.

AdminOnly.cshtml

<h1>Admin Dashboard</h1>

EnthusiastOnly.cshtml

<h1>Enthusiast Dashboard</h1>

Now you should be able to run your application, log in as a user in the “Admin” group, and go to the http://localhost:5000/User/AdminOnly route successfully. The EnthusiastOnly route should return an unauthorized error.

Log back out and log in as a member of the “Enthusiast” group and go to the http://localhost:5000/User/EnthusiastOnly URL, and you should be able to get to it.

Congratulations! You just added authorization to you .NET application! Not only can users get into your application, but you can make sure they have access to the data and functionality they need!

Learn More

You can learn more about the .NET Claims Transformer in the Microsoft Docs and the broader spectrum of security in .NET here.

And don’t forget, Okta can help you make user management simple! Sign up for a free forever developer account! As always, if you have questions about anything here, feel free to reach out on Twitter.

User Authorization in ASP.NET Core with Okta was originally published on the Okta developer blog on October 4, 2017.

ASP.NET application authentication

Published at DZone with permission of Lee Brandt, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • How to Enhance the Performance of .NET Core Applications for Large Responses
  • Configuring SSO Using WSO2 Identity Server
  • 10 Ways To Keep Your Java Application Safe and Secure
  • Dependent Feature Flags

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

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

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!