Angular JWT and user info storage after login - javascript

How good practise is saving any other user info except JWT in localstorage or cookie after successfull login? (User profile object is already saved and encrypted in jwt payload sub part.) I need user profile object ready before initializing anything else in angular (for fetching user role, login status etc.).
If I save only JWT on client side i need one extra ajax request before app load to get user info from JWT decode on server side, because token secret is on server (only after full page refresh). Token is valid or invalid, so handling errors in this case is much easier.
If I save JWT and user profile object as a string in storage on client side then this is rendundant and user can change manually that object and app can go down.
I prefer saving only JWT in storage on client side after successfully login, but i need some advice, how organize code in that case? How fetch user profile object after full page refresh?
Please help.

The most secure solution is to store the JWT in an HTTPS-Only cookie, then make a request of the server to get the user object.
If you want to avoid that extra call to the server you will need to get creative. One approach I'm trying is storing the claims body of the JWT on the client - just the body, the signature is excluded. With the signature excluded the "token" is no longer a JWT and cannot be used for authentication, thus preventing the actual access token from being stolen out of local storage.
However this DOES assume two things about the claims body:
1) That the information is opaque and does not contain personally identifiable information (PII) about the user (local storage is vulnerable to XSS attacks).
2) Your Angular application does not leak sensitive information to the user if this object is modified in local storage (you should not store sensitive information in your Angular application, it should be protected by an API)
3) As with all cookie-based authentication strategies, you are protecting yourself against CSRF Attacks
I work at Stormpath and I recently wrote a blog post on this very subject: Token Based Authentication for Single Page Apps.
Hope this helps!

For the sake of simplicity, I would store just JWT and implement an extra ajax call to fetch the user profile.
But if you absolutely want to avoid this one call, you may consider using asymmetrically signed JWT instead of encrypted JWT and then extract data on the client side, assuming you control the creation of JWT.

Related

Encrypting, then storing access token in localStorage

My API returns an access token after a user signs in.
All future requests must include this token in the Authentication header.
I'd like users to remain logged in even if they close and re-open the browser.
Can I safely store an encrypted version of this access token in localStorage, retrieve it, unencrypt it in my React client code and send it off to the API?
Sure, you could use something like this https://www.npmjs.com/package/aes-js or another library if you like at https://www.npmjs.com/search?q=keywords:encrypt.
I think the real question is why? The user can always see the unencrypted value in the network request of the dev tools. If the access token is tied to a username and password that the user owns why can't they see it? It's really just another way to write their username and password. If it is associated with an username that belongs to your app (such as your server uses that username to login to another server for all requests, not just for this one user) then you shouldn't pass it to the browser ever because it is easy to steal.

Securing API calls without token

I'm building an app and an API endpoint using PHP(I know what you thinking!). My issue is that if I ask user for username and password on opening the app for the first time, since I can't store these details locally because they could be compromised. I'd send these through Post request to server then generate a token depending on whether the user is the right one. After getting response I must store this token locally right?
Yes!. there's expiration for the token. After the token is expired, I don't want to ask user for their name and password but want to access API still authenticating as that user. How will I do this?
If I use Oauth it's still the same procedure right? I should store something locally. won't that be compromised? I'm very confused.
How does other apps work. I'm sure they doing something in the background. They ask us for credentials only once and all subsequent API calls will be secured. Won't the token expire in that case or what?
Can i secure API calls without storing anything locally? I don't want API to be accessed from anywhere else but app.
Use android SharedPreferences. It should be very secure unless you deliberately expose it e.g. its accessible via an exported content provider missing the (android:exported="false") in the manifest. You can also use sqlite but there is no point of using a db table for one or two rows of data.You can also encrypt the user name and password to add one more security layer to protect rooted users.
Furthermore to protect the data in the network you should use ssl in the backend so no one can sniff the credentials.

How to verify signed cookies are valid on the front-end?

