Home > front end >  Setting up authentication endpoints class in minimal API
Setting up authentication endpoints class in minimal API

Time:11-15

In Program.cs I have a post endpoint for getting a Jwt token:

app.MapPost("/api/security/getToken", [AllowAnonymous] async (UserManager<IdentityUser> userMgr, UserLoginDTO user) => {
    var identityUser = await userMgr.FindByEmailAsync(user.Email);
    if (await userMgr.CheckPasswordAsync(identityUser, user.Password)) {
        var issuer = builder.Configuration["Jwt:Issuer"];
        var audience = builder.Configuration["Jwt:Audience"];
        var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]));
        var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
        var claims = new List<Claim> {
            new Claim(ClaimTypes.Email, identityUser.Email),
            new Claim(ClaimTypes.GivenName, identityUser.UserName)
        };;
        var token = new JwtSecurityToken(issuer: issuer, audience: audience, signingCredentials: credentials, claims: claims);
        var tokenHandler = new JwtSecurityTokenHandler();
        var stringToken = tokenHandler.WriteToken(token);
        return Results.Ok(stringToken);
    }
    else {
        return Results.Unauthorized();
    }
}).WithTags("Security");

I want to move that logic in a separate class for readability.

public static class SecurityEndpoints {
    public static void MapSecurityEndpoints(this WebApplication app) {
            app.MapPost("/api/security/getToken", GetToken).AllowAnonymous();
            app.MapPost("/api/security/createUser", CreateUser).AllowAnonymous();
    }
    internal static async Task<IResult> GetToken(this WebApplicationBuilder builder, UserManager<IdentityUser> userMgr,[FromBody] UserLoginDTO user) {
    //same logic
    }
    ...
  }

Because of the WebApplicationBuilder I'm getting a InvalidOperationException.

How to refactor the GetToken method to get rid of WebApplicationBuilder and maybe access the builder.Configuration details that I need form another service? How would that service look like? Or how else would you approach this?

CodePudding user response:

You should not use WebApplication(Builder) in your handlers. Use standard approaches for working with the configuration in .NET/ASP.NET Core which are described here.

For example create type for jwt settings, register it with options pattern and inject into handler. Something along this lines:

public class JwtOptions
{
    public const string Position = "Jwt";

    public string Issuer { get; set; } = String.Empty;
    public string Audience { get; set; } = String.Empty;
}

builder.Services.Configure<JwtOptions>(
    builder.Configuration.GetSection(JwtOptions.Position));

internal static async Task<IResult> GetToken(IOptions<JwtOptions> jwtOptions,...) {
  // use jwtOptions
}
  • Related