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

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.

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.

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

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.

Using Ory/Kratos login/registration API flows

In the documentation, there is a large, bright red warning:
Never use API flows to implement Browser applications!
Using API flows in Single-Page-Apps as well as server-side apps opens up several potential attack vectors, including Login and other CSRF attacks.
The documentation does not elaborate on what these attacks are. If I properly secure my application by storing session data on the server, by allowing only the server to access this API, and by implementing my own csrf protection, am I safe? If not, what attacks am I opening myself up to and what additional measures should I take?
Certainly, there must be a way to secure my application without tearing down the running javascript vm then sequentially being redirected three times just to view a login/registration page. For modern apps, I think users may expect this discontinuous transition for successful authentication, but I don't think it's necessarily expected for just viewing the login/registration page.
There are two ways to use Kratos.
From a WebApp (browser)
From a Native app (iOS, Android...)
The first way is using browser redirects and they set csrf tokens.
The second way does not set csrf tokens since there is no browser involved.
That's why there is a warning stating that any sort of "browser" related application should never use the methodology from the native app flows and vice versa!
For example here is how you initialise the login flow for API clients (native apps)
https://www.ory.sh/kratos/docs/reference/api#initialize-login-flow-for-api-clients
And here is an example of how you initialise the login flow for Browser clients
https://www.ory.sh/kratos/docs/reference/api#initialize-login-flow-for-browsers
The selfservice configurations are for your browser redirect flows (so Browser clients).
All credit for this answer goes to https://github.com/Benehiko.
For more details about the warning, please visit the kratos channel.

Securing oauth bearer token against attacks such as XSS, CSRF in javascript apps

I am a bit unclear about how to secure (or protect) bearer tokens when using pure JavaScript applications.
I know when user request token to the server it can come with a validity of 14 days or 24 hours. but once the user has token there is no neat (assured) way of securing this from XSS or CSRF attacks (am I missing something?).
Now lets say user is logged into the web application and the browser has this token which is valid for 14 days. If the user is accessing another web application which is trying to do XSS (or CSRF) then the token is exposed to the third party application and this application can make calls to the my application using this token (?)
I have tried to search online but nothing concrete (or something which is easy to understand) coming up for pure js apps and how to protect the token. Or there isn't a good way to do it in js atm. and you just hope (and pray) that the attack will not take place within the validity of token (i.e. 14 days :|)?
Any thoughts or inputs are welcome to this.
Thanks
Edit: It prob. goes without saying but we are assuming the use of SSL certificate.
So, a very quick summary. CSRF occurs because a request to a HTTP end point automatically includes cookies (as it should) plus required headers as described by the server and doesn't require a user to physically do something. They simply visit a web page with the CSRF vector on.
CSRF is generally said to be possible if there is no use of a unique "secret" passed firstly to the client and back to the server to verify that the user indeed intended to make the call. Generally speaking, web browsers are shaping the main ways to protect against CSRF for any type of application. CSRF on OWASP
As you've pointed out, you use a bearer token (sent as a HTTP header) - but you are still protected because requests need to originate from the same origin by default. IF the server allows calls from all origins which is returned in the HTTP headers (which tells your user's web browser if it is allowed) then on their heads be it Same origin policy here.
As for XSS, as long as your cookies at the very least have the "HTTP" flag they are invisible to javascript code on any page the user visits anyway. Plus strictly speaking XSS vectors including the theft of cookies for your site would need to be performed on your site generally speaking. Off the top of my head I can't think of anyway to steal them unless a user is physically on your site. If you set the "Secure" flag this is even better as it forces "Server" only too and ensures the cookie will only be sent when a TLS/SSL connection has been established. XSS on OWASP
Here is a screenshot of cookies listed with the Secure and HTTP flags:
As an extra, make sure you always enforce TLS connections as otherwise they could become victim to a MITM (Man in the middle) attack on a public WIFI network that forces a protocol downgrade to a weak version of SSL that is susceptible to POODLE or non at all. Please read up on HSTS as it will most definitely reinforce everything I have mentioned and really help to prevent the token from being stolen HSTS OWASP and HSTS info wikipedia

What's the best way to support Facebook login in a secure way and avoiding eavesdropping from a malicious user?

Facebook has done great work on preventing eavesdropping (with tools like Firesheep) by supporting https on all facebook.com pages, but does not provide similar levels of security for 3rd party sites.
Right now it's possible to eavesdrop the traffic from a 3rd party website which is using the Facebook JS SDK and get a user's signed fbsr_APP_ID cookie which a website should use to authenticate their users.
Is there a way to set this cookie with the secure parameter so that it's only transmitted over HTTPS connections?
I have read both the documentation and the JavaScript SDK source code and it doesn't seem possible. So if it's not possible, which other authentication method would you suggest to avoid eavesdropping of this cookie?
I think I'm too late for the bounty, but I'll happily take the "accepted answer" :)
As noted in the remark, on FB.init you specify, whether you want the facebook JS SDK to set cookies for you with the cookies option, it even looks like by default no cookies are set: https://developers.facebook.com/docs/reference/javascript/FB.init/
Then afterwards use your own javascript to store the fbsr_APP_ID any way you want (secure cookie, client side storage, etc).

Resources