Using JWT(?) to authenticate users for an electron app with persistence - rest

I'm looking to secure my electron desktop app with user credentials (username + password), but I'm having a hard time finding the right technology to use. Requirements:
Number of activations can be determined (e.g. x copies of the app can be activated at any given time)
The user can deactivate/revoke access to all active instances remotely.
The activated copy will not need to be re-authenticated manually indefinitely if the user does not log out remotely.
For example, the user can authenticate themself, not use the desktop app for a long time then they aren't expected to log in again when they re-open it.
I am currently looking at JWT as it somewhat satisifes 2. However i've read that it's advised that the tokens not be saved in a database, so if I need to blacklist tokens, the blacklist would be a forever growing collection which is not ideal (unless you had a cronjob to remove expired tokens)
I'm not sure which solution would be ideal here that would meet the requirements.

Use JWT. Create two tokens: access token and refresh token. The access token will be short-lived (minutes), the refresh token will be long-lived (hours, days, weeks). Follow the best practice in token handling (Access token and Refresh token best practices ? How to implement Access & Refresh Tokens). Also comply with the OWASP ASVS V3 requirements regarding session handling
You actually do want the refresh token to expire. Else you would need to hold them in some blacklist forever. Forever is pretty long. Having to delete the expired logs from storage is a small price to pay for this level of flexibility you are willing to implement.
Make the refresh token hold two additional attributes:
Unique identifier
Human readable name
so the user knows which tokens he is invalidating. You would put into the blacklist the unique identifier and the expiration date.
You can identify how many copies of the application are being used based on the active access token count.

Related

How to prevent log out users when changing JWT secret?

I am using a JWT token implementation of this https://jwt-auth.readthedocs.io/en/develop/quick-start/
I need to update the secret key and is there a way to update it without logging out every user? I presume it's not possible to reuse the old token once my secret key is changed. So all my users will be logged off and need to log in again. Is there any way to go around this?
If not, if for security reason, I need to update the secret monthly, that will be pretty troublesome to ask my user to re-login monthly.
Thanks!
If you change your keys it's correct to invalidate all the tokens signed with the old ones as they are to be considered expired.
It's a good practice to let the token expire as well after a certain amount of time. Usually you implement a mechanism based on two tokens, access_token with an expiration of 1h (usually) and a refresh_token with a longer expiration (usually 24h). The second one is used to renew the first one. When the second one expires, the user has to be considered logged out.
What you need is to implement a refresh token mechanism. You can implement it from scratch, for learning purposes, or you could just implement OAuth 2.0 protocol, since it's a flow that it already supports. There are lots of libraries both for server side and client side implementations
https://oauth.net/

JWT and one-time tokens?

