Where and how to store the access token and refresh token - asp.net-core-mvc

I have a dotnet core 2.2 MVC web application which uses a web api to perform some database queries. I have implemented JWT token based authetication for web api. Tokens are generated at the api and the web application has received the access token, expiry and refresh token. I need to store this token details at my client , so that I can either use it to access web api(before expiry) or generate new token using the refresh token if the token expires.
Any help on this would be appreciated.

You have various options (secure http-only cookie, localstorage, session storage, etc.).
In the most simple scenario, you can store it in a cookie so that it is sent along with each request :
The cookie should always have the HttpOnly flag to prevent XSS attacks in the browser.
The cookie should also use the Secure flag in production, to ensure that the cookie is only sent over HTTPS.
Protect your forms against CSRF attacks (by using ASP.NET Core’s AntiForgery features, for example).

Previous answers don't provide clear explanation about the reasons of using those solutions.
Typical systems look like on the picture below and there are two common Client Application architectures used in WEB:
Singe Page Application running in browser
Server side MVC application
In case of SPA the tokens are stored in browser (session storage or local storage) and are cleared automatically by either browser or the app itself when expire. FYI, obtaining refresh token is not possible in SPA because of security reasons.
In case of MVC app (your case) the things get more complicated. You have two options: either store it in http-only cookie or some external session store. Aspnet core supports both cases but each has caveats. A good article here. In short, if your are concerned about cookie size then use Distributed Session Storage which adds more complexity to the system architecture. Otherwise cookies is the easiest solution and is enabled by default in aspnet core, you just need to set options.StoreTokens = true and options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme.

There are multiple ways to store the tokens. Usually applications doesn't store access token anywhere, but they do store refresh token in a permanent storage.
Let's take a look at what you need to store at web and api end.
First, user will request to login in web application with credentials, web app will pass this request to the api project - which interacts with DB.
Now, api will generate access tokens and refresh token and the save refresh token to that DB. Web api then need to store access token and refresh token in temporary storage like cookie or session.
When access token is expired; you need to make a call for a new tokens, which will update the previous refresh token in the DB.
TL;DR
Refresh token - in DB
Access token and refresh token - web temporary storage

Make the call from ui to web application server(controller) controller which in turn makes call to get the token from api.
get the token from api response and store it in cookie.
you controller should look something like this
var option = new CookieOptions
{
Expires = DateTime.Now.AddMinutes(response.ExpiresIn)
};
if (!string.IsNullOrEmpty(domain))
{
option.Domain = domain;
}
Response.Cookies.Append({cookiename}, response.AccessToken, option);

Related

Parse Server - Where do you store session token in single page application?

I have an Angular4 SPA + Parse Server. Currently, I'm implementing authentication with Parse.User.logIn(...) and Parse.User.logOut(...) directly on web page. The thing that I am worried about is storing session token received from logIn() method in Angular app. Whatever is stored on client side (even local storage or session storage) is prone to XSS attacks.
The only workaround I see is to implement custom login and logout methods in cloud code. On successful login cloud code could store session token in a cookie (secure, httpOnly) and would on every subsequent request parse token from cookie and set it in request as header "X-Parse-Session-Token", and then Parse Server logic would take over.
I guess this would work but I'm wondering how are you guys solving this problem. Where are you storing the token on web page?

Spring Oauth Token storing mechanism

I'm trying to implement Spring OAuth. I'm new to it and I'm trying to understand how it works.
My Questions:
OAuth generates token after authentication and this token must be used for every request the user makes. We need to append this access_token to each REST API call for accessing the resources. Did I sound correct?
Do we need to store this token on client side (using cookies)? or is there anyway so that we do not need to store this token at client side and can be handled on the server side?
If we have to store the token on client side what's the best way to do it? I have gone through this link
If endpoint on your server is protected by oauth, then yes, you have to pass token with each request - probably in "Authorization: Bearer {token}" header. In spring its solved by using different restTemplate - OAuth2RestTemplate which automatically fetch it and add to request.
You just store just JSESSIONID in a cookie. Then spring read session from store ( disc where tomcat is installed / redis if you use spring session project/ etc )
Access token should be relatively short living. There should also be revoke endpoint available so you can invalidate specific token when there are reasons to believe it was compromised.
3.a) there is another issue with storing some data on client side. Its about storing clientId, clientSecret on mobile native apps. Android apps code can be reverse engineered quite easily, so anyone can then try to use your oauth app to get token. In those situations its recomennded to use different grant type "password" - check https://aaronparecki.com/2012/07/29/2/oauth2-simplified#other-app-types

