Authentication and Authorization in .Net Core 5 and Angular 10 using JWT problem

Viewed 292

Hello I'm trying make authorization using JWT token so when not authorized user request api or request service it decline,

I've used JWT token with claim Role and made Job column in my database as role so that It will get the role from it

the problem is I can't decode the token or tbh I tried my best with the help of identity to decode it but I sure can't

that's my 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.AddAuthentication();

        services.AddCors(options =>
        {
            options.AddPolicy("EnableCORS", Builder =>
             {
                 Builder.AllowAnyOrigin()
                 .AllowAnyHeader()
                 .AllowAnyMethod();
             });
        });
        services.AddDbContext<media_cloudContext>(option => option.UseSqlServer(Configuration.GetConnectionString("MediaCloudCS")));
        services.AddScoped<ILoginService, LoginService>();
        services.AddControllers();
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "MediaCloudApi", Version = "v1" });
        });
    }

    // 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", "MediaCloudApi v1"));
        }

        app.UseHttpsRedirection();

        app.UseCors("EnableCORS");

        app.UseRouting();

        app.UseAuthentication();

        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
}

I added JWT package and tried to add default scheme but it can't define it and the only thing avilable JWTBearerExtension

that's my token creation service

public class TokenHelper
{
    public const string Issuer = "http://MediaCloud.com";
    public const string Audience = "http://MediaCloud.com";

    public const string Secret = "OFRC1j9aaR2BvADxNWlG2pmuD392UfQBZZLM1fuzDEzDlEpSsn+btrpJKd3FfY855OMA9oK4Mc8y48eYUrVUSw==";

    public static string GenerateSecureSecret()
    {
        var hmac = new HMACSHA256();
        return Convert.ToBase64String(hmac.Key);
    }

    public static string GenerateToken(UserInfo user)
    {
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = Convert.FromBase64String(Secret);

        var claimsIdentity = new ClaimsIdentity(new[] {
            new Claim(ClaimTypes.Name, user.Id.ToString()),
            new Claim(ClaimTypes.Role, user.Job),


        });
        var signingCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature);

        var tokenDescriptor = new SecurityTokenDescriptor
        {
            
            Subject = claimsIdentity,
            Issuer = Issuer,
            Audience = Audience,
            Expires = DateTime.Now.AddMinutes(15),
            SigningCredentials = signingCredentials,

        };
        var token = tokenHandler.CreateToken(tokenDescriptor);
        return tokenHandler.WriteToken(token);
    }
}

and that's the get request from the controller

[HttpGet,Authorize]
public async Task<ActionResult<IEnumerable<UserInfo>>> GetUserInfos()
{
    return await _context.UserInfos.ToListAsync();
}

and the error code from postman STATUS 500 INTERNAL SERVER ERROR

System.InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action<AuthenticationOptions> configureOptions).
   at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)
   at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

HEADERS
=======
Accept: */*
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Content-Length: 69
Content-Type: application/json
Host: localhost:44371
User-Agent: PostmanRuntime/7.28.4
token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1bmlxdWVfbmFtZSI6IjciLCJyb2xlIjoiYWRtaW4iLCJuYmYiOjE2MzU5NzMyMDYsImV4cCI6MTYzNTk3NDEwNiwiaWF0IjoxNjM1OTczMjA2LCJpc3MiOiJodHRwOi8vTWVkaWFDbG91ZC5jb20iLCJhdWQiOiJodHRwOi8vTWVkaWFDbG91ZC5jb20ifQ.QjOC2ixirm9zmMmFDRO28JPd1Q97mq_M8bxlmmgT8EU
Postman-Token: 3911736a-ea2b-4273-ba35-d0315a560e71

I think the problem is the default schema but I can't add it and I'm new to .net core

1 Answers

you have to add to ConfigureServices(IServiceCollection services) of your startup file the code similar this one

var key = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Configuration["Tokens:Key"]));

            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(x =>
            {
                x.RequireHttpsMetadata = false;
                x.SaveToken = true;
                x.TokenValidationParameters = new TokenValidationParameters
                {
                    IssuerSigningKey = key,
                    ValidateIssuerSigningKey = true,
                    ValidateLifetime = true,
                    ValidateIssuer = false,
                    ValidAudience =Configuration["Tokens:Audience"] ,
                    ValidateAudience = true
                };
            });

and it is better to use appsettings to keep token parameters then to hard code them. Add somethig like this to to appsettings.json

"Tokens": {
    "Key": "xxxxxx"
    "Audience": "xxxxx",
    "Issuer": "xxxx"
  }
Related