Skip to main content

JWT Authentication (ASP.NET Core + Angular) - Backend


 Key code Snippet are followings

Back End:

Startup.cs

    public class Startup

    {

        public Startup(IConfiguration configuration)

        {

            Configuration = configuration;

        }


        public IConfiguration Configuration { get; }


        // This method gets called by the runtime. Use this method to add services to the container.

        public void ConfigureServices(IServiceCollection services)

        {

            services.AddDbContext<PharmaDbContext>(options =>

                        options.UseSqlServer(Configuration.GetConnectionString("DBConnection")));


            services.AddControllers();

            services.AddSwaggerGen(c =>

            {

                c.SwaggerDoc("v1", new OpenApiInfo { Title = "PharmaSuite", Version = "v1" });

            });


            services.ConfigureMappings();

            services.ConfigureBusinessServices(Configuration);

            services.ConfigureRepositories(Configuration);

            services.AddCors();

            services.AddHttpContextAccessor();


            // Configure Authentication


            var jwtSettings = Configuration.GetSection("JWTSettings")

                                                     .Get<JWTSettings>();


            services.AddAuthentication(auth =>

            {

                auth.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;

                auth.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

            })

            .AddJwtBearer(options =>

            {

                options.SaveToken = true;

                options.TokenValidationParameters = new TokenValidationParameters

                {

                    ValidateIssuer = true,

                    ValidIssuer = jwtSettings.Issuer,

                    ValidateAudience = true,

                    ValidAudience = jwtSettings.Audience,

                    ValidateIssuerSigningKey = true,

                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSettings.Secret))

                };

            });



        }


        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)

        {

            if (env.IsDevelopment())

            {

                app.UseDeveloperExceptionPage();

                app.UseSwagger();

                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "PharmaSuite v1"));

            }


           


            app.UseHttpsRedirection();


            app.UseRouting();


            // global cors policy

            app.UseCors(x => x

                .AllowAnyMethod()

                .AllowAnyHeader()

                .SetIsOriginAllowed(origin => true) // allow any origin

                .AllowCredentials()); // allow credentials


            HttpContextHelper.Configure(app.ApplicationServices.GetRequiredService<IHttpContextAccessor>());


            app.UseAuthentication();

            app.UseAuthorization();


            app.UseEndpoints(endpoints =>

            {

                endpoints.MapControllers();

            });



        }

    }

}


.csproj: Nuget  package for JWT
    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.6" />
    <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.7.1" />


namespace PharmaSuite.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AccountController : BaseController
    {
        private readonly IUserService _userService;
        private readonly IConfiguration _configuration;
        public AccountController(IUserService userService, IConfiguration configuration)
        {
            _userService = userService;
            _configuration = configuration;
        }

        [AllowAnonymous]
        [HttpPost]
        [Route("Authenticate")]
        public async Task<IActionResult> Authenticate(UserLogin userLogin)
        {
            var candidate = await _userService.AuthenticateUser(userLogin);

            if (candidate != null)
            {
                var loginUser = await _userService.GetUserAsync(candidate.Id);

                var claims = new List<Claim>();
                claims.Add(new Claim("UserName", loginUser.UserName));
                claims.Add(new Claim("Email", loginUser.Email));
                claims.Add(new Claim("UserType", loginUser.UserType));
                claims.Add(new Claim("CompanyId", loginUser.CompanyId.ToString()));
                claims.Add(new Claim("UserId", loginUser.Id.ToString()));

                // Add roles as multiple claims
                foreach (var role in loginUser.Roles)
                {
                    claims.Add(new Claim(ClaimTypes.Role, role.Name));
                }

                var jwtSettings = _configuration.GetSection("JWTSettings")
                                         .Get<JWTSettings>();

                var token = JwtHelper.GetJwtToken(
                                loginUser.UserName,
                                jwtSettings.Secret,
                                jwtSettings.Issuer,
                                jwtSettings.Audience,
                                TimeSpan.FromMinutes(jwtSettings.TokenTimeoutMinutes),
                                claims.ToArray());

                var response = new TokenResponse()
                {
                    AccessToken = new JwtSecurityTokenHandler().WriteToken(token),
                    ExpiresOnUtc = token.ValidTo,
                    RoutePermissions = loginUser.RoutePermissions
                };

                return Ok(response);
            }
            else
            {
                return Unauthorized("Invalid Login Credentials!");
            }
        }

    }
}


TokenResponse Model:
public class TokenResponse
    {
        public string AccessToken { get; set; }
        public DateTime ExpiresOnUtc { get; set; }
        public List<UserRoutePermission> RoutePermissions { get; set; }
    }

JwtHelper : 

