When using Token based authentication how should you handle multiple tokens/expiry - authentication

I'm reading/learning about token based authentication and I'm understanding it to a degree but the following questions have arisen.
If you log into site A you are given a token, this token will expire 24 hours after creating it.
You also visit Site B which calls an API from site A that allows you to give site B access to your information stored on site A. At this point a token is passed to site B to use for 24 hours.
Is this the same token? (So if you logged into Site A via site B, 23hrs59mins after logging into site A directly you would only have a minutes access to your info through site B before needing a new token?)
If its not the same token and you store your token in a table which links it to the user would you have multiple tokens per user?
Is it wise to to generate your token(s) as a random uniquely generated code and store it in the database along with the users log in details or is it better to create a token which takes a combination of the log in details and encrypts it (if so, how do you change the token each time).

Is this the same token?
Well that depends on Site A. Using the same token would mean that Site B has access to everything that your login on Site A allows you to access. If this didn't seem appropriate, then Site A would generate a new token with a more limited access. In this case, there would be multiple tokens per user.
So if you logged into Site A via site B, 23hrs59mins after logging into site A directly you would only have a minutes access to your info through site B before needing a new token?
If it expires 24 hours after creation (which you mentioned), then yes. Often the expiry would be updated upon every access though, so this might renew it for another 24 hours.
Personally, I would (and have) generate token as a random uniquely generated code. I think either would work though, and I'm sure you can find lots of opinions out there, like
here or here.

Related

Sliding Window with expiring JWT Refresh Token

