Telling ember-simple-auth that the user is now invalidated/logged-out, inside a custom authenticator - ember-simple-auth

From a custom authenticator; is there a way of telling ember-simple-auth that a user is now invalidated/logged-out?
Some background: I am building an authenticator with token refresh, similar to oauth2-password-grant. While I haven't experimented with the oauth2 authenticator directly, it seems we face the same issue: if the token refresh fails to update, for example due to an expired token, the user remains logged in as far as ember-simple-auth is concerned.
EDIT: (to address comments for further clarification)
Ah, I use JWTs and the server does not maintain sessions; the server has no idea who is logged in nor does it matter. The authentication is done via username/password after which the server issues a JWT token along with a time when it expires. To prolong the expiry time, you may refresh this token (as long as its valid) and get a new token with an updated expiry time. All is well and good except that ember-simple-auth does keep track of whether the user is logged in, as it should. However, if a call to refresh the token fails the user should be considered logged out (the token is invalid/expired and any attempts to make a call to an API that requires authentication will fail).
My question is how do I tell ember-simple-auth that this user has been logged out.

Related

A few questions about json web tokens

I have recently started using json web tokens and I have a few unanswered questions
what would happen if a users token expires while they are online? would they be forced to log in again when they request the next protected route? and if so it feels like there has to be a way around this so that the user does not randomly get logged out
how would you log someone out before the jwts expiration date considering the client holds all the info
any clarification on those 2 questions would be appreciated
what would happen if a users token expires while they are online? would they be forced to log in again when they request the next protected route? and if so it feels like there has to be a way around this so that the user does not randomly get logged out
When you make a request in a webapp, you need to pull in the available token. So the answer is "what does your app do?". There are lots of things you can do, such as making the request with the invalid token, or no token at all. But obviously that's not really a good idea. The best strategy is to:
Before every API call needing a token, check if the current token is valid
If the token isn't valid ask your auth provider to get a new token. This is known as silent authentication. How the provider handles this is totally up to them, usually they have a HttpOnly cookie saved for a secure domain, and return a new JWT.
If the silent auth fails, then the provider will tell you to log the user in.
At this point the best course of action is to redirect to the user to the auth provider using the same "login strategy" they previously used, to get a new "session" and a new "token".
how would you log someone out before the jwts expiration date considering the client holds all the info
Logging out is completely separate from token expiration. Logging out from a user standpoint is:
Tell the auth provider to remove the HttpOnly secure cookie
Delete the JWT in the browser
Change the UI to display the user as no longer logged in.
But that doesn't expire the token. The token will always be valid until the exp date. If you want to also prevent that token being used as if it was valid, you must deny-list the token using your AuthZ IAM as a service. For instance, if you were using Authress to manage access control, a DELETE https://api.authress.io/v1/users/{userId}/tokens/{tokenId} would cause subsequent checks using that token to return Forbidden. However, I will stress, the token is still valid, but you've taken the step to mark it as Deny-listed.
would they be forced to log in again when they request the next protected route?
If there is no other information that associates the session with the logged-in user (for example, there aren't any cookies or other tokens the server can use), yes.
Yeah, it's not very user-friendly, and JWTs often have a short expiry time. A common solution to this issue is to provide a refresh token as well, which could be stored in a HttpOnly cookie:
A refresh token has 2 properties:
It can be used to make an API call (say, /refresh_token) to fetch a new JWT token before the previous JWT expires.
It can be safely persisted across sessions on the client!
This way, the client can always have a valid JWT at any one time; they won't have to log back in, or logout and then log back in.
how would you log someone out before the jwts expiration date considering the client holds all the info
You can implement logic on the server to somehow blacklist or ignore the JWT from a particular user until they log in again. For example, after parsing the JWT, you could check to see whether the server considers the token to still be usable or not. If not, return a 401 error.

How to handle JWT refresh token in a mobile app environment

I am implementing JWT inside a client mobile app with a separate back-end server, and I am looking for an optimum way to use refresh tokens without too much server calls and while keeping a good user experience.
I am new to implementing such a mechanism, and I am confused about many things, so what I am really looking for is a solid conceptual solution to secure the user access to the app, and keep him at the same time logged in indefinitely.
Any correction or suggestion would be most welcome:
Why refresh tokens anyway?
Using a JWT access token alone might compromise the user security: If an attacker holds the access token, he might run feature requests whenever he wants. Even when applying an expiry date to the access token, if the server issues a new access token whenever the old one expires, the attacker will receive this new access token using his old one, and keep accessing the user features.
Refresh tokens stop the attacker once the user regains access to his account using his login/password: When the user uses the app and the server detects that his refresh token is invalid, he will be logged out and a new refresh token and access token are issued after he's logged in with his credentials. The attacker won't be able then to use the old tokens.
My first question would be:
I. Regardless of how the attacker gets hold of the tokens from the user environment, would he be able to use them indefinitely as long as the user is still inactive and isn't logged in again with his credentials to create new tokens?
What about when the tokens are refreshed asynchronously?
Let's imagine a scenario where the user is inside the app, and at least two server calls are run asynchronously:
"Service1" makes a server call with an expired accessToken1 and a refreshToken1, and the server responds by sending a new accessToken2 and refreshToken2
Before receiving the "Service1" response, "Service2" makes an other server call with accessToken1 and refreshToken1, the server compares refreshToken1 to the previously saved refreshToken2 and finds them different. It responds then with an Invalid refresh token response, and this causes the user to be logged out!
To avoid this problem and keep the user logged in, there could be a centralized authentication service that checks first the validity of the tokens before any server call is made. Which means that any call won't be executed unless the authentication service is idle, or wait for the new tokens if it's already loading.
My second question here is:
II. Having such a service to avoid the asynchronous refresh token problem means more round trips to the server, which might prove costly. Is there a better solution?
There are some steps to login / revoke access to an api:
When you do log in, send 2 tokens (Access token, Refresh token) in response to the client.
The access token will have less expiry time and Refresh will have long expiry time.
The client (Front end) will store refresh token in his local storage and access token in cookies.
The client will use an access token for calling APIs. But when it expires, pick the refresh token from local storage and call auth server API to get the new token.
Your auth server will have an API exposed which will accept refresh token and checks for its validity and return a new access token.
Once the refresh token is expired, the User will be logged out.
JSON Web Tokens are a good way of securely transmitting information between parties. Because JWTs can be signed—for example, using public/private key pairs—you can be sure the senders are who they say they are. Additionally, as the signature is calculated using the header and the payload, you can also verify that the content hasn't been tampered with.
What about when the tokens are refreshed asynchronously?
that supposed be done with a single request to an endpoint, so there is a single accessToken
Having such a service to avoid the asynchronous refresh token problem means more round trips to the server, which might prove costly. Is there a better solution?
i think that's the best & secure solution for mobile and serverless apps, token are like ssh keys must be kept secure all the time :)
for more information check [question]: JWT refresh token flow
Here's the official introduction to JWT

How should I handle RESTful authentication while using JWT tokens?

I have read many articles and viewed many videos but there are a lot of contradictions. I try to avoid any external libraries and build the system from scratch, I have read about oAuth 2 but it is more confusing.
This is the flow that I think is ok untill now:
User fills a form using email and password and submits it.
Server verifies the password if it matches and responds back with a httponly cookie with a signed jwt token that expires in like 10
minutes. (I know I have to protect it against csrf attacks)
User gets logged in and every new request he is making to the server he will send the cookie in the header automatically and the
server will verify the token.
Everything is fine but I have encountered some issues and have some questions:
I want the user to stay logged in even after opening a new session so there is no need to login after the token expired or when he closes the browser.
What should happen if the access token expired?
There should be a refresh token attached to the user in database that gets added when the user logs in with an expiration of ex 7 days, then the server will respond with a cookie containing that refresh token?
On the new request while access token is expired,the user will send the refresh cookie to the server, if it matches the user database refresh token,server will respond with a separate cookie that will renew the access token?
If there is a refresh token where should you store it and what format? (cookie,database or where?)
Should I keep the user logged in based on this refresh token cookie?If is it httponly I can't read it and set the state that user is logged in. How should I do it?
I heard about that revoking the jwt token is problematic. How would you fix it?
How would you do this whole thing?Please explain the workflow, I try to avoid localstorage,as I read everywhere that is not safe for sensitive data.
I have implemented and deployed to production systems that do exactly the kinds of things that you are asking about here so I think that I am qualified to provide you with some guidance to solve your particular issues and answer your questions. The flow that you have listed above in the numbered list is definitely the correct path so far. I do understand your confusion going forward from there because there are many different options for how to approach this problem.
In addition to providing a login route that returns a new JWT to the client when the user submits a login form to the server, I would recommend also implementing a token refresh route that accepts a still valid JWT that was received from the initial login process and returns a new JWT with an updated expiration time. The logic for this new token refresh route should first verify that the provided JWT is still valid by matching it with a user in the database. Then, it should generate a new token using the same JWT generation logic as the login route logic. Then, the application should overwrite the access token data in the database for the user replacing the old access token with the newly generated access token. It is not necessary to keep an old access token in the database once it is no longer valid, which is why I suggest simply overwriting it with a new one. Once all of that is finished and successful, you can return the new JWT to the client and then the client should now use that new JWT when making any additional authenticated calls to the server to maintain an authenticated interaction with the server. This logic flow would keep the user logged in, because the client would have a valid JWT before calling the refresh logic and it would have a valid JWT after calling the refresh logic. The user should only be recognized as not logged in and not authenticated if they are no longer able to provide a valid access token that is associated with a user in the database.
As far as cookies go, whichever method that you use for maintaining the cookies on your client should be used for setting the refreshed access token as it is for setting the initial access token that you receive on login. If the server finds that an access token is no longer valid at some point in the future, if for example your client is not used after login until some time after the access token has expired, then the client should recognize a server response indicating that this is the case and present the user with the login flow on the client again so that a new access token can be acquired and stored in a cookie on the client.
I would not worry about revoking JWTs and instead just let them expire if they do and initiate a new login flow if it is found that a JWT has expired. Also, instead of using local storage I would suggest using session storage to store your JWT so that you have it for the duration of your user's session on the website and it is removed as soon as the browser has been closed. This will prevent the JWT from persisting beyond the session and should assuage your fears about saving sensitive data in the session storage. Also, when generating your JWT, you should also make a point of not storing any sensitive data in it because JWTs are easily reverse-engineered. This can also prevent any sort of sensitive data from being exposed on the client.
EDIT:
The key thing to remember when developing your server API is that you should have two different classes of endpoints. One set should be unauthenticated and one set should be authenticated.
The authenticated set of endpoints would not require an access token to be included in the request. An example of this class of endpoint would be your login endpoint, which does not require an access token because it actually generates an access token for you to use later on. Any other endpoint that does not expose sensitive or important information could be included in this class of endpoints.
The unauthenticated set of endpoints would require an access token to be included in the request, and if no access token or an invalid access token is detected the endpoint would respond with a 401 HTTP response code (indicating an unauthorized request). An example of this class of endpoint would be an endpoint that allows a user to update their personal information. Obviously, a user cannot update their own information if they cannot provide credentials to prove that they are the user whose information they are attempting to update. If the client receives a response with a 401 response code, that would be the signal that the client would need in order to tell the user to re-login so that a new valid access token can be retrieved. This possibility can be avoided on the client if the client is programmed to periodically check the expiration of the JWT that is currently being held on the client and initiate an access token refresh, but obviously you should still have logic in place to detect and respond to a 401 response code so that the client user flow is managed properly.

App authentication and authorization with JWT

I was going through Oauth2 docs and thought it was kind of permissive security wise, so i tried to implement JWT tokens with a special scheme like in the picture for a mobile app communicating with a web API.
Notes : i didnt like Oauth2 refresh tokens idea as they might get stolen and allow parallel usage (by legit and malicious users) unless you implement theft detection by rotating them (refreshing refresh token upon each request) in this case why use them at all ?
How the auth flow works :
A user logs in with credentials gets a jwt of 20 minutes lifetime.
Upon expiry the jwt gets refreshed by hitting the db checking if it's blacklisted (relogin) and if not check if it was used to generate a new token.
If it was never used to refresh it is accepted and used to issue a low grade access token.
If the token was used before, or had different client+device+user than its parent offer a credential check (password or lockscreen code)
If passed, this check issues a new first grade token that blacklists all its parents and children on the db, its like a new first user login.
If lockscreen fails the user is presented with login screen.
The questions are :
What are possible security holes ? (I found two use cases : stolen valid access token lasts 20 minutes same issue as Oauth tokens. No gain no loss here. And stolen sleeping token : user not logged in for say 7 days, token gets stolen and used until user logs in again or token chain revoqued after 3months of persistance - our policy - and this theft has small chances since token has to be intercepted at the last request the user makes on the app , slimmer than stealing an Oauth2 refresh token )
What are user experience problems an attaker can cause on the app while on this scheme ?
OAuth2 refresh tokens are not meant to be used by mobile clients. Using refresh tokens requires client credentials, which cannot be stored securely in a mobile application.
Refresh tokens are used from confidentials clients (server side web applications for example). They are often renewed when used (server sends back new access and new refresh token). In contrast to access tokens, the refresh token is only sent to the authorization server, not the resource (API) server.
Regarding your auth flow. Step 2 is the weak link IMO. You allow the client to use an expired token to generate a new access token. So if I find your phone and access the device, it will allow me to get a fresh access token and impersonate you.
You could force the client to refresh the token every say 15 min., but then you have to define what happens if the app gets closed or the device is turned off? Is it okay to re-authenticate the user again?

Google Oauth2 Contacts API returns Invalid token: Stateless token expired after an hour

What's wrong with my setup?
I am using django-allauth for social signup and recently i added contacts to it's scope. Things are working fine. It now asks for permission to manage contacts and I am able to get contact details of users through the API.
But once i make a request to get contacts of a user(I am not saving any refresh token or accss token at that time), after an hour when i make the request again with same token, It shows this error "Invalid token: Stateless token expired".
However I can still login into the website and the token does not change. However when I logout and login again the token changes and i can again get the contacts using that token for one hour.
What's the issue? What am I missing?
See, when you are logging into the website, you are probably using cookies. So basically you might be using the same session and actually the api is not called.
The time when you are logging in incognito mode or in a diffrent browser, that cookie cannot be used, so this time api is called. For this reason, the token is getting changed.
For example, if after few users have signed up with google, you change the scope of the app, what happens is, if the user has enabled cookies and it has not expired, when he visits your site, it simply logs him in. It does not asks for permissions (that you added recently to scope). But when he logs out and logs in again, then it asks for the additional permission and th token also gets changed.
What you should do is, you should go through th codes of django-allauth and clear it out how they are using the token. You must also know that for getting refresh token, you must have offline access enabled in your configuration.

Resources