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.
I'm making an application that among it's task will use the REST API in KeyVault. I already have functions written that will query the KeyVault for the secret without an issue.
I also have functions written to request an OAuth token from AAD, following the documentation on this link:
https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-code
What I'm not sure about is; Since the application is going to be installed on hundreds of computers when a token expires and the function to refresh the token is called chances are that more than one PC is going to make the POST. What is the best practice for a scenario like this? Should i just configure an exponential back off after a refresh token function is called?
The app installed on the machines will not have the ability to talk to each other.
The only way I can think to do this is to use a logic app as the broker but that would defeat the purpose of the KeyVault.
The document you provided is using the code grant flow to acquire the access token. This flow requires users to login to acquire the token. And did you mean all the PC you installed will use the same account to acquire the token?
If yes, you can design you own token cache. For example, you can using an SQL server to store the cache. Then the app will search the token/refresh token in the token cache before it sends the token request. And if the token is expired, you can refresh it. In this scenario, all PC will share the same access token since they are sign-in with same account.
If not, you need to refresh for the every PC when the access token is expired. Because the access token is different from each user.
So after some testing and verifying with MS it looks like the documentation on the link is outdated. When a token is generated it has a lifetime of 8 hours (this is configurable) so every time I make a request to /token a new token is handed out, since the time window is small I don't need to worry about token refreshes since PCs won't be on for over 8 hours.
The other part of this is that i built a function to test the validity of the existing token, before i query any azure service i test the token validity, if it fails a new token is requested. Since the token lifetime windows are short and each machine gets it's own token (i thought all machines were getting the same token, code error on my part) this is a non-issue anymore
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..
Since LinkedIn discontinued their network updates RSS feeds, I haven't been able to find any "simple" mechanism to gain access to update feeds w/o going through the oauth process requiring the user to authenticate first. The few examples I've seen posted here all assume you've obtained the auth token first. Is that even possible?
In case anyone else inquires: https://developer.linkedin.com/support/faq
If your application requires you to make API calls in an automated way
- without user interaction, you need to bootstrap the first access token request by manually signing in, and then ensure that your
application refreshes the token automatically prior to expiry to avoid
the need for additional human authentication.
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.