I'm running a website + native apps that communicate via HTTPS with my backend. The following requirements must be fulfilled:
Sliding session on the website. That means if the user interacted with the website within the last xx Minutes, he must not be logged out
Remember me on the website. When this is checked, the user must not be logged out (or after a very long time)
The user must not be logged out on the app
Access can be revoked, either by the user (currently logged in) or specific events (password changes).
What I currently have is the following: A refresh token endpoint generates a JWT when password hash and username match in the database. Every refresh token has a jti that is stored in the database, as well as expiration (for DB cleanup only), device_id and a revoked flag.
Another endpoint can be hit with the refresh token, which returns a JWT access token. The access token is valid for 15 minutes. The access token cannot be revoked.
My problems arise with requirement 1. I do not want the user to reauthenticate when he's interacting with the website. This means I need the refresh token. However, the refresh token must only be valid for e.g. last user interaction + xx Minutes. I cannot extend the access token with every request, as there is no way to blacklist access tokens. This would mean that a leaked access token is like a master key forever (as long as you constantly hit the api in 15-minute intervals). But I also do not know what the expiration for the request token could be.
The second problem is (2) with incognito modes or multiple devices. Assuming the user opens 20 private tabs and uses remember me on all of them. Then I have to store 20 tokens in the database. I could, of course, set a limit for type "web" to say 5 and "app" to 3 and remove the oldest last accessed one from the database (and therefore invalidate it). But this would log him out on the "main" browser if he opens 5 private tabs somewhere. It would also limit the number of phones to e.g. 2.
Different PCs/laptops would also generate many refresh tokens of type web. How would I best identify the corresponding device so access can be revoked, but I also do not store hundreds of refresh tokens over the application's lifetime? Best would be one refresh token per device (windows+firefox, iPhoneA, iPhoneB, windows2+firefox). But identifying desktop PC's is super hard.
What it comes down to is:
How can I store refresh tokens in the DB so they are identifiable to the end-user (e.g. Whatsapp webs "Safari started in New York last used at xxx-xxx-xxx"
How do I avoid having hundreds of tokens per user in the DB (as refresh token basically never expire, and the user can open as many private tabs as he likes without logging off)
How can I implement sliding windows with the refresh/access token pattern? So no unlimited refresh token on the client-side, but also no logoff after the access token expires as long as there is any usage. I could have it in the session storage, but then it still clutters my database and shows to the user as "currently logged in" (which displays all refresh tokens) as it's basically still valid.
Sliding session on the website. That means if the user interacted with the website within the last xx Minutes, he must not be logged out
To solve this problem you can use a refresh token, i.e when the user login for the first time, the application will return a access token (JWT format), with an expiration date set to the amount that you want.
When the user will browse the application, your backend will return a X-Refresh-Token header valid for your xx amount of time (i.e you'll need to return this header for each backend call).
If the acess token is expired (the backend will read the access token used, and perform check on expiration date token field), the backend will return a 401 Unauthorized error,
and your client must call the authentication endpoint, providing the last refresh token stored, to issue a new access token.
With this implementation your requirement #1 is satisfied.
Remember me on the website. When this is checked, the user must not be logged out (or after a very long time)
To solve this one, you'll just need to generate a long lived access token (i.e with an expiration date set to the amount of time you want).
The user must not be logged out on the app
I don't understand this one
Access can be revoked, either by the user (currently logged in) or specific events (password changes).
This one is really tricky. Since backend is stateless, revoking access token is a really complex topic.
Hopefully a lot of pattern existing to solve this one, we just need to discuss about it.

Any way to generate a Auto Login/Token Authentication Link?

I have an account that I do referrals on and instead of having to make an entire landing page, and provide users with my referral link - I'll just have them purchase from my account.
Is there any way I could generate a link that will automatically log users in without me having to reveal my password?
You could definitely do this by using something like a JSON Web Token (JWT).
Basically, the way it works is like this:
On your server, you create a JWT that is signed with a secret key (some random string that only your server knows).
In your JWT, you include your user's account ID that you want the purchase to come from.
You email this JWT to the person in a link, something like https://mywebsite.com/order?token=<jwt-token-here>.
The user clicks that link.
Your web server takes the token out of the URL parameters, and ensures it is valid (that the signature is good).
Your web server then finds the account ID in the token, and retrieves that user account from your user database.
You then LOG that user in using cookies or whatever, and direct them to the purchase page fully logged in!
This is a pretty typical web flow for what you're trying to do, and is a totally fine way to do things like this. There are tons of JWT libraries out there that make this easy to do, so it shouldn't be very technically challenging.
The only other thing you should know in regards to creating JWTs, is that you can set an 'expiration' time. You should DEFINITELY do this, as you don't want someone to be able to log in using your token months in the future. The best way to do it would to likely be generate a token that lasts for 24 hours or so, then email THAT to the user. This way, it expires after one day.
Last thing to know: there are actually quite a few auth libraries that simplify this stuff. I'm the author of one, myself: express-stormpath. Depending on what you're trying to do, that might actually make your life wayyy easier as it can generate those tokens automatically, and handle session creations for ya.
Hope that helps!

What defines a client/user pair for Google API refresh tokens?

According to Google, there is a limit (currently 25) of how many refresh tokens can be given per client/user pair.
Just to clarify, this is referring to each user, right? Meaning that if I have a million users (!) each user could have 25 refresh tokens active? Or does this mean that I only 25 of the one million users are able to store refresh tokens on my server?
I am referring to the bottom of this page:
https://developers.google.com/analytics/devguides/config/mgmt/v3/mgmtAuthorization#helpme
Ok trying to figure out how to explain this:
When a user says yes they will allow your application to access there data you get a refresh token. You should save this refresh token some place so that you can use it next time. Then you will never have to ask the user to authenticate you again.
But if for some reason you ask the user again can I access your data you will get another refresh token. The first refresh token is still good you can still use that to access there data. You can do this up to 25 times before the first one gets deleted.
Here is a real life example of when this can be a problem:
I have an SSIS connection manager that asks the user if i can access there Google Analytics data. (works with a datareader but i digress). I have run into a problem where the user has to many packages authenticated. Basically they installed my application to many times in testing and the first one stopped working.
In the end i just recommended that they have a dedicated account for using my Task that way they would reduce the change of hitting the 25 authentications.

Can LinkedIn's access token renewal flow be performed on the server?

In the Facebook's Graph API, once we have initially authenticated the user, we can interact directly with the API (from the server) to obtain a long-lived page access token. This long-lived page access token never expires. (https://developers.facebook.com/docs/facebook-login/access-tokens/)
In reading LinkedIn's documentation, it appears that it is impossible to obtain an access token with an indefinite (non-expiring) access token. It seems that they expire every 60 days. However, these access tokens can be refreshed before the 60 days is up.
What isn't entirely clear from the documentation is whether or not the access token renewal can be performed on the server alone without the client's interaction. The language of the documentation suggests that the interaction of the client (browser) is required, but nothing is explicitly stated.
So, my question is, is it possible to renew a LinkedIn access token using the server alone, without the interaction of the client (browser)?
Relevant LinkedIn reference material: https://developer.linkedin.com/documents/handling-errors-invalid-tokens
As it turns out, the access tokens of linkedin can not be refreshed without having linkedin user logging in to linkedin. Please refer to the first comment here by LinkedIn employee which clearly states a note that "this refresh will only work if the user is still logged into LinkedIn (authenticated) and the current access token isn't expired. Otherwise, the user will be presented with the login dialog again."
I guess that is now a major issue for those who were previously storing the linkedin access tokens to database for later use.
I am mentioning few links here which refer to the issue with refreshing linkedin oauth2 tokens (hope this makes it clear for everyone who is struggling with the same issue):
1) This refresh will only work if the user is still logged into LinkedIn (authenticated) and the
current access token isn't expired. Otherwise, the user will be presented with the login
dialog again.
2) There is no way to refresh the token using the old authentication token/secret. User
needs to log into linkedin in order for you to refresh the tokens. We use this flow as it
protects our members and their data in the best possible manner.
3) Refreshing an access token is very simple and can happen without an authorization
dialog appearing for the user. In other words, it's a seamless process that doesn't affect
your application's user experience. Simply have your application go through the
authorization flow in order to fetch a new access token with an additional 60 day life span. When the following conditions exist:
-User is still logged into Linkedin.com
-The current access token isn't expired (within the 60 life span)
We will automatically redirect the user back to your redirect_uri without requiring them to reauthorize your application. If they don't exist, we'll prompt them to login and then redirect
them.
4) We have also standardized the duration of the authorization tokens. Previously, members
could choose to grant tokens that were as short as one day or as long as forever. Now all
tokens are 60 days in length, with the ability for you to extend them in a series of rolling 60 day increments whenever the member comes back to your application. To prevent a bad user experience in your application, be sure to proactively refresh tokens and elegantly route any expired tokens through a refresh flow.
5) As long as the user is logged into LinkedIn and their current access token hasn't expired, you can fetch an access token with a 60 day lifespan the next time the user comes to your application.
I had the same question and the LinkedIn docs and forum posts are confusing, but I'm pretty sure now that it's not possible to do it programmatically without user intervention (i.e. the user needs to login to your app via LinkedIn auth to refresh the token).