How to protect REST API when using AJAX?

There are SNS application with 2 servers. Web backend server and REST API server.
The web server allows user login/logout with username/password, and show user information
The REST API server provides APIs like /topics, /comments, it should be stateless without session
The REST API will serve other web applications
There are some potential solutions, but neither is security.
Base Auth, the browser hold the username/password
Token with expiry timestamp, the problem is user could stay on the page until token expires
So, is there a way to protect the REST API when calling it from AJAX?
If I have understood your problem correctly I may suggest you use the Token solution. In order to maintain security you may generate new token on every request (& send it to client in response), which should be used to make next request, and disable token if it is once used or has expired.
Sorry, I meant to mention it as a comment, but I don't have enough reputation.

Why should the GITkit.idToken be replaced by a Session Token?

The GitkitDemo on GitHub says
Now use the idToken to create a session for your user. To do so, you
should exchange the idToken for either a Session Token or Cookie from
your server. Finally, save the Session Token or Cookie to maintain
your user's session.
In the sample code from the answer to the question Validating OAuth2 token obtained on Android device via Google Identity Toolkit (GitkitClient) on 3rd-party backend (custom python backend, non-gae)? the backend-server token verification of the token obtained through Android seems to be enough to ensure having a valid, secure token which can be added to the Android client headers during any follow-up communication with the backend.
So why is there a recommendation to you should exchange the idToken for either a Session Token or Cookie from your server?
Is this due to the size of the idToken (almost 1KB, IIRC)?
Which recommendations exist (the simplest and most secure way) to generate such a Session Token?
Are there any other arguments against using the idToken as a Session Token other than the size?
Can the Session Token be the first part ("token") of the idToken ( idToken.split(".")[0] in Python )? Or the payload (idToken.split(".")[1])? Or maybe creating a SHA1 of the idToken? EDIT: Ok, I realize that using the JTW header would be stupid, but the payload has at least a couple of variables (iat and exp and possibly as well the user_id), but the signature?
The token/cookie created by gitkit.js ("gtoken") is the idToken itself, should that one be replaced by a session token as well?
There are several reasons for the recommendation to use your own session token/cookie:
1) Most existing web server frameworks have their own session management mechanism (cookie generation with expiration time etc.). The common approach is to generate a random string as session id, and associate the server-side user activities with the session id. The server then instruct the browser to set a cookie of the session id. It is unnecessary, and sometimes very hard, to replace that mechanism.
2) As you mentioned, the IdToken is much larger than normal session cookies.
3) Currently the Google Identity Toolkit IdToken will expire after two weeks.
Other than these consideration, the IdToken is secure enough as the session token. Be sure -not- to use any sub-part of the IdToken as the session cookie, since attackers can easily create a fake one.
If your server issues its own session cookie, you should delete the gtoken after the user session terminates, so that the Sign In button state of the gitkit.js is kept sync'ed with your server.

OAuth access token and page refreshes

I can see OAuth working well for a fully Ajaxified application, as the local JS code can always replay the Bearer token to the server. However, what happens if we have a page refresh? In that case I assume we lose the token and then go back through the OAuth redirect process to get yet a new access token issued. Is this correct, and are there patterns to avoid this, such as storing the access token in HTML5 local storage?
If you're talking OAuth 2.0 then you can probably request both a refresh token and access (or Bearer) token when you authenticate with the OAuth 2.0 provider. The refresh token should be returned directly to the server hosting the web application, stored somehow (perhaps session state) and NOT ever exposed to the browser. The browser can use the access token to make requests to secured services/endpoints which require it but it should have a short lifetime (regardless of whether or not there was a page refresh). When it expires (again may or may not be due to a page refresh) the client application can make a request to the hosting server where the refresh token was delivered. The server can then use the refresh token to get a new access token WITHOUT the user needing to login again.
There's a diagram of this in the refresh token section of the OAuth 2.0 spec.
There are several variations of how OAuth 2.0 can be used and details may vary with your particular scenario and implementation but hopefully that gives you a high-level idea of how you can avoid prompting the user to re-authenticate when the access token expires or on page reload.

Resources