Git Product home page Git Product logo

an.authentication.basic's Introduction

AN.Authentication.Basic

This project contains an implementation of Basic Authentication Scheme for ASP.NET Core. See the RFC-7617.

Add Basic Authentication

To add Basic authentication in .NET Core, we need to modify Program.cs file. If you are using .NET Core version 5 or less, you have to add the modifications in the Startup.cs file inside the ConfigureServices method.

Add the code to configure Basic authentication right above the builder.Services.AddAuthentication() line:

builder.Services.AddAuthentication()
                .AddBasic(BasicDefaults.AuthenticationScheme);

Basic Authentication Configuration

To configure Basic authentication, we need use delegate from overloaded method AddBasic(string authenticationScheme, Action<BasicOptions> configure):

builder.Services.AddAuthentication()
                .AddBasic(BasicDefaults.AuthenticationScheme, configure => {
                    //some options will be here
                });

User credentials separator

User credentials (user-id and password) constructs by concatenating the user-id, a single colon (':') character, and the password. If your credentials is separated by another symbol, then it can be configured with the option CredentialsSeparator:

builder.Services.AddAuthentication()
                .AddBasic(BasicDefaults.AuthenticationScheme, configure => {
                    //Default option value is single colon (':')
                    configure.CredentialsSeparator = '~'
                });

Credentials encoding scheme

By default user credentials encoded by Base64 into a sequence of US-ASCII characters. If your credentials is by another algorithm or scheme, then it can be configured with the option EncodedHeaderDecoder:

builder.Services.AddAuthentication()
                .AddBasic(BasicDefaults.AuthenticationScheme, configure => {
                    configure.EncodedHeaderDecoder = credentials => DecodeCretentialsToString(credentials);
                });

Or you can use EncodedHeaderAsyncDecoder for asynchronous decode:

builder.Services.AddAuthentication()
                .AddBasic(BasicDefaults.AuthenticationScheme, configure => {
                    configure.EncodedHeaderAsyncDecoder = async (credentials, cancellationToken) => await DecodeCretentialsToStringAsync(credentials, cancellationToken);
                });

If both the EncodedHeaderAsyncDecoder and EncodedHeaderDecoder options are implemented, BasicHandler will use only EncodedHeaderAsyncDecoder to work:

builder.Services.AddAuthentication()
                .AddBasic(BasicDefaults.AuthenticationScheme, configure => {
                    //This one will be used
                    configure.EncodedHeaderAsyncDecoder = async (credentials, cancellationToken) => await DecodeCretentialsToStringAsync(credentials, cancellationToken);

                    //This one will be ignored
                    configure.EncodedHeaderDecoder = credentials => DecodeCretentialsToString(credentials);
                });

ClaimsPrincipal object creation

After decoding user credentials, it will be split into two separed strings (user-id and password). Then user-id and password will be used to create Claim[] by ClaimsFactory option for final ClaimsIdentity. By default this ClaimsFactory creates Claim[] with only one Claim with type NameIdentifier. If you need add another claims or get claims from storage, you can overload ClaimsFactory option:

builder.Services.AddAuthentication()
                .AddBasic(BasicDefaults.AuthenticationScheme, configure => {
                    configure.ClaimsFactory = (userId, password) => GetUserClaimsFromStorage(userId, password);
                });

Or you can use AsyncClaimsFactory for asynchronous Claim[] create:

builder.Services.AddAuthentication()
                .AddBasic(BasicDefaults.AuthenticationScheme, configure => {
                    configure.AsyncClaimsFactory = async (userId, password, cancellationToken) => await GetUserClaimsFromStorageAsync(userId, password, cancellationToken);
                });

Same as when you use header decoding option, if both the AsyncClaimsFactory and ClaimsFactory options are implemented, BasicHandler will use only AsyncClaimsFactory to work:

builder.Services.AddAuthentication()
                .AddBasic(BasicDefaults.AuthenticationScheme, configure => {
                    //This one will be used
                    configure.AsyncClaimsFactory = async (userId, password, cancellationToken) => await GetUserClaimsFromStorageAsync(userId, password, cancellationToken);

                    //This one will be ignored
                    configure.ClaimsFactory = (userId, password) => GetUserClaimsFromAnotherStorage(userId, password);
                });

Dependency Injection for ClaimsPrincipal object creation

If you want to get Claim[] from a service that works with dependency injection, you need to add service that implement IClaimsService or IAsyncClaimsService to the IServiceCollection.

builder.Services.AddTransient<IClaimsService, MyClaimsService>();

Both interfaces implement methods that returns an Claim[].

//sync service
public class ClaimsService : IClaimsService
{
    private readonly UserStorage storage;

    public ClaimsService(UserStorage storage)
    {
        this.storage = storage;
    }

    public Claim[] GetClaims(string userId, string password)
        => storage.GetUserClaimsFromStorage(userId, password);
}

//async service
public class AsyncClaimsService : IAsyncClaimsService
{
    private readonly UserStorage storage;

    public AsyncClaimsService(UserStorage storage)
    {
        this.storage = storage;
    }

    public async Task<Claim[]> GetClaimsAsync(string userId, string password, CancellationToken cancellationToken = default)
        => await storage.GetUserClaimsFromStorageAsync(userId, password, cancellationToken);
}

In case both types of services are added, only IAsyncClaimsService will be used.

If both one of ClaimService and one of options ClaimsFactory are implemented in same time, only the service will be used to create the Claim[].

Basic Authentication Events

The following events may occur during Basic authentication, which we can handle:

  • OnMessageReceived - Invoked when a protocol message is first received.
  • OnFailed - Invoked if authentication fails during request processing. The exceptions will be re-thrown after this event unless suppressed.
  • OnChallenge - Invoked before a challenge is sent back to the caller.
  • OnForbidden - Invoked if authorization fails and results in a Forbidden response.
  • OnPrincipalCreated - Invoked after request principal instance created.

All this events is part of BasicEvents object.

Events handling is the same as in other authentication schemes:

builder.Services.AddAuthentication()
                .AddBasic(BasicDefaults.AuthenticationScheme, configure => {
                    configure.Events = new BasicEvents()
                    {
                        OnMessageReceived = context => {
                            //handle this event
                            return Task.CompletedTask;
                        }
                    }
                });

an.authentication.basic's People

Contributors

nester-a avatar

Stargazers

 avatar

Watchers

 avatar

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.