Home > Software design >  Authenticating .net console applications with .net core web API
Authenticating .net console applications with .net core web API

Time:11-17

I have a .net core 3.1 web API ,which was built with JWT authentication and it is integrated with Angular UI and it working as expected.

following is my JWT authentication middleware


services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})

// Adding Jwt Bearer
.AddJwtBearer(options =>
{
    options.SaveToken = true;
    options.RequireHttpsMetadata = false;
    options.IncludeErrorDetails = true;
    options.TokenValidationParameters = new TokenValidationParameters()
    {
        ValidateIssuer = false,
        ValidateAudience = false,       
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:Secret"]))    
    };
    options.Events = new JwtBearerEvents
    {
        OnAuthenticationFailed = context =>
        {
            if (context.Exception.GetType() == typeof(SecurityTokenExpiredException))
            {
                context.Response.Headers.Add("Token-Expired", "true");
            }
            return Task.CompletedTask;
        }
    };
});

Now i need to create some more Web API methods which will be consumed by Angular UI as well as some existing scheduled tasks (.net console applications which will be consuming the web api methods) which are created for internal operations and will be running in the background.

My API controllers are decorated with [Authorize] attribute. It is working fine with Angular UI where the authentication and authorization are implemented using JWT bearer token.The problem is now with the integration of scheduled tasks which does not have logic for getting the tokens.

How to integrate these console apps with .net core web API in terms of authentication? the easiest option (which i thought) is to create a user login with like username "servicetask" and obtain token based on that username and do the API operation (but this requires more effort since no.of console apps are more and there and some apps from other projects also).

Is there any way to handle authentication in this case?

  1. Is it good practice to pass some API key from console application and by pass the authentication in web API ? is that possible ? then how to handle the request in .net core web api?

  2. Is it possible to create any JWT role or claims for these service account and validate them?

Please help.

CodePudding user response:

1.IMO, no , this won't be good idea. 2. Yes you can use claims for this scenario . Use a BackgroundService to run your task and inject claims principle on this class.

This sample is for service provider account claims: serviceAccountPrincipleProvider.cs

 public class ServiceAccountPrincipalProvider : IClaimsPrincipalProvider
{
    private readonly ITokenProvider tokenProvider;

    public ServiceAccountPrincipalProvider(ITokenProvider tokenProvider)
    {
        this.tokenProvider = tokenProvider;
    } 

    public ClaimsPrincipal CurrentPrincipal
    {
        get
        {
            var accessToken = tokenProvider.GetAccessTokenAsync().GetAwaiter().GetResult();
            if (accessToken == null)
                return null;

            var identity = new ClaimsIdentity(AuthenticationTypes.Federation);
            identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, accessToken.Subject));
            identity.AddClaim(new Claim(AppClaimTypes.Issuer, accessToken.Issuer));
            identity.AddClaim(new Claim(AppClaimTypes.AccessToken, accessToken.RawData));

            return new ClaimsPrincipal(identity);
        }
    }
}

This is your IClaimsProvider interface:

public interface IClaimsPrincipalProvider
{
    ClaimsPrincipal CurrentPrincipal { get; }
}

CodePudding user response:

  1. Don`t bypass authentication. You can pass appKey (key to identify the app instance) to webapi endpoint that is responsible for identifying your dotnet console apps. If appkey is part of your registered appkeys list, let the webapi endpoint get token on behalf of the console app by subsequent authentication step with your webapi auth service and return a JWT token to the console app. In my case I have console apps running on dotnet 4.5, I mention this because HttpClient is not available in previous versions. With HttpClient you can then do the following in your console app.
HttpClient client = new HttpClient(); 

client.BaseAddress = new Uri("localhost://mywebapi/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/text"));

HttpResponseMessage response= client.GetAsync("api/appidentityendpoint/appkey").GetAwaiter().GetResult();

var bytarr = response.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult();
string responsemessage = Encoding.UTF8.GetString(bytarr);

res = JsonConvert.DeserializeObject<Authtoken>(responsemessage);

Authtoken object can be as simple as

public class Authtoken
{
  public string accesstoken { get; set; }
  public string refreshtoken {get;set;}
}

and once you have your token you add it to your HttpClient headers for subsequent calls to your protected endpoints

  client.DefaultRequestHeaders.Add("Authorization", "Bearer "   res.token);

  client.GetAsync("api/protectedendpoint").GetAwaiter().GetResult();

Error handling is obviously required to handle reauthentication in case of token expiry etc

  • Related