I'm feeling really stupid right now - I'm an experienced javascript & PHP developer but I just can't get my head round this one!
I have developed a system that allows users to create widgets and embed them on their own sites by including one dynamically-generated javascript file. I have now incorporated an authentication system so users of these widgets can register and login on my client's sites. The registration details are stored on my server.
When a user registers or logs in, I was planning on sending back some kind of encrypted token (of their unique ID) so that when they next access a widget on the same site the code will automatically log them in by sending the token to my server and decrypting it.
However, if this token is stored in the browser via localStorage or a cookie, it will be copy-and-paste-able to anyone that can get their hands on it, resulting in them being able to log in as that user. Is there any way I can achieve what I want without this risk?
Thanks in advance!
You can use JWT. Server generates JWT to frontend and when frontend receives JWT it will store it to localstorage. Localstorage is safe place to keep JWT as long as you make sure that user can't perform any XSS on your application.
You can also solve CSRF with JWT if you send it in HTTP header. That makes sure that unauthorized requests won't go through on other domains. You should check this PHP JWT library out. I have used it on my own projects.
PHP-JWT
I decided to send back a hashed token made up of the user's (encoded) id, password, and salt. I store their encoded id and token, then send both details to the server when automatically authenticating. Should the user's account be compromised through use of this token, they can change their password to invalidate it.
Related
I currently have this flow but I am unsure of the architecture going forward.
On my page, the user gets sent to the Slack OAuth API where they confirm scopes
User gets redirected back to my page with a one time code
Client sends a request to the server with the code
The server sends a request to Slack with the code, exchanging it for an access token
If the code and token are OK, it creates a new user in MongoDB
I made a flowchart to illustrate:
I would like the user to not have to authorize the scopes every time they want to access the service, and even if they did, how would I keep the token around in a secure manner to make requests? Would I have to create my own token authentication with login and password, or is there a better way? Should I persist this token on the client somehow and have the users be logged in that way? If so, what is the best way to do that?
Slack token generation must be one time activity per user.
When creating user in MongoDB, you should also store the generated token securely.
For later use, your application should use the stored token for any slack interactions, given that you have authenticated the user whose token you'll be using.
I am looking for some advice on implementing authentication when the client and the server live in separate projects.
The Server
This API was built as an Express Server. It has routes for CRUD operations with a MySQL database. It also has a user model that utilize bcrypt to encrypt passwords. There is no Frontend, in this project.
The Client
This is a Vue project made with the vue-cli and hits the above API to get the data to display.
The Issue
I need to add authentication. I was thinking I would do this with express-session, but I am a little confused with how exactly it works. All of the tutorials I have seen use express-session in combination with passport. This seems fine, but in all the examples passport forwards to a login page that lives on the server. This is usually written in handlebars or some other templating framework. I am not sure the best way of implementing since the login page lives in the client project.
How I thought it worked (Am I missing something?)
I was originally of the impression that for a new user express-session would create a token that I would save in the users table (maybe generated at login and stored temporarily). Once the user logs in with the correct password this token is passed to the client to be stored as a cookie. When the client wants access to restricted data, it would pass the token as a Authentication header to the server to get permission.
The Questions
Since my projects are separated is passport still useful for my use case?
Is it secure to create the session cookie on the server and send the token to the client as a response to the client's login POST?
Do I need to store the session token in the database?
Is there a better option?
In my project I have almost the same setup, and I ended up with JWT to generate an access token.
The cycle begins with the user sending his/her email and password to my login endpoint.
In this stage I hash the password using some secret string, fetch the user from database and check if authentication succeed.
After that I generate an access token with an expiring time set, and I expected this access token in all protected routes.
With this approach you can easily implements refresh token to exchange at time to time, saving the refresh token in your database.
This is very simple and Is good to you understand how the process of authentication is done.
jsonwebtoken
The Setup
We’re building a PWA (progressive web app). The main components are the app shell (SPA) and the API. The REST API will supply the data needed for the app, while the SPA will handle the rest (as per Google recommendation).
The Problem
Authentication of the end-user seems problematic because the web browser needs to be accounted for. We want the user login to persist through closing down the browser.
We’ve done the research about the possible ways of going about it, however we’d like to ensure that we’re not going in the wrong direction.
Solutions we’ve considered
Session based authentication - the user sends username and password to /accounts/auth and receives a HTTP only cookie with the session ID. The session needs to be stored in a database or Redis. The issue with this option is that cookies are automatically sent by the browser therefore we need a CSRF protection in place. Using the Synchronizer Token Pattern a new token would be generated every time a state changing request has been made e.g. POST. This means that the application needs to supply a CSRF token with every request so that the PWA can send it via AJAX. We determined that it’s not ideal as the user can send multiple post requests in a quick succession making some of them fail and resulting in a bad user experience.
We could also use this method without the CSRF by limiting the CORS policy to same domain and adding a header requirement which technically should stop all CSRF, however we're unsure how secure it would be.
JWT token based authentication - the user sends username and password to /accounts/auth and a new JWT token is issued. The JWT then needs to be stored in localstorage or a cookie. Using localstorage means that JWT is XSS vulnerable and if the token is stolen, an attacker can impersonate the user completely. Using cookies we will still have a CSRF issue to resolve. We considered a double submit cookie method but the CSRF would only refresh every time the JWT is reissued which creates a window for the attacker to find out what the CSRF is. It is not clear which method is best to use.
Session based authentication + JWT token authentication - the user sends username and password to /accounts/auth, a session is created, a HTTP only cookie is set in the browser and a JWT token is sent back to the user. The PWA can authenticate requests with the JWT and whenever the JWT expires the app calls /accounts/auth again to acquire a new one. The /accounts/auth endpoint would still need to be CSRF protected, however the impact of it on usability would be minimised.
There seems to be a large amount of articles claiming that localStorage is insecure and shouldn't be used so why are high profile organisations like Amazon still recommending it? https://github.com/aws/amazon-cognito-auth-js - this SDK uses localStorage to store the token.
You don't need to generate new CSRF token each time a client make a request. It's much easier to use a scheme like token = hash(id + secret + current_day). You only need to update it once a day, or even employ mixed scheme (if the token is invalid today, but is okay for the previous day, the server accepts the operation and returns new token in a predefined header for client to renew it). You may also use the cookie as an id, making the token totally stateless and much easier to check, no need to store them in the database.
Here is how I look at it.
JWT token authentication : with this approach, you can always use a time-bound token with its expiration set to say 2 hours or something?
Or another approach would also be to try and see how you could use some of the approaches the Credentials Management API suggests for example, auto-sign-in of users whenever they come back.
Stuff like 2-step verification with OTPs for instance; for very important features in your web app can be a choice. In this case basic stuff are tied to whichever one time authentication method you have.
Actually, you can also use user-defined pins or short codes (seen a lot in banking apps) to grant access to some features in your web app.
Hope this helps, or sparks some ideation.
I am trying to build an API service that will communicate with another application but I have some concerns about the security of the application. I want it to use token authentication but in all tutorials that I read is said to give the user a hashed token and make requests with it. For example if I want to retrieve a user:
myapp.com/user/1?my_token=<TOKEN>
This token would be checked for example if it contains an existing user with username and password that has the access to this route. But no matter what checks I make on the server if someone knows this token he can send requests from anywhere.
I saw that in Google APIs developers should paste their API_KEY as a query variable but maybe they have some other security checks? Isn't it like putting your username and password as plain text in the query parameters? What is the best way to authenticate users without the possibility of man in the middle attack?
I'm writing a web app with a separate frontend and backend. The frontend is written in React, and the backend is a node.js server running an Express endpoint. How do I ensure that only my frontend can access the API, and not anyone else? My API URL is exposed in my frontend client side code, so anyone can see that.
I added JWT authentication to my API, but I still need to have an unprotected /login endpoint in order to generate the JWT token, and in order to login to generate the token, I must post both a username and password from my frontend, which other users can see, since it's done from the client side.
What is the proper way of securing an API that is hosted on a separate backend like this, so that only my frontend can access it, in a way where nobody can see what credentials are being used to access the endpoint?
You can't. Your API is on the internet. Anyone can access it. You can require an account and login credentials for the account before allowing access to the API, but once someone has an account and credentials, they can access the API from their own script rather than via your web page. This is how the web works. Not much you can do about it. And credentials being used by the client cannot be hidden. All data that is EVER on the client can be looked at by a hacker on the client. This is the way of the web.
Larger companies will typically monitor their API usage to look for inappropriate use. This includes rate limiting, detecting behaviors and sequences that are not typical of a regular human user. When they detect inappropriate use, they will often disable that action or ban the offending account, either temporarily or permanently. This is also why some pages use techniques to detect if an actual human is individually causing the operation such as reCaptcha. For example, on stack overflow, when editing comments or posts, I often run into rate limiting where it tells me that I have to wait a bit before it will accept my edit.
There is no absolutely secure way to store credentials in a client. The most common scheme for credentials is to require username and password (securely over https) and then when that is accepted on the server as legit credentials, some sort of token is issued to the client which can be used for future API calls. That token may be in a cookie or may need to be manually included with each subsequent API call (the advantage of a cookie when using APIs from a browser is that the cookie is automatically sent with each subsequent request).
If the token is a cookie, then the cookie is stored in the browser's cookie storage and an expiration can be set for it. The browser's cookie storage is protected from access by web pages from other sites, but can be accessed by someone on the local computer (it's stored in the file system).
If the token is not a cookie, just returned as a token, and the client wishes to store it, there are a few other places that Javascript provides access to in order to store it. Local storage has similar security as cookie storage. It is protected from access by other web sites, but can be accessed by a person on the local computer.