API desing – Is it ok to fetch user's data from auth token? - authentication

Let's consider this use case:
1) I call my API login endpoint with username and password and get my Auth token that I add to every consecutive request to the header as Authorization: Bearer <token>.
2) I call /current-user endpoint with no params, only with Authorization header. Server authorizes user using token and gets user's id from that token. Then he finds the user by id in database and returns it's data.
My question is, whether this approach isn't insecure. I'm wondering, what if I was an attacker and was calling /current-user endpoint using randomly generated tokens. Once I occasionally matched real token, the server would return me other user's data.
Isn't it necessary to store user id on client along with token and call requests using both? Eg. /user?id=<stored user id> with Authorization header and get rid of /current-user endpoint? After that some kind of ACL on server would determine, whether used token has allowed access to user with passed user id.
(I also found there are JWT tokens but I see the same problem there. As an attacker I would somehow manage to guess other user's token and server would return me his data)

For security purposes, it is normally assumed that the user id is known to the attacker anyway. For example, if the attacker already has or knows a legitimate account, she might be able to guess how other user ids are assigned.
Also, if your token is long enough and totally random, it doesn't really make any difference.
Look at it this way: let's say your token has length n, your user id has length m. Without the user id, the attacker has to guess n characters, with it included she has to guess n+m characters. If your n is high enough, you don't need those extra characters. Keep in mind that the effective length of the user id might be much shorter than its apparent length if your user ids aren't completely random, so the m added might actually be really small.

Is it possible for you to use digitally signed tokens? You could basically encrypt the token with the client's (or user's) private key and then encrypt the package along with plaintext userid again with the server's public key. That way only the server can decrypt the package and once decrypted, it knows who the user is. It can then use the public key associated with that userid to decrypt to the package and get the token.
As you havent provided much info on the application and the speed of authentication required or technologies you are using, it is difficult to provide any more info.

Related

In token-based authentication, how does the application server know which tokens are valid?

I'm trying to understand cookie vs token-based authentication. I get the basics - cookies have to be stored in the server (as well as the client) to be verified each time, whereas tokens only have to be stored on the client-side. The server simply decodes any incoming tokens and verifies the request.
What I don't understand is, how does the server know whether any decoded token is valid, if a list of valid tokens isn't being stored anywhere in the server?
https://dzone.com/articles/cookies-vs-tokens-the-definitive-guide
User enters their login credentials.
Server verifies the credentials are correct and returns a signed token.
This token is stored client-side, most commonly in local storage - but can be stored in session storage or a cookie as well.
Subsequent requests to the server include this token as an additional Authorization header or through one of the other methods mentioned above.
The server decodes the JWT and if the token is valid processes the request.
Once a user logs out, the token is destroyed client-side, no interaction with the server is necessary.
To be specific - I'd like to know how #5 works. Thank you.
A full answer to your question would be very long, but here is my attempt at a brief one. The server also happens to be the entity which issues the JWT in the first place. As such, it possesses a key which it used to sign each outgoing JWT. As a result of this, when the server receives an incoming JWT, it first tries to open/unlock that JWT using its private key. If the JWT were tampered with in any way, the server might not be able to open it properly, and it would result in an exception. As an example of one sanity check the server would perform against an incoming JWT, it would observe the checksum of the JWT, would not pass in the case of tampering.
Once the server has opened the JWT and deemed it to be valid, the next thing it would likely check would be the exp claim, one of possibly several claims which are contained within the JWT. The exp, or expiry, claim, records for how long the JWT is valid. Should a user present a stale JWT, the server would immediately reject the JWT as being invalid.
So far, we have been discussing checks the server may perform using no state, that is, relying only on the state contained within the JWT itself. In reality, most of the time the server would in fact be storing some state of its own. As an example of why this might be necessary, consider the edge case of a user who logs out of the site or app. In this situation, his phone or browser would still be bearing a JWT with a valid exp expiry. In order to prevent the user from continuing to use this JWT, the server might maintain a blacklist of JWT which it will not honor, even if the exp and checksum pass inspection. So, a third step after unlocking the JWT and checking exp might be to make sure that the JWT does not appear on the blacklist.
A good JWT implementation can limit the amount of server side state to something very small, but typically the server would actually maintain some state of its own.

JWT token base authentication on each request for dashboard app

I want to create a login system using JWT and have these questions:
1- My client login and I generate a token for him/her and store the token in local storage. Now If somebody else copies this token from local storage of this person browser and paste in his/her (I mean hacker) browser local storage, this hacker will able to log in? If yes, is that safe?
2- I put user Id in the token that I generated On login function. On each request that is sending to the backend, I decode token and find userId in it. Now should I compare this user id by anything? Example checking that is there any session by this user ID in backend or even checking the user Id by DB?
3- should I put an expiration time for JWT token on the local store?
1 - It's safe to store these in localStorage. It is worth checking out how to protect against Cross site scripting attacks; this is particularly true for high security environments. Users copying and pasting is probably an unlikely attack, and, if the user has physical access to do the copy and paster, there are probably other 'vulnerabilities' like just using the browser's stored passwords.
2 - The JWT encrypts the user id included in the claim. A user can't change this claim and keep it valid (assuming a strong key), so no need to check this elsewhere.
3 - Yep! Since the JWT has a claim (like the user roles) in it, you don't want those to be valid for forever. Also, you want to have a way to ensure that users re-verify their identify (ie. log in again) just in case something goes wrong/a token is stolen. When you put an expiration on the token, you force this.

Generating an API Secret

