What's the best option for session management/csurf/Firebase with 3rd party cookies not being allowed in Safari, Chrome on mobile - node.js

I've had my log-in and authentication set up in a React app with Firebase Auth and a Heroku hosted server. It's all been working well. I've now tried the app on different browsers and found that my log-in feature doesn't work at all on Chrome on mobile, and also on Safari. When I log in on Chrome, I get the usual log-in screen, followed by the Firebase Auth redirect, and then I'm redirected to the log-in screen with the following message in a yellow pop-up:
"This browser is not supported or 3rd party cookies and data may be disabled"
I'd been following the csurf and jwt middleware documentation for my sessions, and I'm wondering whether it's best to rewrite my session code to accommodate for cookies not being fit for purpose when my server is hosted on a different domain to my React app. Alternatively, should I do away with Firebase Auth?
Having spent a few months working through different problems, I'm perplexed as to why cookies seem to be the preferred option for the middleware I've used (when they seem to give you nothing but grief), and also, why Firebase Auth doesn't accommodate for use of cookies (since they're the preferred option in middleware documentation).

I'm not sure what the best option is, but the best one I've determined is to use jwt authentication, as per:
This PERN tutorial by Henry at FreeCodeCamp and then combine it with this Firebase Auth tutorial by Maksim Ivanov (and also remove the cookies and csurf functionality that Maksim introduced).
Apparently Safari don't allow 3rd party cookies, which makes it very difficult to use cookies for authentication between servers. There are workaround provided in the other responses in that link, although they all seem a bit convoluted to me.
I've also seen a post on Stack suggesting that CSRF wasn't required if using with Firebase Auth, since it has implicit CSRF protection within it. Although I wouldn't take my word on that one.

Related

PKCE using backchannel to refresh token

I have a project that uses node-oidc-provider and angular-oauth2-oidc.
However one thing is wierd, refresh token request uses prompt=consent (I know it is by spec) which returns 303 with location including code in the hash, the token is refreshed but it looks like terrible UX if SPA appplication refreshes in middle of user interaction, is this expected behaviour or is something in my configuration wrong?
Is there any way to get refresh token through backchannel like AJAX request (I would like to avoid iframes if possible)? I can't find any specs on how it should work.
OPTION 1
The traditional SPA solution is to use an Authorization Code Flow (PKCE) redirect on a hidden iframe using prompt=none. This prevents refreshing the SPA since it runs in a mini app as in this code. This is no longer reliable though, due to recent browser restrictions that drop the SSO cookie - eg in Safari.
OPTION 2
Another option is to use a refresh token grant message in an Ajax request. But this relies on storing a refresh token in browser local storage to get past page reload issues. And this is not considered secure and is not likely to fare well in PEN tests etc.
OPTION 3
The preferred option these days is a variation on option 2 where the refresh token is stored in a secure HTTP only encrypted cookie. It is possible to issue cookies via an API, if you want to avoid impacting the web architecture, though it is a little tricky. See this Curity blog post for more on this approach - and this code sample.

Silent Renew with oidc-client cross domain, if third party cookies are blocked

We have two SPA Application, which interact with the same IdentityProvider.
We implemented the oidc-client and SSO worked fine. Now we recognized that silent authentication is not working if third party cookies are blocked, which is a big problem.
Browsers like Safari, Firefox are already blocking third party cookies by default. What is the recommended way to do the Session_Management and Access_Token Management in a SPA Application.
We don't want Users to Login again, if the Session on the IdentityProvider is still active (Session is Active for 14 days with a sliding expiration).
What are my options?
Based on the comments on the OP and having experimented a bit... If I set the auth cookie to SameSite=Lax then iframe-based silent calls do not work but top-level redirects are not affected. Therefore SameSite=Lax breaks OIDC and thus it's necessary to have a comprehensive CSRF solution in place instead if you wish to use the standard client side pattern.

Best way to handle authentication on a react-redux single page appliction?

I'm currently sending the client an empty html document with a few scripts included that set up my single page application with react-redux. After everything is set up I'm fetching the dynamic data using AJAX and determine if the user is logged in or not. If the user is not logged in, he will see the products available only for users that are not authenticated and conversely.
Even though I am a noob, this seems extremly primitive to me and I don't know how I can do this better.
So what is the best way to handle authentication in react-redux applications?
Thanks a lot for helping.
There's a few options:
Passport which you can install through npm and it has a variety of strategies you can authenticate through such as Auth0 Link here
Firebase - a solution that google has that can be used as a drop-in authentication module. Link here
Meteor framework - I believe this framework has multi user authentication. Link here
First, for authentification you need to have a token or session id on the client side. So, there should be next steps:
After login, you receive token|session_id from backend and put it to the store and also to the localstorage not to lose it after page reload.
While initializing your app, get the token from localstorage and put it to the store every time.
When you do request for products list, add the token to ajax request (usually in headers).
Based on token, back-end application should returns another list of products.
It is a regular logic for such situations and of course it requires work on back-end side as well.

Passing google identity from chrome extension to my node.js app

