JWT Token for distrubuted system running on multiple server instance - authentication

I am using JWT token for rest api's security.
When user is logged in check user's credentials with DB.
If it matched we are encrypting it for further security and then passing it to jwt to create a token
Now in order to match user's token we need to keep password somewhere so that we can match them when user sends any request after logged in
we can do it 2 ways
1. Keep detail in Database and each time rest call is fired check token with token in Database which is too costly for each rest call
2. Preserve secret somewhere in JVM and use it. Here I have tried HttpSession from package
javax.servlet.http.HttpServletRequest
// My key issue code
// Encrypt it
Key key = keyGenerator.generateKey(password);
jwtToken = Jwts.builder()
.setSubject(username)
.setIssuer(uriInfo.getAbsolutePath().toString())
.setIssuedAt(new Date())
.setExpiration(toDate(LocalDateTime.now().plusMinutes(1)))
.signWith(SignatureAlgorithm.HS512, key)
.compact();
// Adding details to session
HttpSession httpSession = currentRequest.getSession();
httpSession.setAttribute("userSecret", password)
This works fine for single Server instance.
But at some point we need to scale up and run multiple instance of server.
How do we handle this case where user may logged in using 1 instance and may serving rest call using another instance using load balancing.
As users secret is available only in first Server's JVM.

You can share the private key, which was used for encrypting the JWT, among the servers. When a servers gets an API call, you can try to decrypt the JWT with the private key. If the decryption is successful, you have a valid a JWT and you can process the request. If the decryption fails, that means it's an invalid JWT. Once a JWT has been created, you don't need to hit the database. That's the primary usage of JWT in my opinion.
I am not sure what you mean by userSecret.

Related

How server verifies JWT token

How does the server validate the JWT token?
Where is it stored?
How does the token expire after specific days?
On the client side, I store the token and send it to each query. But what's happening on the server side?
It could do with some entry that works
I'm not a JWT expert, so if some of what I write is wrong, I'm very happy to be corrected.
1) When distributing the JWT, the server will sign it using a private key. The private key is top secret, and must be stored securely on the server. This signature can then be verified using a public key, which confirms that this token was indeed signed by the server (using the top secret private key). The public key is not necessarily secret and can be widely distributed to anyone who needs to verify that the token was signed by that server.
2) The JWT does not really need to be stored anywhere on the server, as the server can verify that it's a valid token whenever it receives it. As the server is also likely to generate JWT, some servers will use a cache to store generated and valid JWT to increase performance. So in short, the JWT does not need to be stored by the server.
3) The JWT contains lots of data, including an expiration time (or time when it was created, and duration for how long it's valid). In addition to verifying the token using the public key, the server will discard valid tokens that have expired.
4) Before processing your request, the server will at minimum use the public key to verify that the token is genuine and check the expiration time. If it passes those tests, the server might also do additional checks with the data stored in the JWT before processing your request. These checks might include checking if your user ID has permission to access the data you are trying to access, check if you're located in a country to has access to the data, and so on. It can change wildly from a case to case basis.
It's a little bit of a broad question. I'll try to answer some specific points though.
How does the server validate the JWT token?
JWTs are typically digitally signed.
The token server signs the token using either symmetric or asymmetric cryptography.
The resource server validates the token by checking the signature against the symmetric key or public key.
Where is it stored?
This is up to the client.
In the case of a single page application, the client can store the token in local or session storage.
How does the token expire after specific days?
A JWT always has an expiry time, set in the token when it is created.
And since the token is signed, this time cannot be changed by someone without the key.
The resource server must check the expiry time after validating the signature.

AWS Cognito - Why is token still valid even User pool is changed or User is deleted (.Net core)

I'm quite new to AWS Cognito and about token security. I decided to use AWS Cognito for may application. I followed the guide here for my web app and my web api.
https://dzone.com/articles/identity-as-a-service-idaas-aws-cognito-and-aspnet
https://dzone.com/articles/identity-as-a-service-idaas-asp-net-core-api-and-a
Everything works fine. But when I try to create a new User pool in AWS Cognito and then change the appsetting for both web app and web api to use the new user pool, I found something quite weird.
(For the web app). User still can access controller action by the old token that belong to the old User pool that used before even the action is marked as [Authorize]. I don't know why user still can access with the old token even appsetting is set to the new User pool. (But User cannot access to the web api,that use new User pool, with the old token)
(For both web app and web api). Then I deleted that User from the old User pool and set web app and web api to use the old user pool. I found that User still can access both action in web app and web api even that User was deleted.
I think that it might be something that I missing about validation token or setting. Can anyone suggest about a solution to fix that?
The ID Token issued by AWS Cognito User Pool is a JWT token, which is Signed By AWS. Once issued the token is valid for 1 hour. Within this 1 hour, there is no way of revoking the token since its stateless.
Amazon Cognito generates two RSA key pairs for each user pool. The
private key of each pair is used to sign the respective ID token or
access token. The public keys are made available at an address in this
format:
https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json
Since the public key is publically available, anyone can verify whether the JWT token is authentic and issued by AWS Cognito.
However, this involved multiple things to verify.
Validate the JWT Token Encoding whether its compliant with JWT standard.
Validate JWT Issuer, whether its the particular User Pool (Verify its ID).
Validate whether the token is an ID Token (Optional).
Validate the Audience of the Token (Whether it is issued for the particular App).
Validate Token Signature (This is where the public key is needed).
Validate whether the token is expired or not.
This information is already self-contained within the JWT token string properly encoded according to the JWT standard.
Therefore, even the Cognito User Pool is deleted, if there is a valid token (< 1 hour after issued), it should be valid, if the verification process uses a stored Public key to verify it.

