I know it's not best practice, but I'd like to store username and password in a json web token after initial authentication. Of course those credentials will be encrypted before passing them to the jwt payload.
The reason for this approach is that my api exchanges information with a third party which relies on username/password authentication only (no tokens). So every time I make a request from my client, the api has to pass the user credentials to the third party.
Is this safe or can anybody think of a better way to do this?
Related
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.
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.
I'm writing a single page web app using express and react.
I am now trying to choose the way to authenticate my users.
I want to let them register and log in with email and password and 3rd party provider like Facebook, Google etc...
I read some articles about passport and jwt (express-with-passport, jwt-with-passport), but none of them combined jwt and 3rd party provider.
The only way I could think of is to save the tokens in my db, and for each request to compare them (tokens provided by a 3rd party and tokens generated by myself using jwt)
Saving the token from a provider in my db and compare with each request makes sense, but using jwt I just need to verify the token without accessing the db.
How can I differ the tokens that I receive from the client? How can I tell when to access the db (for provider tokens) and when to verify using jwt?
EDIT:
The way of implementation I was thinking about is as follows:
- Username & password: Upon login, generate a token (using jwt) and send it to the client. Every request will include the token and the server will verify it.
- 3rd party provider: Let's say that the user is authenticated with Facebook. My server receive the token (using passport-js) from Facebook. Now I need to send the client its token. I could send the token I just received from facebook, but then how can I verify the token the client send to me afterward on every request?
So I could generate once again a token using jwt and work just like described above.
Is this a good implementation or am I missing something? I couldn't find
a full tutorial that describe all of those aspects.
Rather than using a token that an identity provider might give you, you might consider generating your own tokens based on a successful login callback to your application. Issue new tokens on every request for sliding expiration, and possibly consider the use of refresh tokens.
In your DB, you could store the authentication method for a given user (Facebook / Google / etc.) when they log in. When you receive a request with an invalid token, query for this auth method from the DB, then redirect them to the respective identity provider for re-authentication.
This will avoid DB lookups for most "normal" JWT validations for your app and gives you the full benefits of the stateless nature of the token.
I'm writing an application with a front end in emberjs and backend/server-side in a nodejs server. I have emberjs configured so that a user can login/signup with an 3rd party Oauth (google, twitter, Facebook). I have a backend written in express nodejs server that hosts the RESTful APIs.
I do not have DB connected to emberjs and I don't think I should anyways since it's strictly client side code. I'm planning on using JWT for communicating between client side and server side. When a user logins with their oauth cred, I get a JSON object back from the provider with uid, name, login, access_token and other details.
I'm struggling with picking a strategy on how to handle user signup. There is no signup process since it's OAuth. So the flow is if the user is not in my db, create it. I do not support email/password authentication. What would be the flow when a user signs in with an OAuth provider for the first time? Should emberjs send all the details to the backend on every sign in so that backend can add new users to the db?
What should be part of my JWT body? I was thinking uid and provider supplied access token. One issue I can think of here is that provider specific access token can change. User can revoke the token from provider's site and signs up again with emberjs.
I'm open to writing the front-end in any other javascript client side framework if it makes it easier.
If we're talking about not only working but also secure stateless authentication you will need to consider proper strategy with both access and refresh tokens.
Access token is a token which provides an access to a protected resource.
Expiration here might be installed approximately in ~1 hour (depends on your considerations).
Refresh token is a special token which should be used to generate additional access token in case it was expired or user session has been updated. Obviously you need to make it long lived (in comparison with access token) and secure as much as possible.
Expiration here might be installed approximately in ~10 days or even more (also depends on your considerations).
FYI: Since refresh tokens are long lived, to make them really secure you might want to store them in your database (refresh token requests are performed rarely). In this way, let's say, even if your refresh token was hacked somehow and someone regenerated access/refresh tokens, of course you will loose permissions, but then you still can login to the system, since you know login/pass (in case you will use them later) or just by signing in via any social network.
Where to store these tokens?
There are basically 2 common places:
HTML5 Web Storage (localStorage/sessionStorage)
Good to go, but in the same time risky enough. Storage is accessible via javascript code on the same domain. That means in case you've got XSS, your tokens might be hacked. So by choosing this method you must take care and encode/escape all untrusted data. And even if you did it, I'm pretty sure you use some bunch of 3rd-party client-side modules and there is no guarantee any of them has some malicious code.
Also Web Storage does not enforce any secure standards during transfer. So you need to be sure JWT is sent over HTTPS and never HTTP.
Cookies
With specific HttpOnly option cookies are not accessible via javascript and are immune to XSS. You can also set the Secure cookie flag to guarantee the cookie is only sent over HTTPS.
However, cookies are vulnerable to a different type of attack: cross-site request forgery (CSRF).
In this case CSRF could be prevented by using some kind of synchronized token patterns. There is good implementation in AngularJS, in Security Considerations section.
An article you might want to follow.
To illustrate how it works in general:
Few words about JWT itself:
To make it clear there is really cool JWT Debugger from Auth0 guys.
There are 2 (sometimes 3) common claims types: public, private (and reserved).
An example of JWT body (payload, can be whatever you want):
{
name: "Dave Doe",
isAdmin: true,
providerToken: '...' // should be verified then separately
}
More information about JWT structure you will find here.
To answer the two specific questions that you posed:
What would be the flow when a user signs in with an OAuth provider for
the first time? Should emberjs send all the details to the backend on
every sign in so that backend can add new users to the db?
Whenever a user either signs up or logs in via oauth and your client receives a new access token back, I would upsert (update or insert) it into your users table (or collection) along with any new or updated information that you retrieved about the user from the oauth provider API. I suggest storing it directly on each users record to ensure the access token and associated profile information changes atomically. In general, I'd usually compose this into some sort of middleware that automatically performs these steps when a new token is present.
What should be part of my JWT body? I was thinking uid and provider
supplied access token. One issue I can think of here is that provider
specific access token can change. User can revoke the token from
provider's site and signs up again with emberjs.
The JWT body generally consists of the users claims. I personally see little benefit to storing the provider access token in the body of a JWT token since it would have few benefits to your client app (unless you are doing a lot of direct API calls from your client to their API, I prefer to do those calls server-side and send my app client back a normalized set of claims that adhere to my own interface). By writing your own claims interface, you will not have to work around the various differences present from multiple providers from your client app. An example of this would be coalescing Twitter and Facebook specific fields that are named differently in their APIs to common fields that you store on your user profile table, then embedding your local profile fields as claims in your JWT body to be interpreted by your client app. There is an added benefit to this that you will not be persisting any data that could leak in the future in an unencrypted JWT token.
Whether or not you are storing the oauth provider supplied access token within the JWT token body, you will need to grant a new JWT token every time the profile data changes (you can put in a mechanism to bypass issuing new JWT tokens if no profile updates occurred and the previous token is still good).
In addition to whatever profile fields you store as claims in the JWT token body, I would always define the standard JWT token body fields of:
{
iss: "https://YOUR_NAMESPACE",
sub: "{connection}|{user_id}",
aud: "YOUR_CLIENT_ID",
exp: 1372674336,
iat: 1372638336
}
For any OAuth workflow you should definitely use the passportjs library. You should also read the full documentation. It is easy to understand but I made the mistake of not reading the the whole thing the first time and struggled. It contains OAuth Authentication with over 300 Providers and Issuing Tokens.
Nevertheless, if you want to do it manually or want a basic understanding, here is the flow that I'd use:
Frontend has a login page listing Sign-in with Google/Facebook etc where OAuth is implemented.
Successful OAuth results in a uid, login, access_token etc. (JSON object)
You POST the JSON object to your /login/ route in your Node.js application. (Yes, you send the whole response regardless if it's a new or existing user. Sending extra data here is better than doing two requests)
The backend application reads the uid and the access_token. Ensure that the access_token is valid by following (https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow#checktoken) or asking for user data from the provider using the access token. (This will fail for invalid access token since OAuth access tokens are generated on a per app/developer basis) Now, search your backend DB.
If the uid exists in the database, you update the user's access_token and expiresIn in the DB. (The access_token allows you to get more information from Facebook for that particular user and it provides access for a few hours usually.)
Else, you create a new user with uid, login etc info.
After updating the access_token or creating a new user, you send JWT token containing the uid. (Encode the jwt with a secret, this would ensure that it was sent by you and have not been tampered with. Checkout https://github.com/auth0/express-jwt)
On the frontend after the user has received the jwt from /login, save it to sessionStorage by sessionStorage.setItem('jwt', token);
On the frontend, also add the following:
if ($window.sessionStorage.token) {
xhr.setRequestHeader("Authorization", $window.sessionStorage.token);
}
This would ensure that if there is a jwt token, it is sent with every request.
On your Node.js app.js file, add
app.use(jwt({ secret: 'shhhhhhared-secret'}).unless({path: ['/login']}));
This would validate that jwt for anything in your path, ensuring that the user is logged-in, otherwise not allow access and redirect to the login page. The exception case here is /login since that's where you give both your new or unauthenticated users a JWT.
You can find more information on the Github URL on how to get the token and to find out which user's request you are currently serving.
I'm trying to build a mobile app that has a login functionality with an ASP.NET web api, and I need to implement the token based authentication,
what I need is, as a first time the user login using username and password, a new token will be generated with expire date along with a refresh token, I'm thinking of the refresh token because the user doesn't have to login every time the token expires,
the token is saved in the mobile device and in the database, so with each request, sends the token whether in the request header or with the posted data,
I don't exactly know how the token based authentication works in terms of sending the token encrypted or hashed to the user and processing the request in the server
Edit:
an attacker in the middle can just read the token and start sending requests to the server using the token. I mean he doesn't need to know what the token actually means.
I created a class that has these properties (UserID,Token, RefreshToken, ExpiryDate), but I read that it is not a good approach,
I'm using AES for encryption and SHA256 for hash
Thank you for you help,
Please see the following articles in order to understand how token based authentication works in ASP.NET Web API.
http://www.codeproject.com/Tips/821772/Claims-And-Token-Based-Authentication-ASP-NET-Web
http://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/
Search OpenID and OpenID Connect specs, they will tell you exactly how the tokens should work in your case (non-confidential implicit client flow). You can add OpenID endpoints easily to your asp.net web api if you don't want to use an external openid server.