Using OAuth to add authentication to a React app
fusionauth.io
fusionauth.io
I'm interested in why FusionAuth chose OAuth to share identity between localhost:${serverPort} and localhost:${fusionAuthPort}?
Auth0 does the same, and it's always struck me as misplaced. OAuth makes sense to me between two distinct parties, but the architecture here treats FusionAuth and the application as a single party. Meaning, when a user signs in through the FusionAuth form, they're actually signing in to the application.
That's not true of Google OAuth - if a user signs into Google, they're not automatically signed into every service where they've ever clicked "Sign in with Google".
We moved away from this model because it also makes it really hard for FusionAuth to manage the user's session on the developer's behalf. You can see in this writeup that the developer is asked to pull in express-session to manage the user's session on their own.
Our mindset is: since Clerk is same-site to the developer's server, we can manage the user's session on behalf of the developer. When dev's use clerk, they don't need to think about cookies or sessions at all, except to the extent that lifetimes are configurable in our dashboard.
Disclosure, I'm head of devrel at FusionAuth, as well as a co-worker of the author of the post.
We think there is value in separating identity in the way you describe for a number of reasons.
* While this tutorial is about one app, that isn't usually how things work beyond demo land. In most places you have more than one application authenticating against FusionAuth (a couple of custom apps, OSS software like forums, COTS like Zendesk). In this case, isolating identity to a single component allows you to manage it centrally and to, if needed, bolster security.
* If you use OAuth, you get access to a tremendous selection of libraries across different languages. Every language has an OAuth framework you can use.
* Developers can have portable skills. Sure, figuring out the Authorization Code grant can be a bit of a pain, but once you do it once, you can do it again and again.
* By standardizing on OAuth/OIDC, you can move between identity providers. Yes, there are differences at the edges, but you'll have more flexibility than if you code to say, Clerk. This may or may not be worthwhile.
I haven't taken a close look at clerk, but I'm not sure how you handle the multi application setup. It is likely that both FusionAuth and Clerk are approaching the same problems in different ways (which is fine!).If you want to see a take on how we think about authentication, the Modern Guide to OAuth is a great article to read: https://fusionauth.io/learn/expert-advice/oauth/modern-guide... particularly the "OAuth modes" section.
In general, we're pushing for more use of short-lived JWTs to sync identities between trusted parties instead of OAuth. We think this is preferable because it can keep sessions synced, while OAuth tends to result in independent sessions.
Admittedly, we do not run an OpenID Connect server on behalf of our customers yet. This is on our roadmap and will be added soon, and there are definitely some services that we can't offer first-class integrations with until that happens.
Your other point about "every language has an OAuth framework" is well-taken. Our initial launch used something proprietary and this was an issue, but we recently switched to spec-compliant JWTs to benefit more from existing libraries. Here's an example of our current, standard token:
https://jwt.io/#token=eyJhbGciOiJSUzI1NiIsImtpZCI6Imluc18xcn...
FusionAuth works with GraphQL/Hasura as well, see this post from a community member: https://fusionauth.io/community/forum/topic/696/how-to-use-f...
> In general, we're pushing for more use of short-lived JWTs to sync identities between trusted parties instead of OAuth. We think this is preferable because it can keep sessions synced, while OAuth tends to result in independent sessions.
This is an interesting approach. Can you tell me more (or just point me to the docs)?
> Admittedly, we do not run an OpenID Connect server on behalf of our customers yet. This is on our roadmap and will be added soon...
That's great! I'm sure your customers will welcome the additional flexibility.
Having just done a review of auth vendors (including FusionAuth + Auth0), I think your product addresses a much simpler use-case. FusionAuth and Auth0 support complex multi-tenancy setups and tie that into enterprise SSO providers, and all that's configurable on a per-customer/application basis with logical separation inside the auth vendor. I don't believe you support that level of complexity yet.
The nitty-gritty of auth does suck for most projects/early startups, but once you start selling to mid-size customers (B2B) they'll demand features that require what FusionAuth/Auth0/similar competitors offer.
Indeed, we're still catching up on feature-completeness, especially for the B2B world. In 2022 we will be tackling organization onboarding, SAML SSO, roles and permissions, subscription management, and authorization (as it relates to permissions and subscriptions). Still just getting started...
That said, a much more secure solution is described in the link below. It's also known as "Token Handler" pattern. In a nutshell, keep all the secrets on the backend and also handle the code exchange and tokens on the server, hence the name of the pattern. Then, store the token in a secure cookie. It's way more secure than moving a token into the browser, where a dependency vulnerability could get access to it.
https://wundergraph.com/blog/authentication_for_nextjs_with_...
That said, if you must send a token to the browser because you don't want to manage sessions, we've seen folks have success storing the JWT in an HTTPOnly secure cookie.
Disclosure: am co-worker of the author.
Cookies are still in the browser so what difference are you specifically addressing or advocating
For instance: https://github.com/gorilla/securecookie
Unless I'm missing something and the payload is effectively signed. Either way, I still like to have signing generically done at this level of abstraction. Then I can put whatever in there.
Sometimes the encrypted payload is also signed too - maybe with a per-user secret. Now "log out everywhere" is as simple as scrambling the user's secret, thus invalidating their cookies. Simple.
You can write your application in react, php, perl, bash, c, or just manually answer to http calls for all I care.
How do you store the tokens that the OAuth server generates on successful authentication?
https://github.com/zmartzone/mod_auth_openidc/wiki/Session-m...
Something like
https://github.com/gogatekeeper/gatekeeper/blob/master/docs/...
It's no problem to set up Django, but I don't want to have to separately protect all public endpoints.
There is some really good open source software emerging like https://github.com/ory/kratos which has APIs for native app flows, single page apps, server side apps and doesn‘t rely on protocols intended for completely different things such as „allow CircleCI access to my Gitlab repositories“.
Is it really worth investing in OAuth2 these days just because Auth0 pours millions in marketing? I highly question it…
I don't know your exact use case. But I did a presentation about OAuth in the real world for Denver Startup Week and there was a slide about why you should use OAuth.
* Standards based
* Sharp security minds designed it
* Lots of edge cases handled
* Interoperable
* Not perfect, but far better than if you aren't using Oauth
* Isolates sensitive user data like passwords or PII into a single server. Enforces separation of concerns and allows for single view of user (this benefit is not exclusive to OAuth, of course, but if you chose OAuth, you get it).
Disclosure: I work for FusionAuth, an auth service provider.* Password management * SSO * A bunch of other features and security (MFA, Forgot password, breached passwords, brute force, password validation, threat detection, account takeover protection, etc.)
Another benefit of OAuth is once you use the OAuth authorization code grant in your app, you can swap out IdPs. So, that delegation pattern is really helpful for offloading the extra work of building Auth, and it can "plug and play" into any IdP that supports it.
At the end of the day, OAuth is the protocol that lets you delegate all the auth code to an external auth provider, instead of trying to build it all yourself.