Using JWT to implement Authentication on Asp.net web API - asp.net-web-api

I have been reading about JWT.
But from what I read it is not an authentication mechanism but more like a crucial component in a Authentication mechanism.
I have currently implemented a solution which works, but it was just to try out JWT and see how it works. But what I am after now is how one should make use of it. From my experience of it its basically just an encryption mechanism that gives you a unique encrypted key. You are also able to put information inside of this token.
I am wanting to implement it in terms on a ASP.NET web api 2 to be consumed by a mobile application.
So step 1:
app => Server : Login (user, pasword)
Server => app : Login OK, heres your JWT
app => server : Get my profile (sends JWT with request)
Server then decrypts JWT and determines the requests Identity.
Now this is just my understanding of it, Look I could be on the totally wrong path.
Is the Ideal of JWT so that you dont have to authenticate on every request? I just authenticate the users credentials once (on the initial login) and there on after the server can simply use JWT and no have to lookup the users pw and user in the DB?
I just want to use the JWT to Identity who the user is. I will then authorize then after i have authenticated them. As I know there is a big confused with the new MVC and Authentication and Authorization.
So what my question comes down to.
How can I safely and effectively Implement a Authentication Mechanism Using JWT?
I don't want to just cough something up that seems to work and not have any Idea of the security implications. I am sure that there exists a source some where that has possibly designed a secure mechanism that would suit my requirements.
My requirements are:
Must only have to check db for users credentials once off per session? Due to the use of bcrypt using a lot of resources to compare passwords.
Must be able to identify the user from their request. (I.e who they are, userId will be sufficient) and preferably without accessing the DB as well
Should be as low overhead as possible, with regards to resources on the server side processing the request.
If an intruder had to copy a devices previous request, then he should not be able to access the real users data. (obviously)
Thanks

Your understanding of JWTs is good. But here are a couple corrections and some recommendations.
Authentication and Authorization
JWTs have nothing to do with authentication. Hitting your DB and hashing passwords only happens when you authenticate on creation of the JWT. This is orthogonal to JWTs and you can do that in any way you like. I personally like Membership Reboot, which also has a good example of using JWTs.
Theoretically, you could have the user enter a password once a year and have the JWT be valid that entire year. This most likely not the best solution, if the JWT gets stolen at any point the users resources would be compromised.
Encryption
Tokens can, but don't have to be encrypted. Encrypting your tokens will increase the complexity of your system and amount of computation your server needs to read the JWTs. This might be important if you require that no one is able to read the token when it is at rest.
Tokens are always cryptographically signed by the issuer to ensure their integrity. Meaning they cannot be tampered with by the user or a third party.
Claims
Your JWTs can contain any information you want. The users name, birthdate, email, etc. You do this with claims based authorization. You then just tell your provider to make a JWT with these claims from the Claims Principle. The following code is from that Membership Reboot example and it shows you how this is done.
public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var svc = context.OwinContext.Environment.GetUserAccountService<UserAccount>();
UserAccount user;
if (svc.Authenticate("users", context.UserName, context.Password, out user))
{
var claims = user.GetAllClaims();
var id = new System.Security.Claims.ClaimsIdentity(claims, "MembershipReboot");
context.Validated(id);
}
return base.GrantResourceOwnerCredentials(context);
}
This allows you to control with precision whom is accessing your resources, all without hitting your processor intensive authentication service.
Implementation
A very easy way to implement a Token provider is to use Microsoft's OAuth Authorization Server in your WebAPI project. It give you the bare bones of what you need to make a OAuth server for your API.
You could also look into Thinktecture's Identity Server which would give you much easier control over users. For instance, you can easily implement refresh tokens with identity server where the user is authenticated once and then for a certain amount of time (maybe a month) they can continue getting short lived JWTs from the Identity Server. The refresh tokens are good because they can be revoked, whereas JWTs cannot. The downside of this solution is that you need to set up another server or two to host the Identity service.
To deal with your last point, that an intruder should not be able to copy the last request to get access to a resource, you must use SSL at a bare minimum. This will protect the token in transport.
If you are protecting something extremely sensitive, you should keep the token lifetime to a very short window of time. If you are protecting something less sensitive, you could make the lifetime longer. The longer the token if valid, the larger the window of time a attacker will have to impersonate the authenticated user if the user's machine is compromised.

I've written detailed blog post about configuring the OWIN Authorization server to issue signed JSON Web Tokens instead of default token. So the resource servers (Audience) can register with the Authorization server, and then they can use the JWT tokens issued by Token issuer party without the need to unify machineKey values between all parties. You can read the post JSON Web Token in ASP.NET Web API 2 using Owin

For the formal concept . The Authentication is the process of verifying who a user is, while authorization is the process of verifying what they have access to.
Let’s see the real life example
Imagine that your neighbor has asked you to feed his pets while he is away. In this example, you have the authorization to access the kitchen and open the cupboard storing the pet food. However, you can’t go into your neighbor’s bedroom as he did not explicitly permit you to do so. Even though you had the right to enter the house (authentication), your neighbor only allowed you access to certain areas (authorization).
For more detailed and for users who like more STEP BY STEP implementation on practical use of JSON Web Token in WEB API. This is must read post Secure WebAPI Using JSON WEB TOKEN
Updated to use: System.IdentityModel.Tokens.Jwt -Version 5.1.4