I'm in the process of rolling my own JWT token auth, however, I would really like it to be a one time-token – so once it's used, the server generates a new token and the client will have to use that token during the next request/call.
However, it has come to my understanding that JWT is supposed to be 'stateless' – but with the approach of a one time token, I guess I would need to somehow store the valid tokens, since the token will be refreshed once it's used. Or is there any way to avoid storing a value on the server, and still be able to create one-time tokens?
The two main reasons for why I don't want to store any value is first of all scalability (sure, I could have cache-server inbetween to store the values, but it would be nice if that wasn't required), secondly, JWT is supposed to be stateless from my understanding, which it wouldn't be if I need to store a value on the server to be able to validate the token.
Any ideas?
Use the user's current password's hash for signing the JWT token, in this way all tokens generated before a successful password change would get invalidated the next time. I got the idea from here https://www.jbspeakr.cc/howto-single-use-jwt/.
Solutions exist, of course.
As with any distributed system (you mentioned scalability) you have to choose between availability and consistence.
You choose availability. In this case you could maintain a list of already-used tokens that you replicate in a eventually consistent manner between all the endpoints. For example when a token is used the respective endpoint send that token to the other endpoints in the backgound. There is however a (short) time frame when that token can be used a second time by another endpoint until that endpoint is updated.
You choose consistency (you won't allow a token to be used multiple times whatsoever). In this case you use a central database with already-used tokens and you check that database everytime you need to perform an action. Scalability? You could use sharding on the token and have n databases, each one being responsible for a tokens subset.
It depends on your business what solution fits best.
Not really no, a JWT token is valid if it hasn't expired and the signature is correct, commonly people will keep a DB of blacklisted tokens which are usually ones where people have logged out etc.
The only sensible way I can think of is give them a short expiry time and maintain a list of tokens that have already been used, you'd then periodically remove the ones that subsequently expire from the DB.
There are actually some DB's that have a TTL on records (dynamoDB, mongodb) so you'd just put the tokens in and set a TTL for when the token expires.
Update 2022
Just to be clear JWT tokens AREN'T stateless they have claims that, as long as they're signed by the right private key - give you a stateful piece of data that can be reissued by your API to reflect the current state of the user.
You'd just need to handle token re-issue on the consumer.
Like others have mentioned, it depends on your business case. Password resets links can be like mentioned on https://www.jbspeakr.cc/howto-single-use-jwt/.
If you have the Single-Use & Single-Auth scenario, where you might want to invalidate any previously used and unused token, you can store a single nonce and update it on every new token request and also when its used.

Tracking multiple logins from the same user with Stormpath

I'm working on a mobile application that uses Stormpath on the server side for authentication and authorization. I need to support the same user signing in on more than one device, but I want to be able to keep track of it and limit it if I want to.
My application currently uses Stormpath to sign in the user using email/password or MDN/password and upon successful login returns a JWT token to use for API access to the server.
I'm thinking of the following approach:
Keep a list of sessions in the user's account. Every time the user signs in, a new entry is added with the device_id and the JWT provided. When the user signs off, the entry is removed or marked inactive.
When a user tries to sign in on another device, if I want to restrict to only one active device, I would set the other entry to disabled and expire the JWT so the application can detect it and require login again.
If I wanted to restrict the user to a maximum of n sessions, I could just count the entries and force the user to sign off on one of the other sessions before allowing her/him to sign in on the new device
Is this a good approach? Is there a better way to do it? What are the issues with this method?
I work at Stormpath on the mobile SDKs. You can use the access / refresh token feature that we have to accomplish this.
Every time the user signs in, an access and refresh token are created. When the user signs off, the refresh token is deleted, as well as the access token.
When a user tries to sign in on another device, if you want to restrict to only one active device, you can delete all of the other access & refresh tokens.
If you wanted to restrict the user to a maximum of n sessions, I could just count the entries and force the user to delete one of the refresh tokens before allowing her/him to sign in on the new device. You would then go through the access tokens, and delete ones with a matching "rti" (refresh token ID)
Several notes about implementing this:
If you're using a Stormpath Framework integration, the default is to verify an access token locally (instead of sending it to Stormpath to validate). This is because they have a signature that can be validated by the SDK. However, to log out a user, you'll either have to set this to remote validation, or use a short access token life (and use the refresh tokens to control each "session")
Refresh tokens can't store "customData", so you'll have to maintain metadata about the refresh token in either the account's customData, or in your own database.
Alternatively, you could "create" API Keys for each user, and use that instead of sessions for each user. You can use the API Key name or description attributes to keep track of where the user signed in from / etc.

Is "logout" useless on a REST API?

Considering that, by definition, a REST API is stateless: is the "logout" operation useless?
I mean, I'm creating a REST API using encrypted JWT. Each token has an expiration time of, let's say, 60 minutes. If I save on a database table the last tokens generated by the API, the "logout" would be done deleting them from the table of valid tokens. But, if I do that, I understand that the API will cease to be stateless, right?
So, I understand that I shouldn't do that. The only solution that I'm thinking is make the JWT expiration time shorter, to 5 minutes, don't implement a "logout" operation and just let the tokens expire.
Is this the correct approach?
I mean, I'm creating a REST API using encrypted JWT
The JSON Web Token (JWT) tokens encodes all the data about the grant into the token itself. The most important advantage of this approach is that you do not need a backend store for token storage at all. One disadvantage is that you can't easily revoke an access token, so they normally are granted with short expiry and the revocation is handled at the refresh token. Another disadvantage is that the tokens can get quite large if you are storing a lot of user credential information in them. So if:
If I save on a database table the last tokens generated by the API,
the "logout" would be done deleting them from the table of valid
tokens
Then you would lose the most important advantage of using JWT and also, still have all those disadvantages, which seems unreasonable to me.
So, I understand that I shouldn't do that. The only solution that I'm
thinking is make the JWT expiration time shorter, to 5 minutes, don't
implement a "logout" operation and just let the tokens expire.
Is this the correct approach?
In my opinion, if you're planning to use JWT, YES! it's better to rely on the token expiration. For more details on this approach you can check this question out.
Is “logout” useless on a REST API?
Regardless of the fact that you're using JWT and similar to any other decent questions on computer science, the answer would be It Depends. The most important advantage of Statelessness is that your API would be more scalable. If you choose this path, probably, every request on your API should be authenticated, since you may need to search a backend store for the given token or decode a JWT token. So, in this case you may have some performance cost on a single node but in a big picture, you would still have the scalability. I guess what i'm trying to say is, if you do not need that scalability, you're better off to choose a Stateful approach. Otherwise, pure REST principles is the way to go.
Automatic token expiry is a separate concern from an explicit "log out" mechanism and, as such, they are both perfectly valid actions regardless of whether your API is ReSTful or not.
When a user logs out they are making a conscious decision to invalidate their access token - for example, if they're using a public computer or borrowing someone else's device temporarily.
Automated expiry is used to ensure that the user must revalidate, in some fashion, on a regular basis. This is good for server-side security.
Access tokens are not about sharing session state between client and server - it's entirely possible to implement an access token system without shared state and the token itself doesn't implement session state, it's only used to verify that the user is who they claim to be. As such, access tokens are not really anything to do with the statefulness of the API.
I think it depends on the behavior that you want for your application, and how secure you need it to be. Do you really need to invalidate the token?
For instance, you could just remove your token from your frontend (browser or app). In theory, it is the only place that stores that particular token. If the token is compromised, it will still be valid until it expires, though.
If you really need to invalidate it server side, a common approach would be to create a blacklist with the token, and clear the expired entries from time to time.
But what if you need your application to accept just one token for each user, like in a bank app that you can only be logged in one device at time? For that purpose the blacklist won't do the job, so you will need to store a single token for each user and check if the passed token is the same. At logout, you would just clear that unique entry. Or you may just use sessions.
So, it is not useless, It just depends on your application.
I would argue that your API is already stateful just by the sheer fact that you have a token around. I also wouldn't get too hung up on REST purity, meaning that everything has to be stateless come hell or high water.
Put simply, if your application requires login, then you need a way to logout. You can't implement a short expiry because that's just going to be a really annoying experience to consumers of the API. And you can't just have no logout at all, because thats a potential security flaw.
I have a similar REST API that I support and I implemented a logout endpoint that is a DELETE call. It simply deletes the token information on the server side and clears any type of authentication for the logged in user.
TL;DR
No, a logout is not useless in a REST API. In fact, for APIs that require authentication, it is more or less a necessity.
With a short expiration time on the token I would think for most applications deleting the token from the client on logout would be a good solution. Anything more would rely on the server and no longer be stateless.
The good solution here would be to delete the token from the user.
So typically when you log in, you will get back a token from the server and store it in localStorage or sessionStorage (depending on the user wanting to be logged in after closing the tab) in the browser, and then send the token from there in the headers with any request that you make to your api.
Then if the user logs out, you don't even contact the api (you don't make any requests to your server), you just clear the sessionStorage or localStorage, use the command localStorage.clear() or sessionStorage.clear() , and then if the user will want to send more requests, he'll have to login again in order to get another token.
One drawback to this approach is, that if a virus, for example gets the token from the local or session Storage before the user logs out then, it will still be able to send requests as you, as the token will still be valid.
One solution to that would be to create a token blacklist in the database, and store the token there if the user logs out, until the token expiration time. However, every time the user would request something, the database would have to be consulted to check if his token is blacklisted, lengthening the process, and making your API stateful.
You can generate a new token that it already expired i.e. expiration is 1sec. and pass it to the user. Any upcoming request will be invalid. This is not optimal solution though..

OAuth REST access_token and instance_url expiry time?

I am working with Oauth2.0. In that i could able get the access_token and instance_url. Is there any expiry time for these two.
Can I store them and use it for all my REST calls without getting the new access_token and the instance_url. Is it possible for me to use it for long hours or even days.
The access token is only valid for the length of a session (as defined in the Salesforce Org's settings — I believe the longest this can be is 8 hours without activity), as it's actually a session ID, that said, you should also be given a refresh token. The refresh token has a much longer lifetime and can be used to authenticate the user once the session has expired, without them having to enter any credentials — this allows you to do it in the background without them even having to concern themselves with the login process.
model metrics do a good job of explaining the token flow here.