Udders
Udders

Reputation: 6986

laravel 5.3 passport and angular storing access tokens

I am authenticating users to consume my own API (so a trusted source). What I am struggling to identify is where is the best place to store the return access_token on the client side? Do I create a cookie, or save the data in localstorage?

Also should I only store the access_token, I should I record the refresh_token? What is the refresh token used for?

Upvotes: 4

Views: 3959

Answers (2)

JGCW
JGCW

Reputation: 1529

It is safer if you only store the access token on the client side even if your refresh token expires after a certain period of time although doing this decreases the possible attack window.

This is one way of doing it (if you want to store access & refresh tokens):

https://stackoverflow.com/a/18392908/5549377

However there is another way of doing it. In this way, the client will only get the access token and refresh token is completely hidden from the user. But inorder to do this, the access token as well as the refresh token should be stored in the server side. The best place is in the database. This raises the obvious question: security? Well the answer to that is you can always encrypt the data that is being store in the database and secure your database as much as possible.

  1. Create a table (user_token table) that can store the user_id, access token, refresh_token and even the session_id.
  2. In every login check if a record is existing under the user_id in the user_token table. If it does not exist, request the oauth/token and store the access and the refresh token in the user_token table.
  3. After the login is successful, you can write a .run function in your angular to request for the access token for the user. (remember in the user_token table we had a "user_id" column. Hence you can request filter the current logged in user from the Auth::id() function in laravel.
  4. Once the access token is found, the server should return the access token and access token only to the client.
  5. After the client received the access token, you can do a handshake call to the route which is protected under 'middleware' => 'auth:api' by adding the recieved access_token to the header like this :$http.defaults.headers.common.Authorization = 'Bearer ' + data.access_token;. Also after doing that make sure you add the same token to the a rootscope variable like this:$rootScope.accesstoken = data.access_token;
  6. If the handshake call is successful, then you can add valid access token from the rootscope to an angular cookie like this : $cookies.put('access_token', $rootScope.accesstoken);
  7. If the handshake call is not successful, you can request a new token. To request a new token, use a new route that will redirect to a seperate function. This function will fetch the refresh token under the user_id of the current user and request a new access token from the oAuth end point (refer Passport API docs). Once you do this update the record under the user in the 'user_tokens' table and return the new access token to the web client. On the webclient side, store the recieved token in the angular cookie like this: $cookies.put('access_token', $rootScope.accesstoken); and add that same token to the http headers liek this: $http.defaults.headers.common.Authorization = 'Bearer ' + data.access_token;

By the way why did I mention that I should store the token in the angular cookie. Well if you store it only on the rootscope, if the page refreshes, the app will have to request for a token again because whatever the data in the angular rootscope is lost after refresh. But in the angular cookie, it is not. hence this is why I suggested to add to the angular cookie.

Very important:

For every ajax request you make, if the request fails under the code 401 (unauthorized access), you should call a request new token function from angular to Laravel's request new token function. And once it is successful, insert that new token to the http header and the angular cookie as I mentioned.

Note:

The point of the refresh token is to verify that you are the authenticated user for the old access token (let's call the token xxx).

You can use the access token as long as it expires. Once it does you need to tell the server that you cannot been using this access_token xxx and it is expired now, so give me a new token. When you make this request (to give you a new token) the server should know you are the legitimate user of the previous access token, so the server will ask you to prove that you are legitimate. At that time, you can to present the refresh token and prove the server that you are legitimate. This is the use of the refresh token.

So how will the server verify you are legitimate by the refresh token? initially when you requested the access token, you are given the refresh token so in that case the server will know.

I suggest you read and learn more on OAuth 2.0.

Upvotes: 2

João Angelo
João Angelo

Reputation: 57718

I recently went through some client-side options for token storage so I'll refer you the answer provided in: Where to save a JWT in a browser-based application.

Long story short, both cookies and Web storage are suitable options for storing access tokens and the right choice depends on your exact scenario.

In relation to what you should store, it's usually just the access token mostly because refresh tokens are not typically issued to browser-based applications because they are long-lived credentials meaning the time available for someone trying to steal them is highly increased and the browser storage options all have their deficiencies.

The refresh token is also of particular interest when a client application wants to have access to a protected resourced owned by the end-user even when the user is not interacting with the application; usually referred to as offline access. Most scenarios for browser based applications still imply that the user is online so lack of refresh tokens is not that a big of a deal.

Upvotes: 0

Related Questions