Related

Custom JWT token in springboot microservices

We have an application that loads information(user specific) from the external system upon successful authentication, to avoid round trips to the external system for each api call, we are planning create a custom JWT token with user specific information for the first time user authenticated, then the token is send to user in each response header using http interceptor and in the front-end we are including the custom token in every request along with authorization token. Is this correct approach? Do you have any alternative suggestions?
I have looked into other distributed caching techniques like redis but not so appealing for a small usecase. Our payload length does not exceed 4 to 5K hence inclined towards the JWT option
it is ok to include user information that allows you to handle the user authorization inside the access token. Just beware of the privacy implication and perhaps not include personal information like social security number or date-of-birth or other identifiable information.
Also, make sure the token size does not get to big. The other option is to lookup and cache the user information in the API's when it receives a new access token.
Some systems including ASP.NET Core do store the token inside the session cookie in an encrypted form, so that the end user can't see or access the stored tokens.
If you are developing a SPA application, the using the BFF pattern is one approach.

Spring Boot JWT - How to implement Refresh Token and Logout REST-API

We decided to switch from Basic-Auth to JWT because of the session-ids that were stored in the memory and which leads sometimes to over-memory consumption in shoot-down of our Spring-Boot server that serves an Android mobile app like Twitter.
But we have some questions about JWT for our mobile use-case:
How long should an access token lives ?
How long should the refresh token lives ?
How to logout a User by invalidating his access-token and refresh token ? (For the logout we already delete the tokens on the mobile app side, but what if the tokens have being stolen by somebody and are still valid ?)
I will try to answer your queries
How long should an access token live?
You can easily configure expiry time so it depends on your requirement.
In general, try to keep it short.
How long should the refresh token live?
Above goes for refresh token with a condition that refresh token generally lives longer than access token for obvious reasons.
How to logout a User by invalidating his access-token and refresh token?
This part can be a little tricky.
You cannot manually expire a token after it has been created. So, you cannot log out with JWT on the server-side, as you do with sessions.
Can implement a few options like
When a user performs logout action or compromised. Have a blacklist which stores invalid tokens until their initial expiry date. You will need to lookup DB for every request but storage should be less as you will be storing tokens that were between logout & expiry time. You can make the blacklist efficient by keeping it in memory instead of DB.
Store Client IP Address in the claims objects JWT. When validating the token you can check with this client's IP address if it is the same source or not. You can refine it based on need like use User-Agent along with Client IP.
Worst of all reset user credentials or JWT token components to generate a new one which automatically invalidates all existing ones.
Adding a few links for more in-depth detail
Invalidate JWT Token
Destroy JWT Token
I mean it looks more like you should just be using sessions.
JWTs are not a simple replacement. They have a specific function and for some reason they have become embedded as some sort of automatic go to for any auth system.
From what you have described (the lifting of a basic auth to a more secure and modern auth system) you should be using sessions.
Good ol' Cookie sessions.
I'd go in to why more but to sum up:
A) You can control the session without odd stick on "banlist" tables and extra architecture for the JWTs for users that are banned/logged out for a system that doesn't actually need these if you just used traditional cookie based sessions.
B) They are tried and tested and the browser will keep them safe! Session cookies can be made "secure" and "http-only". There are many odd places people put JWTs including the local/session storage of a browser just waiting for a naughty js injected advert to suck them up. JWTs,just like SessionIDs, should
be in an Http-Only, Secure and Same-Site strict Cookie.
So you may as well just use a session ID and get on with life without strange front end state management when the browser is quite happy and doing that securely for you when using a Session Cookie.
C) Traditional sessions are easy to implement. Harder to understand how/why they work with all the SameSite/HttpOnly/CORS/Secure parts going on...but to implement when once understood is 99x easier and require less code when there is the Spring Framework already doing that 99% for you.
I mean sure it isn't hard to write your own JWTAuthTokenAuthFilter and implement a JWTAuthenticationProvider and a JWTCreationService and a `JWTAutoRefreshFilter...and whatever else you dream of...but why bother if you just need a session. Spring does it in like 20 lines of well tested code.
To sum up:
I mean of course properly implemented JWTs are secure...it is just maybe they are not always the best fit tool for a job.
Have a read of:
Stop Using JWTs for Sessions
Of course JWTs have a use. They are for letting a 3rd party know "yes, this is someone I know" before the client hits their API end points. Or for say having one of your servers talk to another of yours...or having client's servers talk to yours or even your servers talk to another companies:
JWT Auth - Best Practices

Killing "session" with SignalR, OWIN, and Web API

