Files
archived-next-auth/docs/versioned_docs/version-beta/getting-started/02-oauth-tutorial.mdx
Lluis Agusti 5246183c55 chore: docs updates (#5581)
* chore: fix version label

* upgrade docusaurus

* fix

* fix

* fix links, NextAuth -> NextAuth.js

* NextJS -> Next.js

* fix guides

* add docusaurus type

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-10-15 16:39:33 +01:00

292 lines
12 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: OAuth authentication
---
import creatingOauthAppImg from "./img/getting-started-creating-oauth-app.png"
import addingCallbackUrlImg from "./img/getting-started-oauth-callback-url.png"
import gettingClientIdSecretImg from "./img/getting-started-oauth-clientid-secret.png"
import startAppAndSignInImg from "./img/getting-started-app-start.png"
import githubAuthCredentials from "./img/getting-started-github-auth.png"
import nextAuthUserLoggedIn from "./img/getting-started-nextauth-success.png"
We know, authentication is hard. Is a rabbit hole and it's easy to get lost on it. The goal of making NextAuth.js is that you can add authentication easily to your project with just a few lines of code.
The easiest way is to setup NextAuth.js with an [OAuth](https://en.wikipedia.org/wiki/OAuth) provider. In this tutorial we'll be setting NextAuth.js in a **Next.js app** to be able to login with **Github**.
:::info
NextAuth.js comes with a long list of [built-in providers](/reference/Providers/) (Google, Facebook, Twitter, etc...) you can also integrate it with your own OAuth service easily by [building a custom provider](/beta/guides/oauth/custom-provider). NextAuth.js can integrate as well with other frameworks like SvelteKit and Gatsby.
:::
## 1. Configuring NextAuth.js
### Creating the server config
To add NextAuth.js to a [**Next.js**](https://nextjs.org/) project, create the following [API route](https://nextjs.org/docs/api-routes/introduction):
```
pages/api/auth/[...nextauth].ts
```
This route will contain the **dynamic route handler** for NextAuth.js which describes your global auth configuration:
```ts title="pages/api/auth/[...nextauth].js"
import NextAuth from "next-auth"
import GithubProvider from "next-auth/providers/github"
export default NextAuth({
providers: [
GithubProvider({
clientId: /* We'll fill this later */,
clientSecret: /* We'll fill this later*/,
}),
],
})
```
Behind the scenes this creates all the relevant OAuth API routes within `/api/auth/*` so that auth API requests to:
- `/api/auth/callback`
- `/api/auth/signIn`
- `/api/auth/singOut`
- etc...
can be handled by NextAuth.js. In this way, NextAuth.js stays in charge of handling the whole authentication request/response flow of your application for you.
You may notice there are some environment variables in the code example above. `GITHUB_ID` and `GITHUB_SECRET` are provided by the OAuth provider (in this case **Github**) see ["Configuring OAuth Provider"](/getting-started/oauth-tutorial#2-configuring-oauth-provider) section on how to get those.
`NEXTAUTH_SECRET` is a random string used by the library to encrypt tokens and email verification hashes, and **it's mandatory to keep things secure**! 🔥 🔐 . You can use:
```
$ openssl rand -base64 32
```
or https://generate-secret.vercel.app/32 to generate a random value for it.
:::info
NextAuth.js is extremely customizable, [our guides section](/beta/guides/overview) will teach you how you can set it up to handle auth in different ways. All the possible configuration options are [listed here](/reference/server/configuration).
:::
### Exposing the session via provider
To be able to use `useSession` first you'll need to expose the session context, [`<SessionProvider />`](/getting-started/client#sessionprovider), at the top level of your application:
```ts title="pages/_app.ts"
import { SessionProvider } from "next-auth/react"
export default function App({
Component,
pageProps: { session, ...pageProps },
}) {
return (
<SessionProvider session={session}>
<Component {...pageProps} />
</SessionProvider>
)
}
```
Instances of `useSession` (more on it in the next section) will then have access to the session data and status. The `<SessionProvider />` also takes care of keeping the session updated and synced between browser tabs and windows. 💪🏽
:::tip
Check our [client docs](/reference/client/introduction) to learn all the available options for handling sessions on the browser.
:::
### Consuming the session via hooks
NextAuth.js exposes a [`useSession()`](/getting-started/client#usesession) React Hook so that you can easily check if someone is signed in:
```ts title="pages/overview.tsx"
import { useSession, signIn, signOut } from "next-auth/react"
export default function CamperVanPage() {
const { data: session, status } = useSession()
const userEmail = session.user.email
if (status === "loading") {
return <p>Hang on there...</p>
}
if (status === "authenticated") {
return (
<>
<p>Signed in as {userEmail}</p>
<button onClick={() => signOut()}>Sign out</button>
<img src="https://cdn.pixabay.com/photo/2017/08/11/19/36/vw-2632486_1280.png" />
</img>
)
}
return (
<>
<p>Not signed in.</p>
<button onClick={() => signIn()}>Sign in</button>
</>
)
}
```
You can use the `useSession` hook from anywhere in your application (e.g. in a header component). Behind the scenes, the hook will connect to the `<SessionProvider />` to read the current user session.
### Protecting API Routes
Protecting your custom API Routes (.i.e not allowing a resource to be accessed in case the user is not logged in) is easy! You can use [`getSession()`](/getting-started/client#getsession) to know whether a session exists or not:
```ts title="pages/api/movies/list.ts"
import { getSession } from "next-auth/react"
export default async function listMovies(req, res) {
const session = await getSession({ req })
if (session) {
res.send({
movies: [
{ title: "Alien vs Predator", id: 1 },
{ title: "Reservoir Dogs", id: 2 },
],
})
} else {
res.send({
error: "You must sign in to view movies.",
})
}
}
```
## 2. Configuring OAuth Provider
Ok, we have our Next.js app setup with NextAuth, however, if you run the app right now, it won't work as we haven't configured our OAuth provider (**Github**) yet.
:::info
When using OAuth you're asking for a third-party service (in this case Github, although it could be Google, Twitter, etc...) to handle user authentication for your app.
:::
We need to register our new Next.js app in Github, so that when NextAuth.js forwards the authorization requests to it, Github can recognize your application and prompt the user to sign in.
<img src={creatingOauthAppImg} />
Log in into **Github**, go to `Settings / Developers / OAuth Apps` and click on "New OAuth App".
Next you'll be presented with a screen to add details about your new application. Fill in the required fields, but pay extra attention to the **Authorization Callback URL** one:
<img src={addingCallbackUrlImg} />
The callback URL we insert should have the following pattern:
```
[origin]/api/auth/callback/[provider]
```
In this case, given we want to try our authentication working locally on our machine and we're using **Github** as our OAuth provider, it'll be:
```
http://localhost:3000/api/auth/callback/github
```
:::info
NextAuth.js will already magically create this API endpoint for you when we start the application later. Note that because we're using Next.js, locally it starts our server on the port `3000`, hence the origin is `http://localhost:3000`.
:::
Next you'll be presented with the following screen which presents all the configuration for your new OAuth app. For now, let's we need two things from it: the **Client ID** and **Client Secret** for our new OAuth app:
<img src={gettingClientIdSecretImg} />
The Client ID is always there, a public identifier of your OAuth application within Github. Click on the **Generate a new client Secret** button and should be presented with a new string (which is just a randomized string).
:::warning
🔥 Keep both your Client ID and Client Secret secure and never expose them to the public or shared with people outside your organization. With tem a malicious actor could hijack your application and cause you and your user serious problems!
:::
Now let's copy both the Client ID and Client Secret and paste them in an environment file in the root of your project like so:
```title=".env.local"
GITHUB_ID=12345
GITHUB_SECRET=67890
```
Cool! We have finished the configuring our OAuth provider, now let's wire all together so we can finally see authentication working in our app!
:::info
As noted previously, NextAuth.js has built-in support for multiple OAuth providers, <a href="">here the full list</a>. You can also easily build your own in case the provider you need is not on the list.
Note that, for each provider, the configuration process will be similar to what we just did:
1. Log in to the provider
2. Create create your OAuth application within it
3. Set the callback URL
4. Get the Client ID and Generate a Client Secret
:::
## 3. Wiring all together
Finally, we just need to reference our **Client ID** and **Client Secret** we just generated in the previous in our NextAuth.js config. In this way the library will be able to use them when forwarding users to Github, and Github will be able to recognize the request as generated from our application:
```ts title="pages/api/auth/[...nextauth].js"
import NextAuth from "next-auth"
import GithubProvider from "next-auth/providers/github"
export default NextAuth({
providers: [
GithubProvider({
clientId: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET,
}),
],
})
```
Great! We're now ready to run our application locally. Start the Next.js app by running on your terminal the following command and navigating to [`http://localhost:3000`](http://localhost:3000):
```
$ npm run next dev
```
You should see the following page:
<img src={startAppAndSignInImg} />
Click on "Sign in" and then on "Sign in with Github": NextAuth.js will redirect you to Github, and Github will recognize our app [that we just registered](#2-configuring-oauth-provider) and ask the user (in this case you) to enter its credentials to proceed:
<img src={githubAuthCredentials} />
Once inserted and correct, Github will redirect the user to our app and NextAuth.js will take care of any further calls with Github to get access to the user profile and start a user sessions safely in the background:
<img src={nextAuthUserLoggedIn} />
Great! We have completed the whole E2E authentication flow setup so that users can login in our application through Github!
:::info
You can create your own Sign In page instead of using the default one from NextAuth.js. You can learn how to do so in our dedicated guide for it.
:::
## 4. Deploying to production
### Configuring different environments
It's normal to test your application under different environments. Usually you'll have a development environment (when you run the application locally in your machine), a staging environment (for teams members to try the application) and a production environment.
For each environment, you're going to need to create an OAuth application in your provider respectively, as [we did previously](#2-configuring-oauth-provider), and point the **callback URL** to it.
For instance in the previous section, we pointed the callback URL to:
```
http://localhost:3000/api/auth/callback/github
```
as we wanted to test our application in the development environment.
If we were to deploy our app to production, we would need to create again a new **OAuth App** in Github (calling it something like "Van life prod") and point the **callback URL** to our production domain:
```
https://example.com/api/auth/callback/github
```
Finally, we would need just to point the environment variables we set ( `GITHUB_ID` and `GITHUB_SECRET` ) to the credentials of the OAuth app we want our application to run against.
### Setting up `NEXTAUTH_URL`
When deploying your site, **you need to set** the `NEXTAUTH_URL` environment variable to the canonical URL of your website:
```
NEXTAUTH_URL=https://example.com
```
:::warning
In production, this needs to be set as an environment variable on the service you use to deploy your app.
To set environment variables on Vercel, you can use the [dashboard](https://vercel.com/dashboard) or the `vercel env pull` [command](https://vercel.com/docs/build-step#development-environment-variables).
:::
For more information please check out our [deployment page](/deployment).