When Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme) is not used the...

Discussão em 'Angular' iniciado por Quikler, Dezembro 11, 2024.

  1. Quikler

    Quikler Guest

    I have asp net core mvc api and Angular client. When I access the api via https://localhost:7183/api/url/all with [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] attribute I'm getting the actual user from _userManager.GetUserId(User). However when I remove the [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] attribute the _userManager.GetUserId(User) returns null.

    [ApiController]
    [Route("api/url")]
    public class UrlController : ControllerBase
    {
    private readonly IUrlService _urlService;
    private readonly UserManager<UserEntity> _userManager;

    public UrlController(IUrlService shortUrlService, UserManager<UserEntity> userManager)
    {
    _urlService = shortUrlService;
    _userManager = userManager;
    }

    //[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
    [HttpGet("all")]
    public async Task<IActionResult> GetUrls([FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 10)
    {
    var b = Request;

    var a = await _userManager.GetUserAsync(User);
    var userId = _userManager.GetUserId(User);
    var shortUrls = await _urlService.GetAllUrlsAsync(pageNumber, pageSize);

    var dtos = shortUrls.Select(url => new UrlDTO
    {
    OriginalUrl = url.OriginalUrl,
    ShortCode = url.ShortCode,
    UserId = userId,
    IsOwner = url.UserId == userId,
    });

    return Ok(dtos);
    }
    }


    I also checked Request property and it contains Authorization header like: Bearer {token}.

    What am I doing wrong?

    I tried to use swagger with Authorize button and it worked fine with/without [Authorize] attribute. Actual user is returning from _userManager.GetUserId(User)
    Program.cs:

    using System.Security.Cryptography;
    using System.Text;
    using back.Configurations;
    using back.Data;
    using back.Data.Models;
    using back.Services.Authentication;
    using back.Services.ShortUrl;
    using Microsoft.AspNetCore.Authentication.JwtBearer;
    using Microsoft.AspNetCore.Identity;
    using Microsoft.EntityFrameworkCore;
    using Microsoft.IdentityModel.Tokens;

    var CORS_POLICY = "MY_CORS";

    var builder = WebApplication.CreateBuilder(args);

    builder.Services.Configure<JwtConfig>(builder.Configuration.GetSection("Auth"));

    builder.Services.AddScoped<IAuthenticationService, AuthenticationService>();
    builder.Services.AddScoped<IUrlService, UrlService>();

    builder.Services.AddCors(options =>
    {
    options.AddPolicy(name: CORS_POLICY, builder =>
    {
    builder
    .WithOrigins("http://localhost:4200")
    .AllowAnyHeader()
    .AllowAnyMethod();
    });
    });

    builder.Services.AddDbContext<AppDbContext>(options =>
    options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")
    ?? throw new ArgumentNullException("DefaultConnection")));

    builder.Services.AddAuthentication(options =>
    {
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    })
    .AddJwtBearer(options =>
    {
    options.SaveToken = true;
    options.TokenValidationParameters = new TokenValidationParameters
    {
    ValidateIssuer = true,
    ValidateAudience = true,
    ValidateLifetime = true,
    ValidateIssuerSigningKey = true,
    ValidIssuer = "https://localhost:7183",
    ValidAudience = "https://localhost:7183",
    ClockSkew = TimeSpan.FromMinutes(5),
    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration.GetSection("Auth").GetValue<string>("SecretKey")!))
    };
    });

    builder.Services.AddAuthorization();

    builder.Services
    .AddIdentity<UserEntity, IdentityRole>(options =>
    {
    options.Password.RequireDigit = false;
    options.Password.RequiredLength = 8;
    options.Password.RequireNonAlphanumeric = false;
    options.Password.RequireUppercase = false;
    options.Password.RequireLowercase = false;
    options.Password.RequiredUniqueChars = 0;

    options.Lockout.MaxFailedAccessAttempts = 5;
    options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
    options.Lockout.AllowedForNewUsers = true;
    })
    .AddEntityFrameworkStores<AppDbContext>()
    .AddDefaultTokenProviders();

    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen(c =>
    {
    c.AddSecurityDefinition("Bearer", new Microsoft.OpenApi.Models.OpenApiSecurityScheme
    {
    Description = "JWT Authorization header using the Bearer scheme (Example: 'Bearer 12345abcdef')",
    Name = "Authorization",
    In = Microsoft.OpenApi.Models.ParameterLocation.Header,
    Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey,
    Scheme = "Bearer"
    });

    c.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement
    {
    {
    new Microsoft.OpenApi.Models.OpenApiSecurityScheme
    {
    Reference = new Microsoft.OpenApi.Models.OpenApiReference
    {
    Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme,
    Id = "Bearer"
    }
    },
    new string[] {}
    }
    });
    });

    // Add services to the container.
    builder.Services.AddControllersWithViews();

    var app = builder.Build();

    // Configure the HTTP request pipeline.
    if (!app.Environment.IsDevelopment())
    {
    app.UseExceptionHandler("/Home/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
    }
    else
    {
    app.UseSwagger();
    app.UseSwaggerUI(c =>
    {
    c.SwaggerEndpoint("/swagger/v1/swagger.json", "inforce-tech v1");
    c.RoutePrefix = "swagger"; // Use "swagger" as the base path for UI access
    });
    }

    app.UseHttpsRedirection();
    app.UseStaticFiles();

    app.UseRouting();

    app.UseCors(CORS_POLICY);

    app.UseAuthentication();
    app.UseAuthorization();

    app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{id?}")
    .RequireCors(CORS_POLICY);

    app.Run();


    Jwt token generation:

    public async Task<string> GenerateJwtToken(UserEntity user)
    {
    List<Claim> claims = [
    new Claim(ClaimTypes.NameIdentifier, user.Id), // user id claim
    new Claim(JwtRegisteredClaimNames.Sub, user.UserName!),
    new Claim(JwtRegisteredClaimNames.Sub, user.Id),
    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
    ];

    var userRoles = await _userManager.GetRolesAsync(user);
    claims.AddRange(userRoles.Select(role => new Claim(ClaimTypes.Role, role)));

    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration.GetSection("Auth").GetValue<string>("SecretKey")!));
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

    var token = new JwtSecurityToken(
    issuer: "https://localhost:7183",
    audience: "https://localhost:7183",
    claims: claims,
    expires: DateTime.Now.AddHours(1),
    signingCredentials: creds
    );

    return new JwtSecurityTokenHandler().WriteToken(token);
    }

    Continue reading...

Compartilhe esta Página