question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Using JWT with custom authentication filter in the Web API

See original GitHub issue

Hey there, and thanks for an amazing framework!

I’ve scoured the web for an issue about this, but couldn’t find one, so here goes.

I’m attempting to implement JWT, to authenticate mobile clients by a deviceToken (as the clients doesn’t use a login). I’ve followed the setup from: https://github.com/cuongle/WebApi.Jwt , using the same filters, and then inserting the following in the ProjectNameWebApiModule.cs:

//Outcommented "bearer" from original
Configuration.Modules.AbpWebApi().HttpConfiguration.Filters.Add(new JwtAuthenticationAttribute());

The authentication filter looks like this (same as the github link above):

public class JwtAuthenticationAttribute : Attribute, IAuthenticationFilter
{
	public string Realm { get; set; }
	public bool AllowMultiple => false;

	public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
	{
		var request = context.Request;
		var authorization = request.Headers.Authorization;

		if (authorization == null || authorization.Scheme != "Bearer")
		{
			context.ErrorResult = new AuthenticationFailureResult("Missing Jwt Token", request);
			return;
		}
		if (string.IsNullOrEmpty(authorization.Parameter))
		{
			context.ErrorResult = new AuthenticationFailureResult("Missing Jwt Token", request);
			return;
		}

		var token = authorization.Parameter;
		var principal = await AuthenticateJwtToken(token);

		if (principal == null)
			context.ErrorResult = new AuthenticationFailureResult("Invalid token", request);

		else
			context.Principal = principal;
	}

	private static bool ValidateToken(string token, out string username)
	{
		username = null;

		var simplePrinciple = JwtManager.GetPrincipal(token);
		var identity = simplePrinciple.Identity as ClaimsIdentity;

		if (identity == null)
			return false;

		if (!identity.IsAuthenticated)
			return false;

		var usernameClaim = identity.FindFirst(ClaimTypes.Name);
		username = usernameClaim?.Value;

		if (string.IsNullOrEmpty(username))
			return false;

		// More validate to check whether username exists in system

		return true;
	}

	protected Task<IPrincipal> AuthenticateJwtToken(string token)
	{
		string username;

		if (ValidateToken(token, out username))
		{
			// based on username to get more information from database in order to build local identity
			var claims = new List<Claim>
			{
				new Claim(ClaimTypes.Name, username)
				// Add more claims if needed: Roles, ...
			};

			var identity = new ClaimsIdentity(claims, "Jwt");
			IPrincipal user = new ClaimsPrincipal(identity);

			return Task.FromResult(user);
		}

		return Task.FromResult<IPrincipal>(null);
	}

	public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
	{
		Challenge(context);
		return Task.FromResult(0);
	}

	private void Challenge(HttpAuthenticationChallengeContext context)
	{
		string parameter = null;

		if (!string.IsNullOrEmpty(Realm))
			parameter = "realm=\"" + Realm + "\"";

		context.ChallengeWith("Bearer", parameter);
	}
}

The problem:

Above seems to work, however, when a token is not valid, I am not able to pass the error to the response. I get a standard 500-error response like this:

{
    "result": null,
    "targetUrl": null,
    "success": false,
    "error": {
        "code": 0,
        "message": "An internal error occurred during your request!",
        "details": null,
        "validationErrors": null
    },
    "unAuthorizedRequest": false,
    "__abp": true
}

Questions:

  1. How does one go by extending this, so that the mobile client can react to the response?
  2. Are there any examples of a JWT integration like this, without a username/password?

Details:

.Net Framework, Abp version: 1.3.1 Username/password solution is not possible, as an anonymous approach must be taken.

Thank you.

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
acjhcommented, Jul 31, 2017

Does line 47 refer to var identity = simplePrinciple.Identity as ClaimsIdentity;?

Add a null-conditional operator:

var identity = simplePrinciple?.Identity as ClaimsIdentity;
0reactions
Codeshark-NETcommented, Sep 26, 2017

Thanks for your assistance @acjh .

I ended up completely rewriting the authentication filter, from scratch, in order to understand it fully. After that, I’ve had no issues.

Thanks again 👍

Read more comments on GitHub >

github_iconTop Results From Across the Web

Custom JWT Token Authentication in Web API with ... - YouTube
JWT with ASP.NET Core in 3 Simple Steps - WebAPI | REST API | Ep 8 · Adding JWT Authentication & Authorization in...
Read more >
Custom JWT Token In ASP.NET Core Web API
I have implemented Authorization filter to secure the endpoint and this endpoint accepts HTTP GET requests and returns a list of all the...
Read more >
Authentication Filters in ASP.NET Web API 2
An authentication filter is a component that authenticates an HTTP request. Web API 2 and MVC 5 both support authentication filters, ...
Read more >
c# - How to use JWT token and Action filters to retrieve user ...
1 Answer 1 · JWT contains a user's id or some claims. · You have a WEB API endpoint like ("GetCurrentUserData()") decorated with...
Read more >
Authorization with JWT via ASP.NET Core authorization filters
NET Core application. This filter will then add authorization to all endpoints via the configured properties on the filter itself. Example: using Arcus....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found