I'm working on a React application. I am defining user roles and restricting access to components based on the permissions level of the role. I am looking in to using signed cookies to set the permissions from a php backend. When I determine whether the application should render a component based on the data in the cookie, how do I verify that the roles in the cookie have not been redefined by the user without sending the cookie to the backend?
That's not the right approach, in my opinion. The components should be free to load - if there's something built-in to a component that an un-authenticated user shouldn't be able to see, there's nothing stopping someone from going into the source and discovering it themselves.
You have to take a different approach for front-end applications - all the components and UI are public. When the component fetches information from the server to display to the user, the server will still do the session authentication and respond with a 4xx (401 would be a good place to start) and the component would handle that response appropriately.
If modifying the role in the cookie would allow the user to gain more rights, then the solution is not to check the validity of the cookie on the client side. The user could also modify the client side script to circumvent/skip the integrity check of the cookies, and you would have the same problem as before.
The only correct solution is, that the user won't get those informations/scripts at the first place. So you need to check on the server side what informations are allowed to be send to the client, only send the data the user is allowed to see, and verify all actions the user sends to the server on the server side before you execute them.

Handling JWT expiration and JWT payload update

I have a Koa based Node.js backend for my personal/hobby application.
I implemented session handling with JWT tokens. The client (AngularJS) gets the token after a successful login and stores the token somewhere (currently in sessionStorage but for the purposes of this question it shouldn't matter).
I have two questions:
When I need to update the user record which the JWT represents, say, the user turned on Two-factor authentication (2FA) so I asked him to provide his phone number and I'd like to set this phone number in the user's record. Currently, after a successful verification on the phone number I call my backend to update the user record and I create a new JWT token with the updated user record (I exclude sensitive information from the JWT token like the hashed password, but I'd like to include the phone number for client side usage). Is it okay to create a new token when some of the credentials change and update the existing client side token with this new token? Should I never-ever create another token, only to create the one and only upon successful authentication? How do I then update the payload in the token?
How should I handle expired JWT tokens? In my mind I have 3 (possible) scenarios:
2.1. The JWT is set to short living, say 15 minutes. If the backend server replies with a 401 Unauthenticated 'Invalid token' (I guess this is the default behavior of koa-jwt) then I automatically log-out my client and require re-authentication. But I also set up a complementary middleware, which is the last in the chain on the backend to re-create the token with a refreshed expiry and the client would also replace the existing token with the refreshed one. So if the user is active and uses the application every protected API call, in case of success, would create a new token to replace the old token.
2.2. The JWT is set long-living, say 1 week, and if it expires I opt-in re-authentication from the client.
2.3. Copy https://www.rfc-editor.org/rfc/rfc6749#section-1.5. Here when creating the JWT token after a successful authentication we send an access_token as well as a refresh_token. When the access_token is expired and the server responds with HTTP 401 'invalid token' (koa-jwt default) then the client sends the refresh_token to the backend to require a new access_token (and optionally a new refresh_token). In this case I don't fully understand how the refresh_token is verified against the old access_token to provide a new token? Or why do we need to have a refresh_token?
Any generic advice on the upper topics (JWT updates and JWT expiration) would be helpful.
Starting from the bottom, I would ignore refresh tokens as I don't think they will help you here. They are generally aimed at other scenarios where the client application can provide storage more secure than the user browser -- think native mobile applications or server-side web applications.
Refresh Tokens are long-lived. This means when a client gets one from a server, this token must be stored securely to keep it from being used by potential attackers, for this reason it is not safe to store them in the browser.
(emphasis is mine; source refresh tokens)
This means that option 2.3 is basically the same as 2.2, which is not a bad option. It's not uncommon to have web applications with long session duration. If your application is not highly sensitive it's acceptable to use long session to improve user experience. For example, Django uses a default of two weeks for the age of its session cookie. See SESSION_COOKIE_AGE.
The remaining option (2.1), is usually referred as sliding session. The session timeout is short, but as long as the user keeps using the application within that interval the session gets automatically renewed. This is possibly the most common approach, or at least the one I used most time, so I'm biased. The only thing I would note is that sliding session are usually implemented with opaque session identifiers stored client-side as cookies and then with the actual session data stored on the server.
Your approach is a bit different because you have a stateless JWT token (it contains actual user data) stored on browser local storage. Like you said, in order to update the token you'll have to generate a new one, because you'll have to generate a new signature.
The signature is used to verify that the sender of the JWT is who it says it is and to ensure that the message wasn’t changed in the way.
(emphasis is mine; source JSON web tokens)
Having said all that, I would consider the following:
Ask yourself if you really need JWT's or if regular session identifiers stored as cookies (HTTP Only) would simplify your logic.
If JWT's are a requirement, for example, you have another API that will also accept these tokens as authentications, then I would consider option 2.1 or 2.2 as refresh tokens for a browser-based application are not recommended.
Having said that, you should also consider that JWT's are not huge, but they will still be an overhead if you decide to be automatically renewing. You may mitigate this a little by choosing a session duration of 20 minutes and only perform automatic renewal after half the session has elapsed.
Another point is that a vulnerability like XSS in your application will expose the access token to an attacker as the injected scripts would be able to read from localStorage/sessionStorage, this can be another point in favor of HTTP only session cookie storage.
I would like to answer your second question before I can get on to the first one.
Basically the third option which you have mentioned is the best way to renew your access tokens. Access token should be short living(~5mins) and refresh token has longer life. When your access token gets expired, send your refresh token to the backend and get a new access token. So your response should be something like this:
{
"token_type":"bearer",
"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiVlx1MDAxNcKbwoNUwoonbFPCu8KhwrYiLCJpYXQiOjE0NDQyNjI4NjYsImV4cCI6MTQ0NDI2Mjg4Nn0.Dww7TC-d0teDAgsmKHw7bhF2THNichsE6rVJq9xu_2s",
"expires_in":10,
"refresh_token":"7fd15938c823cf58e78019bea2af142f9449696b"
}
So the idea is to seperate your application into Authorization Server (which generates access token / refresh token) & Resource Server (validate access token and access the resources ). You can maintain a schema to validate the refresh token against the access token in Authorization Server. Please refer to the schema section mentioned in this link which might give you some idea. Oauth2. You can modify the schema according to your need. You need not send your refresh token along with your access token for each request call. Refresh token can only be sent to Authorization server for generating new access token. How to generate refresh tokens? If I am using Java, I would use UUID.randomUUID() to generate a unique refresh token.
Now to answer your first question, if you want to update your JWT payload based on your updated user records, then you can use the same refresh token to generate a new access token with the updated payload. The logic remains same because if phone number exists in the user record it gets added to the payload and if not, it will be null in the payload.
The main advantage of using Refresh token is that the Access Tokens can be renewed at any time using Refresh Tokens

Jquery and ApiGility login strategy

I would like to use Apigility and Jquery as a login strategy into my application. I am struggling to understand how to do this.
My setup is as follows:
The client and the Login api are trusted as they are both part of my application.
What I am struggling to understand is the process of taking the username and password from my form, processing it in JQuery, then using the Apigility authorization strategy to ensure that the request is genuine and to pass it securely onto the required login end point.
I have a standard login form:
The user enters a username and password and clicks "login".
Jquery validates the data and now I need to send the users credentials to the Login End Point... How to do this with ApiGility, I am not sure...
I have been reading the documentation here: https://apigility.org/documentation/auth/authentication-oauth2 and I don't quite get it.
This is what I have setup with ApiGility.
I have created a Login end point in ApiGility
This end point can only accept a Post request.
The end point requires authorization to be accessed.
Now how to interact with this?
As I am using a client side script (Even though it is my own app), I cant use traditional Client id and password as there is no way to secure this information in JQuery without exposing it to the world.
In its place, I should use an implicit grant, i.e. a client identity, with no password.
To get an implicit grant, I need to re-direct the user to Apigilities: http://example.com/oauth/authorize?response_type=token&client_id=testclient2&redirect_uri=/oauth/receivecode&state=1 end point, ensuring I include the user name and password in the post request.
When a user is re-directed, they must click on a yes or a no button, if yes, a token is created and a session is generated (storing the customers username and password) and returned. This token I store on the customers machine, using a session.
Now that I have a token, I use this token to gain access to my secure Login End Point.
Once I have access to the Login Controller, I now use the token to get the username and password from the session.
Finally - check the credentials and return: true / false etc.
How close or far off am I?
1. Yes you can, as long as you use a properly configured (secure) https connection. By using a security certificate you will ensure encryption of the data being sent and received by the client and it will be unreadable when intercepted.
2. When using implicit grant you will still need to authenticate your client with a username and password. Check the workflow here in this OAuth documentation.
My idea is you are missing the fact that you need a secure connection. I would suggest setting up https on your server and then follow the Apigility OAuth documentation. It seems quite complete and I think you should be able to manage by following their instructions.

Categories