OAuth
Loading "Intro to OAuth"
Run locally for transcripts
Authenticating with third parties is very common in web applications. For some
apps it's used to help to reduce the friction of signing up via social login
(login with 𝕏, Google, GitHub, etc.). For others it's to be able to retrieve or
update data on behalf of the user. And still for some it's a customer
requirement (SSO).
Doing this securely is challenging. So various standards have been created to
make it easier to do this securely. The most common of these is
OAuth2 (and its sibling
OpenID Connect). These standards define a flow for
authenticating with a third party and getting back an access token that can be
used to make requests on behalf of the user.
The specification is beyond the scope of this workshop, but Digital Ocean has a good
introduction to OAuth 2
if you're interested in diving a little deeper.
App Authentication flow with OAuth
Here's a flow diagram showing how our application will use OAuth to authenticate
a user:
Here's how the flow goes:
- The user clicks "login with provider"
- The server redirects the user to the provider (and sets a cookie to keep track of the user so we remember them when they come back).
- The user authenticates with the provider
- The provider redirects the user which triggers a request to the server with a code and some information to associate the user with their cookie.
- The server exchanges the code for an access token and uses that to get the user's profile.
- The server gets or creates a connection in the database for the user if the user already exists and redirects them home
- Otherwise, the server redirects to onboarding with a value in the
verifySession
that verifies the user owns the email address with which they authenticated on the provider.
remix-auth
Implementing OAuth is definitely not most developers' favorite pass time, which
is why I'm grateful to have
remix-auth
which makes it easy to
implement various authentication strategies in your application. One of these
strategies is OAuth!First, you create a session object for remix-auth to manage the flow with the
user:
import { createCookieSessionStorage } from '@remix-run/node'
export const connectionSessionStorage = createCookieSessionStorage({
cookie: {
name: 'en_connection',
sameSite: 'lax',
path: '/',
httpOnly: true,
maxAge: 60 * 10, // 10 minutes
secrets: process.env.SESSION_SECRET.split(','),
secure: process.env.NODE_ENV === 'production',
},
})
Then you create an authenticator that will manage the flow with the provider.
There's a general
remix-auth-oauth2
package
which can handle OAuth2 providers, but there's even a GitHub-specific strategy
we can use as well!
remix-auth-github
:type ProviderUser = {
// ... user data stored in the session
}
export const authenticator = new Authenticator<ProviderUser>(
connectionSessionStorage,
)
authenticator.use(
new GitHubStrategy(
{
clientID: process.env.GITHUB_CLIENT_ID,
clientSecret: process.env.GITHUB_CLIENT_SECRET,
callbackURL: '/auth/github/callback',
},
async ({ profile }) => {
// convert the user's profile into what the user object should be
return {
// ... user data stored in the session
}
},
),
// name the strategy:
'github',
)
This would go in the
action
of the route that handles when the user clicks
"Login with GitHub."return await authenticator.authenticate('github', request)
// throws a redirect to GitHub + sets a cookie with some state
This would go in the
loader
of the route that handles when the browser is
redirected from the third party back to our application.// GitHub redirects with the code and the state value
const data = await authenticator.authenticate('github', request, {
throwOnError: true,
})
Configuring OAuth Providers
One of the common requirements of OAuth providers is application registration.
This helps the provider know who is using their service and what they're using
it for. This is usually done by creating an "application" with the provider and
getting a client ID and client secret. These are used to identify your
application when it makes requests to the provider.
You can create an OAuth application with the GitHub API by
following the GitHub documentation.
You do not have to set up a GitHub application for this workshop if you don't
want to. Very early on we'll start mocking out the GitHub API so you can
continue to work on the workshop without having to set up a GitHub
application. But feel free to try it if you like!
If you do create an OAuth application, you'll want to set the callback URL to:
http://localhost:4000/auth/github/callback
.Single Sign On
In many business-to-business or Software as a Service applications, your
customers may wish (or require) that you enable their employees to access your
application using their company's identity provider. This is called Single Sign
On (SSO) and is a common requirement for enterprise applications.
In times past, the most common way to do this was to use SAML. Many
organizations still use SAML, but it's a bit of a pain to implement. So many
organizations are moving to OAuth2 and OpenID Connect.
From the How OpenID Connect Works
article on the OpenID Connect website:
OpenID Connect is an interoperable authentication protocol based on the OAuth 2.0 framework of specifications (IETF RFC 6749 and 6750). It simplifies the way to verify the identity of users based on the authentication performed by an Authorization Server and to obtain user profile information in an interoperable and REST-like manner.
If you do have to support SAML, you may find
remix-auth-sso
helpful.For OpenID Connect, you can use
web-oidc
which also comes with a
remix-auth
strategy.In this exercise we're going to focus on OAuth2 with the GitHub strategy, but by
the end of the workshop we'll have a module third party authentication setup
which will make it easy for you to implement authentication with other
providers (including SSO).