I have created an API that I only want certain clients having access to. After a bit of research, I found that API Keys and API Secrets are pretty good way of controlling that.
I want to basically generate my own secrets using information I control. For example, if I create the secret 1500315177265-8005550000-System, the secret itself has information I can reference and validate. From what I understand, it doesn't matter what the secret is, as long as its not shared, and that's what makes it a secret. I can append some long salt values to make it much harder to guess. Can I use secrets securely this way?
Along the same lines, I am thinking what the need for the API Key is needed if the secret itself has identifying information. More than likely, I'm missing something here or more APIs would do it this way.
You don't need to suffer creating this mechanism by your own, you could just use OAuth for this. Actually by reading how OAuth works, I'm pretty sure that you'll get an overall idea of what the "API Key" is doing.
Long story short. OAuth allows you to create access tokens that will be requested by your users, once the user has asked for an access token, he'll be able to use it to get authenticated on the API.
You can also configure the duration for these access tokens, for example, let's say that you only want them to be valid for one hour. Then the user will use a new access token every hour, helping you to minimize risks against compromised access tokens.
If you want to take a look at the pipeline used by OAuth, it will be something like this:
The user sends an identifier and a shared secret (see them as username and password). If the identifier and the secret are correct, he'll receive a "refresh token", this token will be used to send requests to the token server to receive new "access tokens". The client sends a request to the tokens server to receive an access token, and now he'll be able to send requests to your API, where he'll use his access token as an identifier, and only if the token is valid, he'll get access to your application.
Maybe you could be curious about expired tokens, for example, What happens when the token has expired? Now our user needs to repeat all process again? No, because if the token has expired, he can just send a new request to the tokens server, sending his refresh token, and he'll get a new token to be used with your API.
I'm pretty sure that you already noticed that your API key is the "access token" equivalent, and your shared secret is the equivalent to the credentials used at the beginning of the OAuth process.
You can create your own mechanism, but you will need to take a lot of considerations that are already covered by OAuth. For example, Will you expire your API keys? After all, you should not trust a single key to be sent over every request for an undetermined amount of time. How will you handle the process to request new keys? Do you really want your users to send their secret every time they want a new key? Refresh tokens are useful for this.

Encoding and Decoding API Access token with keys

I am planning to secure my rest API in django with a ACCESS_TOKEN.
When ever user is logged in using their username and password, once they are authenticated, I generate a ACCESS_TOKEN and passed to frontend be it Website or Native application. and then later used that ACCESS_TOKEN for further communication.
I am generating this token based on some user data and then encrypting this with public key. Later when application send this for in any request, I decrypt the ACCESS_TOKEN with private key and extract user data data and process the request. This is something similar to session where session data is in encrypted form in ACCESS_TOKEN and only private key and decrypt the ACCESS_TOKEN. This is what I am planning to do.
Please suggest me for following questions:-
1. Is is the best way to secure my REST API? I want to use my API in same way from Web-application(AJAX calling) and NATIVE application(Android/IOS etc) ?
2. What is the best way to expire the token? Do I need to keep track of access token at my end in order to expire them?
Also I do want to use the Oauth in my API.
Most people I see use JWT's that are signed but not encrypted so they store non-PI data like user_id or session_id. I guess you could encrypt it if needing to store personal information but I don't see any other reason. Assuming you are using HTTPS, then only the end client would have access to the information. Sounds like asking for trouble if the secret gets leaked so you would want a really good key rotation scheme since you may not even know its leaked until too late.
Many people using JWTs do so because they don't want a centralized auth server, thus the token is short lived like a few hours or days. If you need really tight control on expiring tokens, you can take a blacklist approach where a blacklist of JTI's (JWT Ids) are stored in a K/V to be checked against. https://www.moesif.com/blog/technical/restful-apis/Authorization-on-RESTful-APIs/

How generation and validation process works for secure token authentication?

I was comparing cookie vs token authentication. I'm fairly familiar with cookie auth, but I needed to understand how token auth works.
From what I understand
User Logins in with Username and Password
server gets data and checks if Username and Password match
If match, generates token using alg like SHA256?
sends token to user
user sends request w/ token and other data to access restricted data?
server uses other data and hash method to check against token?
What I'm confused by is 3, 5, and 6, the token generation part.
For 3, what data do you put to hash, is it just a hash or is there
more to the process?
For 5, what if any other data is sent with the token?
For 6, how is the data sent used to validate the token?
How can you tell if the token has expired?
For 3, what data do you put to hash, is it just a hash or is there more to the process?
Whatever you like really. The implementation details are only of your concern. Basically, the token is a random string (encrypted, hashed or not)...again, it's up to you how you want to implement it. But, always make sure a token is unique across the system and that the system can use it to effectively identifier a user and its scope
For 5, what if any other data is sent with the token?
I'm not too sure what else you need to send, but usually you don't have to send anything else because of what I mentioned above...an access token must describe a user (or device, or whatever) and its scope within the system. So, why would you bother sending additional information?
For 6, how is the data sent used to validate the token?
And again, it's up to you. Other data could be the user's email address or the user id and then your system can match the userid (or email) with the access token. However, this is NOT mandatory, you can implement it whichever way you want to.
How can you tell if the token has expired?
Well, if your system issues temporary access token, hopefully it will be keeping track of when the access token was created and then determine if the access token has expired based on the creation. That's from the server side. For example, in its simplest form, you could have a database table that stores access tokens with the following columns:
Access Token: unique string
UserId: the related user id
DateCreated: UTC time
That's all you need to make it work, of course, usually you will want to provide stronger security and this table will be much bigger.