Skip to content

2.9 Authentication and authorization

Marjan Nikolovski edited this page Apr 9, 2021 · 1 revision

Purpose

Authentication is a process to ensure and confirms a user’s identity and whether the user is registered or not to access particular data or web pages. In other words, we can say that it is a process to validate someone against some data source.

Authorization is a security mechanism which is used to determine whether the user has access to a particular resource or not. The main point that you need to remember is, authentication happens first, then only authorization.

How to use

When we implement any type of process a Authentication and Authiorization managers are automatically injected in the process context.

public class MyProcess : BusinessProcess<Entities.User, VoidResult>
{
    /// <summary>
    /// Authenticate process
    /// </summary>
    /// <returns></returns>
    public override VoidResult Auth(Entities.User user)
    {
        return Ok();
    }

    /// <summary>
    /// Validate process
    /// </summary>
    /// <returns></returns>
    public override VoidResult Validate(Entities.User user)
    {
        return Ok();
    }

    /// <summary>
    /// Handle process
    /// </summary>
    /// <returns></returns>
    public override VoidResult Handle(Entities.User user)
    {
        // create user identity
        var identity = new ClaimsIdentity(authenticationType: "Cookies");
        var principal = new ClaimsPrincipal(identity);

        // login the user
        Context.Authentication.Login(principal, user);

        // get current user if it is logged in
        var currentUser = Context.Authentication.GetCurrentUser<Entities.User>();

        // how to add and check and remove roles for the currenly logger in user
        Context.Authorization.AddRoles("SystemAdmin", "Operator", "Manager");
        var isAdmin = Context.Authorization.HasRole("SystemAdmin");
        Context.Authorization.Remove("SystemAdmin", "Operator", "Manager");

        // example how to logout the user
        Context.Authentication.Logout();

        return Ok();
    }
}

Other more manual way of using the authentication manager is through the IAuthenticationManager instance.

public void AuthUser(Entities.User user)
{
    var authenticationManager = SystemBootstrapper.GetInstance<IAuthenticationManager>();
    var authorizationManager = SystemBootstrapper.GetInstance<IAuthorizationManager>();

    // create user identity
    var identity = new ClaimsIdentity(authenticationType: "Cookies");
    var principal = new ClaimsPrincipal(identity);

    // login the user
    authenticationManager.Login(principal, user);

    // get current user if it is logged in
    var currentUser = authenticationManager.GetCurrentUser<Entities.User>();

    // how to add and check and remove roles for the currenly logger in user
    authorizationManager.AddRoles("SystemAdmin", "Operator", "Manager");
    var isAdmin = authorizationManager.HasRole("SystemAdmin");
    authorizationManager.Remove("SystemAdmin", "Operator", "Manager");

    // example how to logout the user
    authenticationManager.Logout();
}

Configuration

We configure the authentication and authorization depending if the project is .NET Core by either using extension methods from Signals.Aspects.Auth.NetCore.Extensions.RegistrationExtension

Properties explanation

Examples

/// <summary>
/// This method gets called by the runtime. Use this method to add services to the container.
/// </summary>
/// <param name="services"></param>
/// <returns></returns>
public IServiceProvider ConfigureServices(IServiceCollection services)
{
    // other configuration...

    services.AddAuthentication("Cookies")
        .AddSignalsAuth(opts =>
        {
            opts.SlidingExpiration = true;
            opts.ExpireTimeSpan = TimeSpan.FromDays(365);
            opts.Cookie.Expiration = TimeSpan.FromDays(365);
            opts.Cookie.MaxAge = TimeSpan.FromDays(365);
            opts.Cookie.IsEssential = true;
        });

    // other configuration...
}
/// <summary>
/// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
/// </summary>
/// <param name="app"></param>
/// <param name="env"></param>
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    // other configuration...

    app.UseSignalsAuth();

    // other configuration...
}

Extending authentication and authorization

  1. Install package Signals.Aspects.Auth
  2. Create class with implementation of Signals.Aspects.Auth.IAuthenticationManager
/// <summary>
/// Authentication manager
/// </summary>
public class MyAuthenticationManager : IAuthenticationManager
{
    /// <summary>
    /// Custom property
    /// </summary>
    public string MyProperty { get; set; }

    /// <summary>
    /// Get currently logged in user principal
    /// </summary>
    /// <returns></returns>
    ClaimsPrincipal GetCurrentPrincipal();

    /// <summary>
    /// Get currently logged in user
    /// </summary>
    /// <returns></returns>
    T GetCurrentUser<T>() where T : class;

    /// <summary>
    /// Set currently logged in user
    /// </summary>
    /// <returns></returns>
    void SetCurrentUser<T>(T user) where T : class;

    /// <summary>
    /// Login user with addiitonal data
    /// </summary>
    /// <param name="principal"></param>
    /// <param name="properties"></param>
    void Login(ClaimsPrincipal principal, AuthenticationProperties properties = null);

    /// <summary>
    /// Login user with addiitonal data
    /// </summary>
    /// <param name="principal"></param>
    /// <param name="user"></param>
    /// <param name="properties"></param>
    void Login<T>(ClaimsPrincipal principal, T user, AuthenticationProperties properties = null) where T : class;

    /// <summary>
    /// Logout currently logged in user
    /// </summary>
    void Logout();
}
  1. Create class with implementation of Signals.Aspects.Auth.IAuthorizationManager
/// <summary>
/// Authentication manager
/// </summary>
public class MyAuthenticationManager : IAuthorizationManager
{
    /// <summary>
    /// Add roles to currently logged in user
    /// </summary>
    /// <param name="roles"></param>
    void AddRoles(params string[] roles);

    /// <summary>
    /// Add roles to principal
    /// </summary>
    /// <param name="principal"></param>
    /// <param name="roles"></param>
    void AddRoles(ClaimsPrincipal principal, params string[] roles);

    /// <summary>
    /// Add roles to identity
    /// </summary>
    /// <param name="identity"></param>
    /// <param name="roles"></param>
    void AddRoles(ClaimsIdentity identity, params string[] roles);

    /// <summary>
    /// Check role for currently logged in user
    /// </summary>
    /// <param name="role"></param>
    /// <returns></returns>
    bool HasRole(string role);

    /// <summary>
    /// Remove roles to currently logged in user
    /// </summary>
    /// <param name="roles"></param>
    void RemoveRoles(params string[] roles);
}
  1. Use our implementation of IAuthorizationManager and IAuthorizationManager when configuring our application
services.AddTransient<IAuthenticationManager, MyAuthenticationManager>();
services.AddTransient<IAuthorizationManager, MyAuthorizationManager>();