Overview: I am trying to understand the interactions between OAuth security in my server and in my chrome extension. I think I have 90% of the answer working, but I'm missing a bit. I'd like to find the cleanest way to finish my implementation using existing tools, rather than reinventing any wheels.
Background: I have a node.js app that uses passport, passport-google-auth, and express-session to authenticate users. I save per-user information, keyed by the user's Google identity. This works fine. My web pages can exchange data with the app, and the Google login screen pops up correctly in exactly the cases I'd expect.
I also have a chrome extension, which includes a browser_action popup that needs to write data to my node.js app and a content_script that needs to read data from my app.
My extension already uses chrome.identity.getAuthToken to get the user identity.
For testing, if I ignore security, I can pass this id to my node.js app, and access the info I need.
But, this is no good, of course. I want my node.js API to be locked down, only letting in clients that have the cookie generated for me by passport.
Side note: I imagine, instead, that I could do some song-and-dance wheel reinvention and pass the id securely to my server via https. But this seems completely wrong, right?
Question: I assume that my chrome extension really should be doing the OAuth2 dance directly with my node.js app. But, I don't know what piece I should be using, or how to cleanly play with chrome.identity. I suspect that I'm just missing a small bit of wisdom, but I don't know what it is.
Side comment: Because cookies are shared between browser tabs, I can (clumsily) achieve what I want by simply connecting to my node.js app from another tab in the browser. So, I guess I just need to get the same behavior from my extension background page.
It looks like the easiest answer for me was to use the Stormpath APIs for this. It took some effort, but was reasonably straightforward.

JSON Web Token Auth Service - checking status on separate server to protect routes. NodeJS

For a project I’m working on currently I am developing an API using Node/Express/Mongo and separately developing a website using the same tools. Ideally I want to host these on separate servers so they can be scaled as required.
For authentication I am using jsonwebtoken which I’ve set up and I’m generally pleased with how it’s working.
BUT…
On the website I want to be able to restrict (using Express) certain routes to authenticated users and I’m struggling a little with the best way to implement this. The token is currently being saved in LocalStorage.
I think I could pass the token through a get parameter to any routes I want to protect and then check this token on the website server (obviously this means including the jwt secret here too but I don’t see a huge problem with that).
So my questions are
Would this work?
Would it mean (no pun intended) I end up with ugly URLs
Would I just be better hosting both on the same server as I could then save the generated token on the server side?
Is there a better solution?
I should say I don’t want to use Angular - I’m aware this would solve some of my problems but it would create more for me!
First off, I'll answer your questions directly:
Will this work? Yes, it will work. But there are many downsides (see below for more discussion).
Not necessarily. I don't really consider ugly urls to include the querystring. But regardless, all authentication information (tokens, etc.) should be included in the HTTP Authorization HEADER itself -- and never in the URL (or querystring).
This doesn't matter so much in your case, because as long as your JWT-generating code has the same secret key that your web server does, you can verify the token's authenticity.
Yes! Read below.
So, now that we got those questions out of the way, let me explain why the approach you're taking isn't the best idea currently (you're not too far off from a good solution though!):
Firstly, storing any authentication tokens in Local Storage is a bad idea currently, because of XSS (Cross Site Scripting attacks). Local Storage doesn't offer any form of domain limitation, so your users can be tricked into giving their tokens up quite easily.
Here's a good article which explains more about why this is a bad idea in easy-to-understand form: http://michael-coates.blogspot.com/2010/07/html5-local-storage-and-xss.html
What you should be doing instead: storing your JWT in a client-side cookie that is signed and encrypted. In the Node world, there's an excellent mozilla session library which handles this for you automatically: https://github.com/mozilla/node-client-sessions
Next up, you never want to pass authentication tokens (JWTs) via querystrings. There are several reasons why:
Most web servers will log all URL requests (including querystrings), meaning that if anyone gets a hold of these logs they can authenticate as your users.
Users see this information in the querystring, and it looks ugly.
Instead, you should be using the HTTP Authorization header (it's a standard), to supply your credentials to the server. This has numerous benefits:
This information is not typically logged by web servers (no messy audit trail).
This information can be parsed by lots of standard libraries.
This information is not seen by end-users casually browsing a site, and doesn't affect your URL patterns.
Assuming you're using OAuth 2 bearer tokens, you might craft your HTTP Authorization header as follows (assuming you're representing it as a JSON blob):
{"Authorization": "Bearer myaccesstokenhere"}
Now, lastly, if you're looking for a good implementation of the above practices, I actually wrote and maintain one of the more popular auth libraries in Node: stormpath-express.
It handles all of the use cases above in a clean, well audited way, and also provides some convenient middlewares for handling authentication automatically.
Here's a link to the middleware implementations (you might find these concepts useful): https://github.com/stormpath/stormpath-express/blob/master/lib/authentication.js
The apiAuthenticationRequired middleware, itself, is pretty nice, as it will reject a user's request if they're not authenticating properly via API authentication (either HTTP Basic Auth or OAuth2 with Bearer tokens + JWTs).
Hopefully this helps!

Resources