Best way to seamlessly & silently authenticate with a second webapp while logged in to a first?

Third party app (A) needs to link users to our app (B) and log them in behind the scenes.
Both apps work independently with their own auth systems. Users share a common unique ID, but have different authentication tokens (username/password/key etc) at each app.
The two complicating factors are as follows:
One app B user may associate with two app A users (e.g. both accounts at app B would redirect and login to the same app A account)
The app B user may not actually have any existing auth tokens, only their personal record and user ID, but we still want to be able to log them in if they are coming from app A.
My first thoughts were OAuth - but I don't think it will work as some users don't have app B accounts and thus won't be able to log in to grant app A access (see point 2 above).
The simplest way I have come up with is:
Each app has a pre-shared key e.g. "LOLS"
Common hash algo generates indepentent identical tokens e.g. hash(PSK + UID)
App B stores hashed tokens for each user
App A sends POST with UID and hashed token to App B, which uses it to identify and auth against a user
The problem with this is that it's hideously insecure. Anyone with knowledge of the pre-shared key (any system admin) and a user's ID (once again, any system admin) would be able to authenticate as ANY user, which is unacceptable.
Does anyone have any solutions? I'd prefer existing standards but am open to customised implementations. We can't really do much to app B other than to get them to use whatever API we provide.
I've faced situation similar to this many times. There have been a variety of solutions we've explored, here's one of them.
You produce a webservice for them to call. This could be something you lock down however you like, including by limiting access to their IP address at the firewall. They post the UID to your webservice, which inserts into a table on your end and hands back some sort of random token (we randomly generated a guid). Your table associates the token with the UID (in plaintext) they sent and a datestamp.
Their application sends the random token to you instead of the UID, you use it to look up the UID, and use the timestamp to make sure the random tokens are expired after a minute or so. Even if someone looks through your table somehow to get the list of UID's recently attempted, it doesn't let them authenticate unless they can pull it off real fast!