namespace PharmaSuite.Common.Helpers
{
    public class JwtHelper
    {
        public static JwtSecurityToken GetJwtToken(
        string username,
        string signingKey,
        string issuer,
        string audience,
        TimeSpan expiration,
        Claim[] additionalClaims = null)
        {
            var claims = new[]
            {
            new Claim(JwtRegisteredClaimNames.Sub,username),
            // this guarantees the token is unique
            new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
        };

            if (additionalClaims is object)
            {
                var claimList = new List<Claim>(claims);
                claimList.AddRange(additionalClaims);
                claims = claimList.ToArray();
            }

            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(signingKey));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

            return new JwtSecurityToken(
                issuer: issuer,
                audience: audience,
                expires: DateTime.UtcNow.Add(expiration),
                claims: claims,
                signingCredentials: creds
            );
        }
    }
}

HttpContextHelper:

namespace PharmaSuite.Common.Helpers
{
    public static class HttpContextHelper
    {
        private static IHttpContextAccessor _httpContextAccessor;

        public static void Configure(IHttpContextAccessor httpContextAccessor)
        {
            _httpContextAccessor = httpContextAccessor;
        }

        public static HttpContext HttpContext => _httpContextAccessor.HttpContext;
    }
}


BaseController:
namespace PharmaSuite.Controllers
{
    [ApiController]
    public class BaseController : ControllerBase
    {
       public CurrentUser CurrentUser { get { return this.currentUser; } }
       private CurrentUser currentUser = null;

        public BaseController()
        {
            
                var identity = HttpContextHelper.HttpContext.User.Identity as ClaimsIdentity;

                if (identity != null && identity.Claims != null && identity.Claims.Any())
                {
                    currentUser = new CurrentUser();

                    currentUser.UserId = Convert.ToInt32(identity.FindFirst("UserId").Value);
                    currentUser.CompanyId = Convert.ToInt32(identity.FindFirst("CompanyId").Value);
                    currentUser.UserType = identity.FindFirst("UserType").Value;
                    currentUser.UserName = identity.FindFirst("UserName").Value;
                    currentUser.Email = identity.FindFirst("Email").Value;
                }

        }
    }
}

Comments

Popular posts from this blog

SQL Server(from 2012) FileTable Features some useful SQL Statements

The FileTable feature brings support for the Windows file namespace and compatibility with Windows applications to the file data stored in SQL Server. FileTable lets an application integrate its storage and data management components, and provides integrated SQL Server services - including full-text search and semantic search - over unstructured data and metadata.( FileTable ) Here is sequential SQL statements to enable,alter existing database for FileStream and create FileTable --check current config value EXEC sp_configure filestream_access_level; --reconfig GO EXEC sp_configure 'filestream access level',   2 Go RECONFIGURE GO -- chack file table enabled databases  SELECT DB_NAME(database_id) as [Database Name], non_transacted_access, non_transacted_access_desc ,directory_name FROM sys.database_filestream_options --  Enable a file table in an existing Database ALTER DATABASE TestDB  SET FILESTREAM ( NON_TRANSACTED_ACCESS = FULL, DIRECT...

First J2ME Application & Deployment(.jar,.jad) for your Supported Mobile Phones

Most probably 2 years ago I had decided to swap from C#.NET to Java.But at the time of its beginning I found it so messy than that of C#.As I desired to develop applications for my famous China Phone(Network down most of the time but supports java) at last I did it at the end of 2010.Now I'll discuss how to prepare your desktop to develop your first  j2me applications .   What is actually J2ME? J2ME stands for Java 2 Micro Edition, also known as Java ME. J2ME is a stripped down version of Java targeting devices with lower processing capabilities, like mobile phones, pagers .J2ME runs on a highly optimized version of Java Run-time Environment called KVM which comes pre-installed on devices(mobile phone,hand-held devices) supporting J2ME apps. Basic Concepts on J2ME: We can divide J2ME framework into three main parts namely Configurations, profiles and optional packages Configurations : A configuration contains the KVM and important class libraries, It defin...

Referenced assembly does not have a strong name

  Steps to create strong named assembly Step 1 : Run visual studio command prompt and go to directory where your DLL located.   For Example my DLL located in  D:/hiren/Test.dll Step 2 : Now create  il file using below command.    D:/hiren> ildasm /all /out=Test.il Test.dll   (this command generate code library) Step 3 : Generate new Key for sign your project.    D:/hiren> sn -k mykey.snk Step 4 : Now sign your library using ilasm command.    D:/hiren> ilasm /dll /key=mykey.snk Test.il so after this step your assembly contains strong name and signed. Jjust add reference this new assembly in your project and compile project its running now. codeproject.com/Tips/341645/Referenced-assembly-does-not-have-a-strong-name