Checking hashed REST API token - security

I authorize all REST API requests by checking token in Authorization header:
POST /rest/resource HTTP/1.1
Host: domain.com
Authorization: Bearer AbCdEf123456
The token is plain text, using HTTPS. However, the token is salted and hashed in the database.
How could I authenticate the request?
send also user id to the server, select token hash for this user from the database, check if the token is correct (issue with sending user id - where to put it)
check if some hash in the database corresponds to the token received from the user (performance issue)
There must be some elegant way since for example for google maps the "API key" (token) is sufficient.

Use JWT (JSON Web Token) as authorization bearer. JWT can have user id in the payload. You can also easily verify if JWT was issued by trusted party (probably you).
The good thing is that you can verify JWT without reading values form database. It is completely stateless.
This is simple explanation how JWT works:
http://www.intridea.com/blog/2013/11/7/json-web-token-the-useful-little-standard-you-haven-t-heard-about
You can find library for JWT for almost any language (just google it)

Related

JWT tokens: questions best practices and risk of symmetric keys

First a little background on my use of JWT tokens.
Users (via a web frontend) login to my service through a login HTTP endpoint that includes a username and a password in the request body. Two factor authentication will be added in the future, but can be ignored for now.
The API verifies the login information and issues a JWT token in the response. This token is signed with a symmetric key and includes a userId (UUID) that uniquely identifies the user.
In subsequent API calls, the user includes that token in the Authorization HTTP header as a bearer token. The API verfies the signature of the token and then uses the userId to make sure that the user is authorized by checking the roles of the user (stored in a database).
The token can expire, forcing the user to login again, or they can use a refresh endpoint that verifies the token and issues a new one to bypass logging in each time the token would expire.
What are the best practices for JWT authentication/authorization? Are there flaws with my approach? Is there a risk of using symmetric keys here? I am open to suggestions on better approaches as well.

For user verification, you do need to store data on server side even when using JWT correct?

While I understand how jwt works for authentication, I'm trying to build registration.
Registration has a step that requires verification.
User enters the phone number
Code is sent via sms to user
User enters the code and device is verified
Since it's an API for mobile app there is no session/cookie built in.
I'm wondering if I can not implement cookie like system for mobile. And just make it work with JWT. But I don't have much experience with this.
This is my current flow:
User makes a POST request with Phone #
I respond with JWT (Time:Number)
I also send code via SMS
User sends the code via POST and JWT
Problem:
I don't know if code belongs to user or not, as I didn't save the code in DB.
I can't put into payload as it's just encoded not encrypted. (why is it not encrypted, what's the point of sending plain payload, what's even the point of JWT & didn't signed cookies already do that? they had session string encrypted so you couldn't change session string without invalidating the cookie)
JWT is overcome authentication/authorization mostly in APIs. JWT Access Token/Refresh Token is nothing but a JSON data in an encrypted form. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA. Key pair using RSA or ECDSA is more preferable as a security point of view. You can check authentication/authorization by decryption JWTs.
JWT token itself contains expiry date, so you can just configure expiration time to it. Access tokens are to check that user is authorized or not. Refresh tokens is necessary to get a new access token, generally used when the old access tokens are expired. Refresh token and Access token both expire but refresh token is long-lived compare to access tokens.
Generally developers use access token only but it is preferable to use access and refresh token both.

Authorization and authentication in nodejs

how the authorization token that is sent back after a user is authenticated is stored in browser and can be used for authorization in the same api for other routes until the token is deleted from the user's database after he logs off?
I used the postman for same. And there in the Headers section i got the authorization token as a response header. But how does this all work in a real login page in the browser?
For storing the token in browser you can use cookie or browser web storage (localStorage/sessionStorage). see this link for browser web storage. For those routes which need authorization you should send back the token in a header or cookie. this blog post may help you more.
Hello you can check this sample OAuth2 based on oauth2-server you can find the repo here: https://github.com/gerardabsi/NodeJS-OAuth2
Some intro,
The Authorization token is JWT usually and is created with some secret key at the server, the library like https://www.npmjs.com/package/jsonwebtoken is used mostly in NodeJs. One can use different strategies using Passport JS to make it more secure and open for 3rd party integration (like Google, FB etc).
Now your question,
When the user initially logs into the system using his valid credentials, the server generate a JWT token with secret key and sends it in the response header. The client side (browser) saves this token in the cookie or local storage, and for the next request sends this token in the request header. The server has the secret key and can verify the token's validation and can proceed or decline the request.
One should ideally use a token that expires in 1 hour (depends on use case) or so and not use non-expiring or long expiry tokens for security reasons.
This is roughly how it works, please let me know if any doubt.

does JWT containing userID need verification from the database?

I sign a JWT (JSON Web Token) with userID and iat (issues at) like so
jwt.encode({sub: user.id, iat: timestamp}, jwtSecret);
When I receive a JWT from the client, I decode it to extract the userID. Do I need to validate the userID by checking its existence in the database every time I need to allow the user to access a secure route (see first example)? Or can I just assume that the user is who she says she is, and allow her to access the secure path?
My feeling is that I need to access the database to validate the user on every request, this would be expensive and defeat the purpose of using a JWT.
Your token is signed. If someone changes the token on client side, it would fail validation and the server side framework would reject it. Therefore you can trust your token.
Of course, the jwtSecret should be a secret only known by your authentication server and resource server.
You generate the token only if you trust the user who requested it.
You trust the token as long as it has not expired and can be verified with the secret.
The whole idea of JWT is that can verify the integrity of the claims contained within it. If you can decode successfully the token you can be sure that this token contains information previously encoded by you. For someone to pass malformed data has to also know the secret you use to sign the tokens.
For more information read this.

Token Based Authentication advantages?

In token-based-authentication, some information is encoded into a token and that token is sent to the client (usually as an http-only cookie). The client responds with the same token, and the token is decoded to the server to verify that the client is who they say they are.
I have a couple of questions that I can't google the answers to, so was hoping to get some coherent help :)
Is there anything in the token that ties it to the specific client? i.e. if Alice copies Bob's token then can Alice send authenticated requests to the server?
Given that, is the token actually providing anything that can't be provided with a random token stored on the server database? i.e. my server generates a random UUID, stores a hash of it in a cache with Alice's data, sends it to the client. Client responds with the same token, server looks it up in the cache and gets the credentials.
In other words, is JWT just an expensive way of generating a UUID? (I'm assuming you can't encode all the client data you want into the token and will have to do a database/cache lookup on the server end even with a token).
Yes, a JWT token typically has a number of claims. The Subject claim would typically identify the user that was authenticated. If Alice copies Bob's token, she can use the API/application as if she were Bob. That's why it is important to use https to prevent bearer tokens from being stolen.
'iss' => Issuer of the token (Authority)
'sub' => Subject identifying the principal, typically the authenticated user
'aud' => Audience, the application trying to use the token
'exp' => Expiration, until when the token is valid.
See here for more info on the JWT token used in OAuth 2.0.
The thing that security tokens have over session tokens as you describe is that they can be validated without having to go back to the issuer (or central database). The issuer signs the token with its private key. The application is configured with the corresponding public key and can verify that the token was not compromised without going to the issuer.

Resources