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?
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.
Create a table (user_token table) that can store the user_id, access token, refresh_token and even the session_id.
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.
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.
Once the access token is found, the server should return the access token and access token only to the client.
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;
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);
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.
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.
Related
I have created an api in PHP, using JWT. I have set 10 minute expiration time for tokens. How can I verify if user is still logged in after 10 minutes?
Like OAuth providing refresh token along with access token and using refresh token we can generate new access token. But I found that The JWT standard does not have any concept of a "refresh token" or "access token". in one of git thread.
My JWTHandler function to create token:
public function jwtEncodeData($iss, $data)
{
$this->token = array(
//Adding the identifier to the token (who issue the token)
"iss" => $iss,
"aud" => $iss,
// Adding the current timestamp to the token, for identifying that when the token was issued.
"iat" => $this->issuedAt,
// Token expiration
"exp" => $this->expire,
// Payload
"data" => $data
);
$this->jwt = JWT::encode($this->token, $this->jwt_secrect, 'HS256');
return $this->jwt;
}
It is just returning token, any way to create refresh token in JWT? Or I should create it with plain PHP which may contain user id? So, if client receive Invalid token error they can request new token with that user id in refresh token.
Updated:
I have found here Before making any API call, the mobile app checks if the token is about to expire (with the help of the stored values). If the token is about to expire, the app sends the refresh token which instructs the server to generate a new access token but my mobile app(android) developer saying that they have never checked if token valid or not in their past experience. How does it should actually carried out? If I check token is valid or not in API and than create new token if not valid previous one, than I need to send new generated token to mobile app in response? And mobile app needs to check each API response if token is there in response?
I have set 10 minute expiration time for tokens. How can I verify if user is still logged in after 10 minutes?
Access tokens are disconnected from user sessions. The lifetime of an access token has nothing to do with a user's session. It seems to me that in your setup you should rather be using plain old sessions instead of access and refresh tokens.
But I found that The JWT standard does not have any concept of a "refresh token" or "access token". in one of git thread.
That is true because the JWT standard only tells you what a JSON Web Token should look like, how it can be signed for integrity protection (through the JWS standard), and how it can be encrypted for privacy (through the JWE standard). JWTs can be used for many different purposes, and access and refresh tokens are just one such purpose.
any way to create refresh token in JWT
JWT is not a framework that you can use to create refresh tokens automatically, consume them, etc. OAuth and OpenID Connect are standards that define how to deal with access and refresh tokens (what are the flows which allow you to issue those tokens, and how to properly refresh access tokens). You can have a look at the refresh grant from OAuth. It describes what you need. Basically, you need to issue another token (it may be a JWT) and send both to the client. When the client needs to refresh the access token, it sends the refresh token to a special endpoint and gets a new access token (if the refresh token is valid).
Again, in your case, I feel that implementing OAuth refresh flow will be a bit of an overkill, and I would definitely have a look at sessions.
How does it should actually carried out? If I check token is valid or not in API and than create new token if not valid previous one, than I need to send new generated token to mobile app in response? And mobile app needs to check each API response if token is there in response?
It's not exactly accurate. You should validate the token in your API. If the token is expired (or invalid for other reasons), the API should respond with a 401 response. This is a sign to the mobile app that the token is no longer valid and that it needs a new one. If the app has a refresh token, then it can use that token to get a new access token. The mobile app can now call your API again, with a new access token. If the app doesn't have access to a refresh token, or if the refresh token is expired, then the app should ask the user to log in again.
you need to look at the OpenID Connect (OIDC) protocol, which defines how refresh token, id token, & access token work together.
I am working on a project which I need to integrate an api. The API's website requires that every request to their API be authorized by an Authorization token.
My problem is how to save the Authorization token safely and regenerate the token after expiration, so that the users of my website are able to use the Access token for their requests.
The token expires in 2 hours
Below is my request to obtain authorization token and the response.
response = unirest.post("https://webapisite.com/merchant/access",
headers={ "Accept": "application/json" },
params={ "apiKey": "my_api_key, "secret": "my_secret" });
I will receive below json response
{
"status": "success",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MTQwLCJuYW1lIjoic2F2YW5hIHNtYXJ0c2F2ZSIsImFjY291bnROdW1iZXIiOiIiLCJiYW5rQ29kZSI6Ijk5OSIsImlzQWN0aXZlIjp0cnVlLCJjcmVhdGVkQXQiOiIyMDE2LTEyLTA4VDEwOjM4OjE5LjAwMFoiLCJ1cGRhdGVkQXQiOiIyMDE3LTA2LTE0VDEzOjAxOjQ5LjAwMFoiLCJkZWxldGVkQXQiOm51bGwsImlhdCI6MTQ5ODMzNTE2NSwiZXhwIjoxNDk4MzQyMzY1fQ.WojvkYOC2j6XTUfg_E4WQkxQChPUyCgYUCIKaW83YXA", // a valid merchant token
"config":{}
}
Perhaps the most commonly used standard for use cases like this is OAuth 2.0.
OAuth is a widely-recognized protocol on top of HTTP that is used to issue tokens to clients after successful authentication (see also: "What is the difference between authentication and authorization?" on ServerFault). It provides different "flows" to obtain the tokens by, the most suitable in your case would probably be the "Resource Owner Password Credentials Grant" flow. Clients can then use the tokens given to them to make the actual API request.
Storing the tokens is usually done in a database. In truly stateless applications, JSON Web Tokens can eliminate the need to store tokens on the server-side.
Its always better to save Token in DB and stored in session too.
With every request you can get token from session and track session activity by DB stored session.
Basically this kind of things part project flow, so according to project need and flow with aspect of security we can take decesion.
You should save this token in DB.
In one table, save the access token, auth token and expire date.
You can save multiple records if you want, but if you have only one auth token, one record is enough.
Before every call to that API, you check in the DB if the available access token is still valid, if it's not, you must renew the access token through the auth token.
I couldn't understand which language are you using to this task.
If javascript, you can make a post for your backend, asking for the latest valid token.
Hope that helps.
I have a client application that use the oauth2 with authorization grant type resource owner password credential. I write a curl http request to obtain the access token when user provide her credential, but how to request another access token when the first one expired. I read that it's good to estimate the validity of the access token. I found this client library but I don't think it will solve my problem related to requesting a new access token once it expire or even when the refresh token expired too.
Can anyone point me to the right direction how to implement this or use a library for that purpose please?
Instead of checking token expiration for every resource request, you can handle token expiration error and perform a Refresh Token request to get a new access token.
oAuth server should normally mention invalid_grant in its response when access token is invalid, expired, or revoked. Refer here. You should check with your oAuth server what response it provides exactly when a token is expired.
Some libraries does include this feature but I do not find for the library you mentioned. I used Retrofit as java client and it has this. You might want to request this feature for the library you mentioned.
If a refresh token is expired, the oAuth authorization flow should start over again.
the OAuth2 token you receive will have the duration in it. Each token expires after a set amount of time and that information is sent back as part of the object you receive. So you can store it locally and reuse it until the expiration time passes.
Once it does expire you have two options :
Request another token
Refresh the existing token. A lot of the OAuth2 providers offer this functionality.
The only question is if the library you are using has that built in. If not maybe you can add it yourself.
Edit
if you want to store the token somewhere then Session will work. The Session does not expire when the user closes their browser bit when it hits the timeout expiration set on the host itself. To be fair if they reopen the app later, they will have to login again at which point you can request another token. If you decide to use the Refresh Token functionality then it makes sense to store that in the database itself and use it from there as this is a long term thing not something that is session based.
Hi I am creating mobile native application that uses REST API endpoints to communicate with server side.
I have had previous experience developing native clients, but I have simple token (random generated string) stored in DB in the same table where user information is stored. So it is like sessions used in browser, but instead of cookies each request has token in the header.
Recently I discoreved JWT token. It seems to be great way to secure endpoints which are private. You can request token from mobile client providing you pass + login and get generated token in response.
But the one important thing is that this token is not stored anywhere on the server, server verifies the token using secret word, which is private for the server like private key.
That's okay for secured endpoints, but what to do if I require user session, for example how do apps like Facebook, Amazon, Aliexpress ... work, they have ability to use the app without providing credentials, just navigating through the store, but require logining in when user want't to make purchase. And after that user session is kept for some time.
This can be implemented with the JWT token without any problems, but when user need to logout, what to do in this case ? Token is not stored anywhere on the server, so how can I destroy this token, to make it invalid ?
If token is stored in the database, API is not stateless, as REST API should be.
So in general there is no way to keep user logged in in stateless API, am I right ?
I have some ideas how to implement this using JWT token, but again this will not be stateless API, as I understand.
Create the list of expired tokens
Store JWT token in the database, but what is the purpose of self descriptive token (JWT) in this case if it is stored in the database, the main idea of JWT token to keep all information with token, as I know.
Please suggest what is the best way will be in this case, and correct me if I have mistaken.
Thanks.
If you're using JWTs, then you can't have a server side state in order to properly logout the user without defeating the purpose of using JWTs in the first place. The best option though if you want to do this is to have a last logout date stored in the DB and in the JWT, and if these don't match you logout the user (without updating the date in this case). However, you now have server side state.
Storing logged out tokens in the DB seems like overkill though.
An alternative option is that you could generate a 128 bit token generated by a CSPRNG, store this using SHA-256 in the database, and then use the unhashed value in a web token. This way you can simply delete the entry in order to logout the user server side. This is the more secure option as you now have a way to properly expire tokens and sessions on the server. If a user changes their password, or wants to secure their account by logging out other sessions you now have a way to do this.
JWT authentication is basically happens on both the client side and server side.
When the user sends Username and password to authenticate. its checked against the db and if valid a joken is generated and sent back to the user. There are multipe API's for generating the JWT token, you can check out http://jwt.io/
Once the token is generated and sent back, it needs to be sent along with header in each request and needs to be validated, on the server side, before serving the API back to the user.
There is no need to store the the token as the API itself will allow you to decode it on the server side.
How i am doing it:
I generate a random id (I call it validation code) and store it in database when user signup, encode it in jwt.
Whenever any request is made with jwt, I check the validation code, if it is correct: access is granted.
To expire the session like after changing password, I change the validation code in DB.
If you need to logout a user, provide a logout link. The server should reset the session data by encoding the token with any empty array for example. The user will have a valid session but will not have the valid information to validated them.
Valid Token at login
$data = array("id"=>1,"user_type"=>"Admin");
$token = JWT:encode($data, $key);
Validating Token
$token = $_POST['token'];
$data = JWT:decode($data, $key, $hash);
if($data.id){
return "valid token";
}else{
return "invalid token"
}
I am working on a PHP project that utilizes the API from a few services. For a single API, it uses OAuth 2.0 authorization to authenticate the application's API access. However, I am unsure how I should approach the process to authenticate a local console application.
I would not be using a webflow to authenticate the API, as my PHP script runs in a local console. The API allows for the retrieving of the access token and refresh token by entering my username and password (they recommend this only for console applications).
Once I get the access token, I may use it to make API requests. This works fine. However, I am unsure what to do with my refresh token. The API consumes refresh tokens as such:
/oauth2/access_token/ (Refresh token usage)
Context: Client's Web Server
Required arguments: refresh_token, grant_type=refresh_token,
client_id, client_secret
Access token scope: None
On success, a JSON response is returned to the client:
{
"access_token": a valid access token,
"scope": scope as given in authorize,
"expires_in": seconds to expiry,
"refresh_token": a token that can be used to get a new access token
}
Consuming a refresh token will immediately expire the related access
token. Refresh tokens are single-use. A new refresh token is returned
from this call, ready for consumption later.
From what I gather from this, my authentication process should be something like this:
Initial authentication - pass username/password via environment variable, get the access/refresh token from response
Store the refresh token? Check for the expiry of the initial access token
If initial access token has expired, pull refresh token from file and make a request for a new access/refresh token
Store new refresh token?
Does this sound like the correct authentication flow? Is there a specific way I should be storing the refresh token? I am aware there may be a lot of security concerns for simply storing the refresh token in a text file, as it has the ability to give complete access to my account. Are there any better alternatives?
Thanks!
Authentication flow is fine. For more detailing and validation, you can read https://www.rfc-editor.org/rfc/rfc6749 .
You can store ‘Refresh token’ either in file or db using encryption key and this MUST only be transmitted using TLS. ‘Refresh token’ is used in senerios where server do want to some scheduled background activities like accessing of profile and related data from other oAuth server based on previous stored access token without asking user name and password again over and again. If in case ‘Access token’ is invalidated then ‘Refresh token’ will be used to get new ‘Access token’ to serve purpose.