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

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?

Related

Acceptable OAuth Flow for a decoupled frontend/Backend Architecture?

I have a NextJS frontend and Golang backend architecture with an authentication system using JWTs and an internal user/password database. I'm adding OAuth sign-in in addition to the JWT system, but all API calls will still be maintained using JWTs. I have a working prototype that uses the following OAuth flow:
User is directed to a NextJS page that displays various login options as buttons.
When a provider is chosen, the user is redirected to the backend at /auth/provider where they are then redirected to the provider with all required keys and callback links.
User logs in at the provider and the redirect is triggered to /auth/provider/callback.
The backend server retrieves the user data from the callback and connects the user email to the internal user data for generating a JWT.
The backend returns a page that stores the JWT in local storage and redirects to a NextJS page.
The NextJS page can then use the stored JWT to make API calls.
An additional step could be to exchange the JWT for a new, non-stored JWT or session cookie if the JWT is used twice (potential XSS attempt) and the new JWT is invalidated.
The above method works, but requires a locally stored JWT. Is this a concern, and is it possible to complete the final steps without the need for a locally stored JWT.
Does this flow make sense or am i going about it all wrong? Would swapping to PKCE be overkill?
For the current prototype I'm using the github.com/markbates/goth example code running as the golang backend and a basic NEXTjs server
In effect you have a form of backend for frontend there. It is worth browsing OAuth for browser based apps a little similar to section 6.2 of the above doc.
One option might be to host the backend at a URL like https://api.example.com, then make it write cookies for the Next.js app, hosted at a URL like https://www.example.com.
In this way the backend and frontend parts of the OAuth flow are decoupled, and you also avoid locally stored JWTs. Note the same domain prerequisite, needed for the cookie to be considered first-party, and therefore avoid being dropped by browsers later.

Store JWT in a NextJS app with a Spring backend

I'm currently building an app using NextJS and some Spring microservices backend, but have encountered some doubts regarding the handling of the JWT.
My problem is that I want to create private pages, so I was storing my JWT token that comes from my Spring backend in an Authorization header and I was storing it on local storage, but when I try to grab my token on ServerSideProps I can't access local storage, so I went to find another solution to where to store my token.
I found out that you can store the token in an HTTP-ONLY cookie, but I have some doubts:
If I save my token on an HTTP-ONLY Cookie in my Spring Security
microservice when the user logs in, it will be available to grab at
any time on my ServerSideProps on NextJS frontend? Or I will have
to somehow save it in my frontend when receiving the response from
/login?
I have an AuthContext which stores the logged user, should I instead ditch cookies and localstorage and just store the JWT here in context and then somehow grabbed it on ServerSideProps, even though you can't access a hook inside there.
I need a little guidance on how people solved this issue using a custom backend, have looked through Google but people mostly use third party auth providers.
Storing cookies in the browser is today a bad idea due to the various security problems that comes with doing that.
A better idea today is to use the BFF pattern as described here:
https://www.youtube.com/watch?v=lEnbi4KClVw&ab_channel=PhilippeDeRyck
https://blog.bitsrc.io/bff-pattern-backend-for-frontend-an-introduction-e4fa965128bf

Where and how to store the access token and refresh token

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);

How to pass CSRF token with the RestTemplate

I have two Spring Boot REST applications. One of the applications calls other with Spring RestTemplate. Lets call these applications server and client app.
Server app is sending XSRF-TOKEN token as cookie, this is done for the UI part. However there's no way (None that I know of) for the server to distinguish between the request coming from browser and a request coming from the client app. So I can not selectively send the CSRF token from the server to browser only.
Is there a built in mechanism in Spring which allows RestTemplate to detect CSRF cookie/header and replay the request?
If not how can I do the same manually? Should I wait for the CSRF exception to occur and then read the cookie fro the response and replay it?
If it were to be done once then it would be OK, however to wait for the exception for every RestTemplate call doesn't seem right.
I may try to store the token once and set in from the next time, however how would it deal with the multiple server app scenario (Which I have to implement next). As CSRF token of one server app would be invalid for the other, so I won't be able to store a single token, but I would have to store a map of tokens which would have an entry for every new server app URL.
This all seems too complicated, I would rather have Spring handle it.
Any clues are appreciated.
Thanks
For now I have implemented a REST service without protection in the server app which can be called to get CSRF cookies. I had to allow session to be created always so that CSRF cookie doesn't change in one session and so that I could avoid the error Could not verify the provided CSRF token because your session was not found.
Client app calls CSRF rest service to get the cookies and then sends it with the next service call.
It seems a much to call the CSRF token service for each REST call via RestTemplate however it saves me from implementing complicated logic of storing the session. CSRF token service just delivers the cookies so it's network call doesn't take much time compared to the actual service call.
I was also thinking of using a persistent storage (SQL Database or Redis) to store the CSRF token for the server app and then let the client app directly read it from the persistent storage.
However I couldn't figure out how to associate the Session + Server app + CSRF token together to identify token needed by client. As client doesn't have the session initially, so it can't uniquely find CSRF token for it's token from the database. This method is complicated further by the fact that RestTemplate doesn't store the session for the next call.

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