It has been a long road but I have SignalR working with my Web API which uses OWIN for token authentication.
I have a mechanism where if a user authenticates on terminal #1 and then later authenticates on terminal #2, I can send them a Javascript alert saying "Hey, only one session at a time. Which one do you want to log out?"
The question I have is how to kill their "session" on one of the terminals? I say "session", but since this is a REST based API there really is no session. If I could force them to re-authenticate on the terminal they choose to "log out" from that would be sufficient.
I have the SignalR connectionId of each client. Is there a way I can expire their authentication token and force a logout?
Note - The client is separate from the Web API in that they are hosted on two different servers. The client is just HTML/Javascript making calls to the Web API.
If you are using a bearer token approach, and you are not storing tokens (or token hashes) into some kind of persistent storage (e.g. a DB), then you have no way to invalidate a token.
Since OAuth is not an Authentication protocol, it do not have any kind of log out concept in it. Your only option is to remove the token from the client storage (I can imagine it is stored inside the localStorage or in a cookie).
Of course this does not really invalidate anything, and if the token is not deleted for some reason, it can still be used for authorization purposes.
Your only option, if you really need a single access token valid at a single time, is to store some information about it in a database, and check that storage every time you validate the token. You could, for instance, store the hash of the token (never store the real token for this reason, they have the same value of passwords once stored) with the username, but please note that this approach makes your authorization protocol a little less stateless than before.

ASP Identity OAuth token - Should I use ValidateClientAuthentication() and Secret in mobile app flow?

I have a mobile app which talks to an ASP WebAPI on the back-end.
I've implemented the token flow authentication (with the help of Taiseer's guide).
Still there is one concept I can't grasp my mind around: CleintId and ClientSecret.
From what I understand the client secret (along with client id) is meant to
block access to the end point in my API that produces tokens. This way the end point is protected from malicious users trying to poke around the API and try to gain some information by invoking it with various inputs.
Meaning, only clients which hold the secret can start an authenticaon flow. And in my case, I have only one client which is a mobile app, and it's secret is stored in a secure place (KeyChain for iOs). But I've read that those key chains can be easily dumped and dissect for the secret.
So the conclusion I came up with, is that I can get rid of the whole client secret logic, mainly leaving ValidateClientAuthentication() blank:
public async override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
return;
}
And to me it dose not seem like a security hole, but just a thin layer in the flow that is gone now. Because, again, the client secret can be easily revealed by any malicious user holding a mobile device with the app installed, and once he gets it this layer of security is useless.
Are those assumptions are incorrect ?
Can I leave the ValidateClientAuthentication() method blank ?
As you already figured out, mobile applications cannot keep their credentials private because they can be extracted from the application binaries. Not to mention that requests can be easily intercepted using a proxy server and a traffic analyzer like Fiddler or Wireshark.
With the authorization code flow (1) or the resource owner password credentials grant, client authentication is not mandatory if the client cannot safely store its credentials and thus cannot be considered as a "confidential" application (see https://www.rfc-editor.org/rfc/rfc6749#section-4.1.3 and https://www.rfc-editor.org/rfc/rfc6749#section-4.3.2).
For non-confidential applications, it's safe to call context.Validated().
Personally, I try to avoid the resource owner password credentials grant as much as possible as it clearly defeats the purpose of OAuth2: keeping your password confidential and giving constrained authorizations. If your app is fully trusted, it shouldn't be a problem, though.
In practice, using the authorization code flow without enforcing client authentication is extremely rare, as it's simpler to use the implicit flow with mobile client applications, that offers a similar security level in this case (not to mention that it avoids a second roundtrip to the token endpoint).

API Authentication and use of OAuth2

I’m trying to get my head around how I would introduce token-based (key-based?) authentication to a web API (currently looking at Sinatra, but maybe Rails too) that would be used by a mobile client and how OAuth would fit into the picture.
So, let’s say I want to create a web service that uses Facebook for authentication and grabbing basic user data. Here, my API would be a client to Facebook’s OAuth Server, requesting an access token upon a user’s successful login to Facebook. This would then grant me access to the user’s data which I would use to create an entry in my database, storing this user-specific token with any other application information I would like linked to them.
I think I got that part right so far, but here’s where I’m a bit confused.
I think that my API would also need some form of API key to grant access to a mobile user, since I wouldn’t want to transmit and store the Facebook key on their device. Would I have to have a separate store of keys which I provide to the client to access my service? Are there any ‘best practice’ ways of doing this?
Would I have to have a separate store of keys which I provide to the client to access my service?
yes.
Are there any ‘best practice’ ways of doing this?
The simplest way would be to generate a separate authentication token on every User creation and expose that to the mobile client. Then send it with every subsequent request header.
Devise provides a simple example how to achieve that. You don't need devise for that, just provide some token generation mechanism.
#Devise.friendly_token
def self.friendly_token
SecureRandom.urlsafe_base64(15).tr('lIO0', 'sxyz')
end
This mechanism can be extended to provide more security in following ways
Being an oauth2 provider itself.
On successfull login with facebook, you would generate an :authorization_code which the client can exchange for your own Oauth2 Bearer or MAC token within a next step. Then you can send your own Oauth2 token with every request for user authentication.
See rack-oauth2
Implement HMAC token encryption.
Generate and expose a secret_key to every client after singning in. Use this secret to sign messages along with a unique client id. The server can then lookup the secret_key for the specific client_id and verify the message.
See api-auth

Resources