I'm working on a project for which I have planned the following architecture:
auth.example.com: Provides login, registration, and password-reset functionalities.
accounts.example.com: Allows users to update their account data.
example.com: Provides other services.
I have figured out the following solution for maintaining authentication across all domains:
Authenticate user on auth.example.com and set a cookie containing JWT token (signed token with shared key) which contains the user data and its domain is set to .example.com.
Once the user is authenticated, redirect them to example.com/dashboard and verify the JWT token present in the cookie. If the token is valid, present the service to the user else redirect to auth.example.com.
Now, I have the following doubts:
Suppose if a user updates his name on accounts.example.com, how do I make all other services use the updated user data?
If I want to ban a user or delete their account or terminate all active sessions, how would I let other services that the user shall not be authenticated?
Is there any better approach to solve this problem?
JWT tokens are generally stateful means they have everything to be authenticated, once issued they can be used and there is no way we can revoke them. However there are few approaches that we can use.
Normally we keep the life time (expiry) of token short (e.g. 15 mins) and refresh the access after X minutes using Refresh Token (Know the difference between Refresh and Access Token).
Say the token is about to get expired then we will re-issue the access token (refresh token will do that without user sign in again). Refresh tokens are long lived token and have to be handled carefully. If we have to revoke the access then we need to revoke Refresh token and after X mins user is not able to get access token since Refresh token is revoked already.
During the time when you revoked the refresh token , any access token issued is still valid until reaches its expiry. If you want to invalidate the token before that then you may have to blacklist the token and maintain the list of such tokens that will stop the user from login using that particular token.
I have found very nice explanation here Check Revoke Token
Club JWT token, protocols like oauth and openid and store the session in redis/memcache.
This redis/memcache will be single point of contact for all your microservices.
Say microservice m1, m2, ... are independent and using restapi gets connected to microservice called mR which checks the session in redis/memcache.
Related
AWS Cognito has API methods GlobalSignout and AdminUserGlobalSignout that can be used to revoke the access and refresh tokens issued for a user in a user pool (but not the ID token). However, the access token issued using the client credentials flow has no associated user. GlobalSignout fails with an error and AdminUserGlobalSignout requires a username, of which there is none in this context.
The token is short-lived, but in a situation where access tokens have been compromised, revoking the token in a way similar to that described in RFC 7009 would be great peace of mind.
I haven't found anything indicating it is possible to explicitly revoke the token before it expires. Is there any facility to do this?
Maybe one day Cognito will have this and other essential features but it is not for today. The best advice is to validate tokens in your authorization code.
When you are ready to revoke a user's tokens, make a call to CognitoIdentityServiceProvider.globalSignOut().
Then, wherever you are doing the token validation, add an extra check with a call to CognitoIdentityServiceProvider.getUser(). If the call succeeds, the tokens haven't been revoked. If it fails, they are not authorized.
By the way, the 'sub' field in the Access Token is a unique ID that can be matched back to the ID Token. While the username can change for a Cognito User, this value should remain constant.
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/
I am reading about jwt. after couple of days I get the idea of this concept.
now i my question is about create jwt token per user witch privent others to use
others token.
for example scenario :
user A login to server and get its jwt token and server allow it to access the
resources.
now a third party come in and get jwt token of user A. now third party can use this token and use this token to use resources without login to system.
how can i create jwt token spatially for a uniqe user?
The JWT includes in the 'sub' field the user identifier. It may only be used to identify this user
Once issued, the token replaces the user's credentials, so you have to prevent a token can be stolen and also mitigate its effects :
Mainly use HTTPS to avoid Man-In-The-Middle
Set a short expiration time and rotate the tokens
Remove token at client side after logout
Use cookies to store and set HttpOnly to mitigate the risk of client side script accessing the protected cookie
Maintain a server blacklist for non-accepted tokens. For example when user log out, changes password or updates permissions, also when administrator revokes an account.
Use cookies to store and set HttpOnly to mitigate the risk of client side script accessing the protected cookie
Trying to implement a secure authentication method with JWT for an API which will be consumed for many clients including web (Single Page App), desktop, mobile I've came up with this system:
Client calls /auth/login with username and password set
After verifying server returns two tokens an auth_token and a refresh_token
Auth token is short lived 15 minutes and is used on every following API call
Refresh token is long lived maybe a 12 hrs to a week BUT is signed with a secret key in the format user_pass + long_string
After the token expires a called to /auth/renew is called
The auth token is sent to check how long it's expired (no longer than an hour)
The refresh token is sent as well and is validated using the user's password
If refresh token isn't expired and the auth token isn't expired for a long time, a new auth token is sent back
If the user's password has changed, the refresh token is invalid and the user is required to re-authenticate after their existing short lived auth token has expired
While there is a small window for the auth token to be expired and still be valid, and there is calls to the database made; is this an overall secure way to authenticate using JWT and to handle password changes and token refresh?
Don't try to implement your own authentication infrastructure. Chances you'll get a secure implementation are minimal and now you'll have to maintain all that code also.
Better use a authorization server from a reputable origin, like Thinktecture IdentityServer or Azure Active Directory and use standard libraries and protocols.
Some problems I see with your proposal:
if you do not sign the access token, what prevents me from changing
the claims inside?
if you need the user's password to validate the refresh token, you must store it in a way that you can retrieve it in clear text. Passwords should only be stored as a salted hash preventing you from getting to the clear text.
I'm working on an application that uses a token-based authentication system, where the user provides their username / password and receives a token in return (the token gets saved to the database as well). Then subsequent requests will include this token as a custom header and we can use this to identify the user. This all works fine.
Right now if the user doesn't login for 3 days, we expire the token. I was reading a little about refresh tokens in OAuth and I was wondering if I could somehow implement something similar. i.e. when providing the auth token, I also provide a refresh token which can be used later to request a new auth token. In terms of security though, it seems quite similar to just never expiring the user's auth token in the first place. Should I be sending additional information with the refresh token to validate the user?
In OAuth2, the resource server and authorization server are often not the same.
The refresh token is sent back to the client when the access token is issued and when the token is refreshed. The client needs to authenticate itself (using client id and client secret) to use the refresh token. The resource server never sees the refresh token.
Also, access tokens are not stored at the server side as they have a limited lifetime. Refresh tokens are stored and can therefore be revoked.