Coder Social home page Coder Social logo

custom-authorization's Introduction

Custom authorization or in-app authorization

This PoC contains a sample solution for handling custom authorization within a modern application.

The problem

Most of the modern applications are using OAuth or OpenID Connect to authenticate and authorize their users. However, in some cases it is necessary to grant the differnet permissions to a user based on the resource that he is accessing in the application.

problem

A token issued by identity provider can help us to authenticate a user. But it can't help to authorize access because identity provider can issue a token to a user only based on his role within the application but not based on the specific resource in the application that user is accessing.

In this case, in addition to the token, the custom authorization can help to authorize access. However, during the implementation the next requirements should be taken into account:

  • There should be the only one place where authorization rules are configured
  • The framework authorization mechanisms should be used to avoid inserting everywhere conditions like if (<check-user-role>) then ...
  • Solution should be generic and provide a simple way to inject a business logic to provide or restrict an access for a user

The solution

There are multiple solution to solve this problem. But taking into account the requirements above, we recommend to add a service (named here as AuthorizationService) to the request execution pipeline. This service is responsible for enriching the request with the roles of the current user, based on the business logic of your application, and then passing this information on to further processing of the request.

problem

You can find the recommended implementation for the .NET applications below.

The achitecture

solution

Let's look at the flow:

  1. Unauthenticated user is redirected to Identity Provider (for example - Azure AD) where he logs-in
  2. Identity Provider issues a token and return it to a user's browser
  3. The browser uses this token to access an application
  4. The standard Authentication middleware validates the presented token and initializes User.Identity object that contains all the inforamtion about a user (including user's groups as well)
  5. The custom middleware InjectRolesMiddleware, injected after the Authentication middleware and before the Authorization middleware, calls the service to get the users's role
  6. The service AuthorizationService implements the business logic to get roles for the current user. To get the roles for the user, it can use external storage (like SQL or NoSQL databases), internal storage (like files or memory) or external service (available via HTTP).
  7. The service returns the user's roles which will be injected, by the InjectRolesMiddleware, into the User.Identity object as the role claims
  8. The standard Authorization middleware will use (by default) these injected roles to authorize or deny access

The code

You can find multiple projects within src folder.

This project shows implementation of this solution for the ASP.NET WebAPI application that is built using Minimal API.

  • Create a new authorization policy in Program.cs file:

      options.AddPolicy("RequireAccessToSecret", policy => policy.RequireRole("AccessToSecret"));
  • The DummyAuthorizationService is registered in IServiceCollection in Program.cs file:

      builder.Services.AddScoped<IAuthorizationService, DummyAuthorizationService>();
  • The InjectRolesMiddleware injected into the pipeline in Program.cs file:

      app.UseInjectedRoles();
  • Require created above authorization policy for /weatherforecast method in Program.cs file:

      .RequireAuthorization(new[] { "RequireAccessToSecret" });

This project shows implementation of this solution for the ASP.NET WebAPI application that is built using MVC.

  • Create a new authorization policy in Program.cs file:

      options.AddPolicy("RequireAccessToSecret", policy => policy.RequireRole("AccessToSecret"));
  • The DummyAuthorizationService is registered in IServiceCollection in Program.cs file:

      builder.Services.AddScoped<IAuthorizationService, DummyAuthorizationService>();
  • The InjectRolesMiddleware injected into the pipeline in Program.cs file:

      app.UseInjectedRoles();
  • Require created above authorization policy for Get method in WeatherForecastController.cs file:

      [Authorize(Policy = "RequireAccessToSecret")]

This project is referenced by all the other projects and contains the implementation for the custom middleware InjectRolesMiddleware. It also declares the interface IAuthorizationService and contains an implementation for this interface called DummyAuthorizationService. This service is just a simple and naive examle of implementation of the IAuthorizationService interface. You should create your own custom implementation of this interface based on your business authorization rules and register this service as a scoped service in IServiceCollection in your Program.cs file:

  builder.Services.AddScoped<Shared.Services.IAuthorizationService, YourCustomAuthorizationService>();

This project shows implementation of this solution for the ASP.NET Web application that is built using MVC.

  • Create a new authorization policy in Program.cs file:

      options.AddPolicy("RequireAccessToSecret", policy => policy.RequireRole("AccessToSecret"));
  • The DummyAuthorizationService is registered in IServiceCollection in Program.cs file:

      builder.Services.AddScoped<Shared.Services.IAuthorizationService, DummyAuthorizationService>();
  • The InjectRolesMiddleware injected into the pipeline in Program.cs file:

      app.UseInjectedRoles();
  • Require created above authorization policy for Secret method in HomeController.cs file:

      [Authorize(Policy = "RequireAccessToSecret")]

This project shows implementation of this solution for the ASP.NET Web application that is built using Razor Pages.

  • Create a new authorization policy in Program.cs file:

      options.AddPolicy("RequireAccessToSecret", policy => policy.RequireRole("AccessToSecret"));
  • The DummyAuthorizationService is registered in IServiceCollection in Program.cs file:

      builder.Services.AddScoped<Shared.Services.IAuthorizationService, DummyAuthorizationService>();
  • The InjectRolesMiddleware injected into the pipeline in Program.cs file:

      app.UseInjectedRoles();
  • Require created above authorization policy for /Secret page in Program.cs file:

      options.Conventions.AuthorizePage("/Secret", "RequireAccessToSecret");

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.