I can't understand the JWT Authentication well

Nowadays many developers use the JWT Authentication to authorize the api call.
By the way, if a hacker can capture the api call request of the authenticated user then he can have the authenticated JWT token.
Then the hacker can access this api with the authorized JWT token, without his authenticating.
Is this alright?
I am wondering that the JWT Authentication is actually safe.
Can you explain that?
A jwt is a code that contains information about the identity and claims of a user and is valid for only a limited amount of time.
The code cannot be read nor changed by anyone, except the authorization endpoint that issued the token. It is therefor safe in the sense that it cannot be tampered with. This means that the token can be fully trusted. You don't have to validate the token and you can use the identity information and claims without having to consult the database.
But this is also the disadvantage. Once issued the token is valid until it expires, since the expiration cannot be altered. That is why the token should only be send over a secured line to the server. You wouldn't want a hacker to intercept the token.
But if it happens, then what?
There are several options. You can use short-lived tokens, which means that a token expires short time after being issued. If a token was intercepted, it is only valid for a small amount of time. In that case you take for granted that a hacker can have access for limited time to the system. The advantage is that you need less resources and the effort of hacking is probably not worthwhile.
Another option is to validate the token on each request. This requires more resources (e.g. lookups in the database), though you can use some sort of caching. If something changes, like the ip address, then you can invalidate the token. But the question is if you can detect if a token was send by a hacker.
So it depends on the chosen strategy. But: if you issue a long-lived access token without validation (and thus without the possibility to revoke the token), then you'll have a problem if a hacker gets hold of an access token. So you'll need to do something to use it in a safe way.
While I think this should be enough to help you understand, I would like to mention the use of refresh tokens. If you use short-lived access tokens, then you may want to implement long-lived refresh tokens. These refresh tokens are meant to obtain a new access token after it expires. The advantage is that you don't need to send the credentials, the refesh token suffices. You can however only implement this in an application that can keep a secret. Because you most certainly do not want a hacker to intercept the (long-lived) refresh token.
Being used less frequently (opposed to the access token) you can add logic to validate the refresh token when used. You can consult the database and decide to reject the request (e.g. when ip address changed) and revoke the refresh token. In that case the user has to identify itself again (send credentials).
JWT is just a secure msg transporter between fsb server and client so that fsb server can determine whether the client is logged in or not; if logged in, the fsb server will fetch personal unique user based data.
google oauth
G sends back user gid to my server only if user has a google account and successfully inputs gmail and password correctly.
user id is saved in jwt’s payload.
jwt
if google validates the user and google returns gid
create jwt content and internal maintenance: exp date, encryption
jwt is sent and stored in local store of user’s browser;
each user’s req sends jwt back to my server
my server decodes the jwt using secretOrKey, which only my server has, and gets the content(uid) from the jwt.
if uid is in my db, user had already registered and right now is logged in.
send the requested data from my db to the user because he is logged in
if use fails google validation due to wrong password or G email, jwt isn't created.
Process of JWT
user’s google popup logs in
google server returns information to my server. If the gid isn’t in my db, I’ll save it in my db so that the user can be registered.
create jwt and add uid as content. Exp date.
jwt is sent and stored in local storage of users browser
user requests a page though http, it includes the jwt. my server checks whether this user is logged in or not by Login determination test: if user’s jwt uid is in my DB, user is logged in. the user requested data will be given to the user. If user doesn’t have jwt or uid doesn’t match then the user isn't logged in, send the user to login page.
JWT descriptions
https://medium.com/#rahulgolwalkar/pros-and-cons-in-using-jwt-json-web-tokens-196ac6d41fb4
https://scotch.io/tutorials/the-ins-and-outs-of-token-based-authentication
https://scotch.io/tutorials/the-anatomy-of-a-json-web-token
https://auth0.com/blog/cookies-vs-tokens-definitive-guide/

Separate authentication server for users and APIs

