I'm making a login page and I've found that JWT tokens are preferred over sessions but I don't understand what to do with a token.
I send user and password uncrypted with ajax to server and validate the user in a php file which then returns a JWT.
What should I put in my JWT? Do I only check for a token to know if the user is logged in or do I process it somehow to check if it's the right token? If so, how?
So far I've seen examples on client side where you only check if token exists but why should I have hashed data as token instead of a 1 or a 0. I don't get the advantages of this method.
EDIT: Should I both request a JWT token which I store in session storage and store what the user types in the log in field also in session storage and then compare them with eachother every time the user reloads the page?
Looks like we need basics of how JWT works here:
The client sends username/password to the server using ajax.
The server checks username/password and if they are valid, creates an encrypted token, which the only server can read and understand.
Server takes into account various fields (also known as "Claims") like "iss" (token issuer) and "Sub" (Subject of token), whole list here.
We can custom fields like user-id which can be used later while validating token.
Server sends token back to client through response. Client saves this token in local storage or some variable.
With each further request, client sends this token as header.
Server examines and validates this token, gets require info from this token like user-id and responds to the user appropriately if valid. Token may also contain expiry date/time, so after a certain time, the server may choose to refuse to serve a client.
While this may not directly answer your question, it clarifies basic workflow of GWT.
Related
I have developed a simple bakend server in node with jwt authentication, but I still have a question: after the user has correctly logged in and saved the token in the client side should the server validate the token at every user request? For example when accessing the /profile route (which takes the user to the profile page), or when for example the user creates a question by sending a post request to /posts/create route should I use the method jwt.verify(...) to check if the token is correct everytime? Is it correct also to send the jwt access token instead of the refresh token or is this a bad practice?
Yes, you should validate each request. That is call middleware. In the first step, you check authentication. After that, you can use it for authorization. You can write role, some permission, or other info in JWT.
I have a REST API (.net) which for the initial login requires the password to be encrypted (RSA with OAEP). The reason was to obscure the users passwords from local logs.
Performing this encryption with javascript is complicated and I would need to let the client know the public key. The end user would be able to reverse engineer the encryption method then could use it to brute-force (or worse) access. So why bother, right (it is SSL Secure).
Thing is, I still need that password to be encrypted. Should I have some sort of encryption service at the server side that gives me the password to throw at the token endpoint? Why not have the service just log in for me then return the token. How should I proceed?
Thanks ^_^
This seems like a general authentication question. You can solve it like you would solve user authentication. Think of it this way:
When a user signs-in into your app, they provide their data on the client, and then it is validated on the server. In order for them to stay logged in, they get some sort of token, either via a Cookie session, JWT or whatever. Which is then saved on the client and sent on each request to the server in order to verify they are authenticated.
The above is how websites can show "registered users only" content. By validating a previously given token on each new request.
Now, applying this method to your REST Api. A user needs to request a token (which should not be your master password, but a uniquely generated one, in a per-user basis), and then save it locally for X amount of time. Every time the user makes a request to the API they send that token, which is validated.
This is also how normal APIs do it. You will need a token or some sort either way. If it's really sensitive information you're showing, the token should update every now and then (from minutes to days depending on how sensitive). You keep a record of valid tokens in your server. That way, if any token is "stolen", then it will only be valid for a small amount of time.
I am working on an authentication system, implemented the front end using vuejs and back end with nodejs. User is able to register and login successfully. I am verifying user is logged in using jwt token. My problem is anyone can login by manipulating the localStorage jwt token value. Is there anyway to prevent it.
You should be using an asymmetric signature on your JWT token, and the private key should be available only to the server that creates the JWT. If this is the case, then it's highly unlikely that a user would be able to forge JWT claims.
Here's a step by step of how your server should prevent someone from changing their JWT info:
Your NodeJS server creates a new JWT using an encryption key (we'll call it secret-key) to create the signature, and it sends the token to the client.
The user decides they want admin access, so they change their permissions in their local JWT and send it to the server.
The NodeJS server re-signs the header and payload of the user's JWT using secret-key and compares that generated signature with the signature in the user's JWT. If they match, then nothing has changed about the user's JWT. If they don't match, then either the user changed something in the header or payload, or they tried re-signing the token with their own encryption key. Either way, your server can tell that the JWT isn't valid, and you can deny them access.
I have tried implementing JWT to my Angularjs application for a secured authentication. I have generated the JWT at server side(java) and the implementation returns a JWT to the client side after a successful login. I have stored the JWT in $http.defaults.headers.common.Authorization and also in the $window.sessionStorage. Now I could see the JWT in all all requests made by the $http service.
The part I am not clear is I dont know how to proceed from this point. What I guess is I should validate the JWT from now on for all $http calls at the server side somehow. Can someone clarify me how I should proceed for validating the client side JWT at the server side ?
Yes every time the client makes a request to the backend, you now have to supply the JWT in the header.
Inside the JWT you can have some parameters that identifies the user, like his username for example. Do not store password or other sensitive information inside the JWT.
If you are useing Java, you could create a Filter that will be mapped to a url that only an authorized user can have acces. In the filter you can make the necessary checks to see if the suplied token is correct, if it is you can let the request pass trough, otherwise you can return to the client an error specifying that he does not have access.
If you need more information, may be this is a good place to start.
I am currently writing an HTML5 web app with a Sails.js (node framework) backend. Right now, most of my APIs are secured against the user authentication system I'm using with PassportJS. Unauthorized users trying to use my APIs will get a 401 error.
However, there's one hole in the system, which is the sign up API itself. I obviously can't secure my sign up API with user authentication (because the user wouldn't have had an account to sign in with yet), therefore anyone could easily spam the API with many fake accounts. On my sign up page, I have a small verification question on the lines of "What is 2+2?" (it is generated randomly) and it is checked on the client and if the answer is correct, the client sends a request to my sign up API route with all the necessary parameters like name, birthday and username. How can I secure this API to ensure that people must go through my sign up page, and cannot simply bypass this security measure and call the API directly?
Just as a note, my APIs are not RESTFul.
There are multiple possible ways.
First of all, you may consider adding a rate-limit to IP addresses. This is NOT 100% effective, but will certainly slow down some spam attempts. For example, you can limit the number of accounts created by the same IP address to 5 every 5 minutes.
Secondly, if you want to use some sort of captcha, consider reCAPTCHA. Among the different captcha services, this is particularly effective against bots, as they especially use words that fail OCR recognition.
Eventually, to make sure that people actually visit your signup page before calling the API, you can use a "security token". This is the same technique that is used for example to protect against CSRF (Cross-Site Request Forgery) attacks.
When the server generates the signup page, it also passes to the client an hidden field (for example "token") that contains a uniquely-generated value. The client will submit this value along with the form back to the API server when it requests the creation of a user, and the server uses the token to validate the request.
There are basically two approaches to generate these tokens.
First method
The signup page creates a random string/number and stores it in the database to be used as token. When the user submits the form, the server searches for that token into the database: if it's present, then the submission is valid; otherwise it fails. The token is then removed from the database.
Additional security can be obtained by storing into the database, along with the token, an expiration date and the client's user-agent (unlike IP's, user-agents are unlikely to change during the same session).
Pros: each token can be used only once.
Cons: the app needs a database, and it will be queried 3 times just for the token insertion, validation and deletion (requiring time and adding load to the database). You also should to purge regularly expired tokens from the database.
Second method
The signup page creates a token by digitally signing a plain-text string containing all the validation information. For example, suppose that you want to create a token that expires on 1411660627 (UNIX timestamp) and it's associated with the user-agent "Mozilla/5.0 ...". The server also possesses a secret salt (for example "123456abcde") that needs to be unique for the application and kept secret.
The signup page generates the token in a way similar to:
Create a plain-text string to be signed, by concatenating all the information. For example, if the expiration is 1411660627 and the MD5-hashed user agent is 0f7aee3e0a65ff9440d2a0183b4b1f49, your base signature would be something similar to: 1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49.
Append the secret salt to that string: 1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49_ 123456abcde.
Hash that string, using any hashing algorithm (for example MD5). The result is your signature: 0742d84065cb9497c1ba4c1d33190a93.
Concatenate your signature to the plain-text string to obtain your security token: 1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49-0742d84065cb9497c1ba4c1d33190a93. This is what the user received and has to submit back.
To verify the token, then, a similar operation is done. When the server receives the token 1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49-0742d84065cb9497c1ba4c1d33190a93, it performs these steps:
Extract the expiration from the token and check if it's still valid. If 1411660627 is smaller than the current timestamp, then it's still valid.
Compute the hash of the user agent and check if it matches the one on the token: 0f7aee3e0a65ff9440d2a0183b4b1f49.
Re-generate the signature as before: expiration-useragent_secretsalt using the data from the security token received from the user. In our example: 1411660627-0f7aee3e0a65ff9440d2a0183b4b1f49_ 123456abcde.
Compute the hash of the string as before. If it matches the third parameter from the token (0742d84065cb9497c1ba4c1d33190a93), then the security token is valid.
Pros: this solution does not require a database, but it's equally safe (as long as the salt is kept secret into the server).
Cons: the same security token can be used more than once until it expires.
It sounds like you're not making full use of your math-problem countermeasure--you're using it as a client-side barrier, but as you observed, a bot could just skip the client side and call your API. To make it more effective, instead of generating the question randomly on the client, you would generate it on the server, save the answer in the session (req.session.mathProblemAnswer = 4) and then send the user's answer with the API call so that it can be checked against the answer in the session.
Using a token as #Qualcuno describes in his answer will be effective against bots spamming your API endpoint directly, but there are bots that are smart enough to load your signup page, scan for hidden fields and submit the form (including the token). It's still a good idea to use CSRF protection though in general, which Sails has built-in support for.