barak
barak

Reputation: 179

ASP.NET Core authenticate API service with exterrnal identity API

I'm searching for a proper way to authenticate an API service with my own external identity service as the diagram below:

enter image description here

Every incoming request to the API data need to be verified by the identity service, then it can continue the flow to fetch data from database etc...

This is my solution for now which works ok: in my API data service, I created a middleware and set it as the top middleware so every incoming request will verify the token with the authentication service API.

public class CustomAuthMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger _logger;
    private readonly IAuthenticationService _authenticationService;

    public CustomAuthMiddleware(RequestDelegate next, ILoggerFactory logFactory, IAuthenticationService authenticationService)
    {
        _next = next;
        _logger = logFactory.CreateLogger<CustomAuthMiddleware>(); ;
        _authenticationService = authenticationService;
    }

    public async Task Invoke(HttpContext context)
    {
        string token = context.Request.Headers["ApiToken"];

        if (!string.IsNullOrEmpty(token))
        {
            //sending http request to the authentication API
            var isVerified = await _authenticationService.VerifyToken(token);

            if (isVerified)
                await _next(context);
        }

        throw new AppException(System.Net.HttpStatusCode.NotFound);
    }
}

And in my identity service, I have the following action method that authenticates requests by tokens:

[Authorize]
[HttpGet("verifyToken")]
public async Task<IActionResult> verifyToken()
{
    var user = await _userManager.FindByEmailAsync(User.FindFirstValue(ClaimTypes.Email));

    if (user != null)
        return Ok();

    return BadRequest();
}

As I said, it works fine, but honestly, I feel this way is not the best and I don't feel comfortable with this solution.

So my question is

Is there any proper way to authenticate request on the API data service with the identity service, something more "best practice" or with a better design?

Upvotes: 1

Views: 358

Answers (1)

MD Zand
MD Zand

Reputation: 2605

You can do it with adding OIDC authorization/authentication to your api data service so the verification of the token automatically happens and also you can easily implement other standard features like roles authorization. To do so you need some configuration both in your Identity Server and api data service. in program.cs of your a

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
builder.Services.AddAuthentication(
     options =>
     {
         options.DefaultAuthenticateScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
         options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
     })
    .AddJwtBearer("Bearer", options =>
    {
        options.Authority = configuration["ServiceUrls:IdentityAPI"];
        options.RequireHttpsMetadata = false;
        options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
        {
            ValidateAudience = false,
            RoleClaimType = JwtClaimTypes.Role,
            NameClaimType = JwtClaimTypes.Name,
        };
       

    });

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("ApiScope", policy =>
    {
        policy.RequireAuthenticatedUser();
        policy.RequireClaim("scope", "microstruct");
    });
});

And at the end:

app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();

An open-source project with .net 6 and identity server is available here and take a look at Identity server project (MicroStruct.Services.Identity) settings and also (MicroStruct.Services.Dashboard).

Upvotes: 3

Related Questions