I'm working on a cloud service authentication system and I'm not entirely sure what the optimal way to handle authenticating requests is. We're planning to run our image server as a separate process from our API server so that we can scale them independently of each other. Handling request authentication with API keys is fairly simple, because we can just have the image server store its own API key and check that requests provide it in a header (over HTTPS obviously), same with the API server. For users though it gets more complex.
Right now we have it setup so that the API server will handle generating a session token and storing users in its database, however what we'd like to do is use 3 servers:
authentication server
API server
image server
and have the image and API servers authenticate requests against the authentication server. How exactly should this be done though? It seems like a bad idea performance-wise to hit the authentication server for every request that the API and image servers make. Can/should a token be verified from a different server than it was created on?
So for example: can/should I pass the token received from the authentication server to the image server, verify that the token came from "my.auth.server" and check that the user ID is the right one? Would JWTs be a good type of token for this?
Here's an alternative approach.
Your authentication issues a JWT token that is signed using a secret that is also available in your API and server images. The reason they need to be there too is that you will need to verify the tokens received to make sure you created them. The nice thing about JWTs is that their payload can hold claims as to what the user is authorised to access should different users have different access control levels.
That architecture renders authentication stateless: No need to store any tokens in a database unless you would like to handle token blacklisting (think banning users). Being stateless is crucial if you ever need to scale. That also frees up your API and image servers from having to call the authentication server at all as all the information they need for both authentication and authorisation are in the issued token.
Flow (no refresh tokens):
User authenticates with the authentication server (eg: POST /auth/login) and receives a JWT token generated and signed by the auth server.
User uses that token to talk to your API and image servers and assuming user is authorised), gets and posts the necessary resources.
There are a couple of issues here. Namely, that auth token in the wrong hands provides unlimited access to a malicious user to pretend they are the affected user and call your APIs indefinitely. To handle that, tokens have an expiry date and clients are forced to request new tokens whenever expiry happens. That expiry is part of the token's payload. But if tokens are short-lived, do we require users to authenticate with their usernames and password every time? No. We do not want to ask a user for their password every 30min to an hour, and we do not want to persist that password anywhere in the client. To get around that issue, we introduce the concept of refresh tokens. They are longer lived tokens that serve one purpose: act as a user's password, authenticate them to get a new token. Downside is that with this architecture your authentication server needs to persist these refresh token in a database to make them revokable before they expire (think "revoked" column in tokens table).
New flow (with refresh tokens):
User authenticates with the authentication server (eg: POST /auth/login) and receives a JWT token generated and signed by the auth server, alongside a long lived (eg: 6 months) refresh token that they store securely
Whenever the user needs to make an API request, the token's expiry is checked. Assuming it has not yet expired, user uses that token to talk to your API and image servers and assuming user is authorised), gets and posts the necessary resources.
If the token has indeed expired, there is a need to refresh your token, user calls authentication server (EG: POST / auth/token) and passes the securely stored refresh token. Response is a new access token issued.
Use that new token to talk to your API image servers.
OPTIONAL (banning users)
How do we ban users? Using that model there is no easy way to do so. Enhancement: Every persisted refresh token includes a blacklisted field and only issue new tokens if the refresh token isn't black listed.
Things to consider:
You may want to rotate refresh token. To do so, blacklist the refresh token each time your user needs a new access token. That way refresh tokens can only be used once. Downside you will end up with a lot more refresh tokens but that can easily be solved with a job that clears blacklisted refresh tokens (eg: once a day)
You may want to consider setting a maximum number of allowed refresh tokens issued per user (say 10 or 20) as you issue a new one every time they login (with username and password). This number depends on your flow, how many clients a user may use (web, mobile, etc) and other factors.
You can store some additional metadata (ip, geolocation, device, browser cookie, etc.) alongside refresh tokens. That way, you can be smart about when to reject malicious usages of refresh tokens in case it's compromised.
Common Q: Why store all refresh tokens, and not just revoked ones? You could do that. Ask yourself the following: Will I, at any point, need to have a functionality where I can dynamically revoke valid refresh tokens, based on some arbitrary, regulatory, legal, integrity, security etc. criteria? If so, the least you will need is a list of all issued tokens, plus any data required to implement the criterion logic. Example: Due to regulation, I need to ban all EU users equates to a delete from refresh_tokens were user_ip in <... eu logic ...>
one of the best ways to use is a JWT Token , you can generate and share it between all your servers and validate it on the server side .
https://jwt.io
also I think the best architecture to use in this case is the micro service architecture

how does token validation works on token based authantication systems

When token based authantication is compared to traditional server authantication, it is said that: traditional method keeps login info in memory on server side, but in token based authantication server keeps nothing. Information about logged in user is stored in token itself.
However, I didn't get one point here. If server doesn't store anything, how does server validate the token? I think it should store the secret key to decrypt the token and then validate.
If so, where is it stored? If not what poin did I miss?
The server issuing the token, digitally signs the token with a private key.
The service consuming the token only needs the public key to validate the token. It can download the public key from the issuing server on startup or first use. After that, it does not need to communicate with the issuing server to validate tokens. If the signature is valid, the service trusts the contents of the token.
For example, look at the "jwt", it uses "ssh" keys