2023年11月06日
如何在Next.js中实现OAuth用户认证
本文将学习如何在您的Next.js应用中使用OAuth提供程序添加用户身份验证。为此,我们将使用NextAuth.js ,这是一个用户身份验证解决方案,简化了整个流程,并内置支持许多流行的登录服务。
什么是OAuth?
OAuth(开放授权)是一种用于访问委托的开放标准,通常用作互联网用户授予网站或应用程序访问其它网站上信息的方式,但不会泄露密码。
当您使用OAuth身份验证与提供程序(如Google、Facebook、Twitter等)时,您使用的是一种协议,允许您授权应用程序使用提供程序的个人信息,而无需暴露密码。这是通过共享令牌而不是凭据来实现的,这些令牌可以限制用于特定资源或服务。
其主要优势在于您无需处理各种网络服务提供的不同身份验证方法。OAuth被广泛接受并被许多互联网上的热门应用程序使用。
设置NextAuth.js
1. 安装NextAuth.js
npm install next-auth
2. 在您的.env.local
文件中添加NEXTAUTH_SECRET
成功登录后,NextAuth.js会生成一个带有JWT令牌的cookie,用于用户标识,并使用NEXTAUTH_SECRET
值进行加密。
您可以使用
openssl rand -base64 32
或generate-secret.vercel.app生成一个随机值,并将其添加到您的.env.local
文件中。
3. 为您的Next.js应用添加路由处理程序
要将NextAuth.js添加到您的项目中,您需要创建一个动态路由处理程序。为此,请在app/api/auth/[…nextauth]
中创建一个名为route.js|ts
的文件。该文件还将包含您的全局NextAuth.js配置。
路由处理程序相当于API路由在pages目录中,这意味着您不需要同时使用API路由和路由处理程序。如果您使用的是较旧版本的Next.js,则使用pages路由,这里有一个示例**,演示如何初始化API路由。
在下面的我的route.ts
文件中,我成功地使用了四个不同提供程序(Google、LinkedIn、GitHub和Spotify)设置了身份验证。
import NextAuth, { NextAuthOptions } from "next-auth"; import GoogleProvider from "next-auth/providers/google"; import LinkedInProvider from "next-auth/providers/linkedin"; import GitHubProvider from "next-auth/providers/github"; import SpotifyProvider from "next-auth/providers/spotify"; export const authOptions: NextAuthOptions = { providers: [ GoogleProvider({ clientId: String(process.env.GOOGLE_CLIENT_ID), clientSecret: String(process.env.GOOGLE_CLIENT_SECRET), }), GitHubProvider({ clientId: String(process.env.GITHUB_CLIENT_ID), clientSecret: String(process.env.GITHUB_CLIENT_SECRET), }), // LinkedIn recently changed their OAuth flow which is why there is a bit extra code LinkedInProvider({ clientId: String(process.env.LINKEDIN_CLIENT_ID), clientSecret: String(process.env.LINKEDIN_CLIENT_SECRET), authorization: { params: { scope: "openid profile email" }, }, issuer: "https://www.linkedin.com", jwks_endpoint: "https://www.linkedin.com/oauth/openid/jwks", profile(profile, tokens) { const defaultImage = "https://cdn-icons-png.flaticon.com/512/174/174857.png"; return { id: profile.sub, name: profile.name, email: profile.email, image: profile.picture ?? defaultImage, }; }, }), SpotifyProvider({ clientId: String(process.env.SPOTIFY_CLIENT_ID), clientSecret: String(process.env.SPOTIFY_CLIENT_SECRET), }), ], }; const handler = NextAuth(authOptions); export { handler as GET, handler as POST };
路由处理程序带来了什么好处?
由于我们的路由处理程序,现在所有对/api/auth/*
的请求(如signIn
、callback
、signOut
等)将自动由NextAuth.js处理。开箱即用,我们获得了一个简单的登录 页面(/API/auth/signin)。成功登录后,您将在cookie中看到一个JWT令牌。与我们在上一步中创建的NEXT_SECRET
相同,该JWT令牌已签名。
如何获取 clientId
和 clientSecret
?
通常,这个过程涉及在您所需服务上创建一个OAuth应用程序(例如Google),并生成一个密钥和秘钥,然后将其添加到您的.env.local
文件中。
逐步实施
假设我们想要使用X(例如Twitter)实现身份验证。以下是我们需要采取的所有步骤。
- 要使用X(例如Twitter)进行身份验证,只需按照NextAuth.js的指南获取
clientId
和clientSecret
,网址为next-auth.js。请务必仔细阅读您想要使用的提供程序的文档。 - 这是一个关于如何获取Twitter的
clientId
和clientSecret
的简短视频:
注意:不同服务的流程可能有所不同。请参阅提供程序的文档(参见步骤1)。
对于Twitter:
* 使用OAuth 2.0版本。
* 选择“本地应用”。
* 将重定向URL设置为/api/auth/callback/twitter
。在开发中使用“localhost:3000”。您可以稍后添加生产回调URI/重定向URL。
3. 将clientId
和clientSecret
复制粘贴到您的.env.local
文件中。
4. 在您的route.ts
中导入Twitter提供程序,并将其初始化为提供程序列表中的一部分。
5. ```javascript
// ...code
import TwitterProvider from "next-auth/providers/twitter";
export const authOptions: NextAuthOptions = { // ...code providers: [ // ...other providers TwitterProvider({ clientId: process.env.TWITTER_CLIENT_ID, clientSecret: process.env.TWITTER_CLIENT_SECRET, version: "2.0", // opt-in to Twitter OAuth 2.0 }), ], }; // ...code
6. 就是这样!转到您的[/api/auth/signin](http://localhost:3000/api/auth/signin),您将看到您的新提供程序。
![具有所有实现提供程序的登录页面。](https://cdn.iokks.com/art/7dbf84716804/5c2c4344cae746c2ac50f03ead9a5038.png)
*具有所有实现提供程序的登录页面。*
## 我遇到的最常见问题
尽管从编码角度来看,这个过程是直截了当和简单的,但我遇到了一些挑战,因为每个服务都有创建OAuth应用程序和生成`clientId`和`clientSecret`的独特方式。
另外,请确保为每个服务正确设置重定向URI/回调URL。它看起来像这样**/api/auth/callback/<提供程序名称>** 。例如,对于GitHub,它是[locahost:3000](http://localhost:3000/api/auth/callback/github)。
**确保在生产环境中设置正确的重定向URI/回调URL。**
*在开发中,您可以使用[localhost](http://localhost):3000。*
最后一件事是确保设置正确的范围和权限。基本上,您需要设置您的OAuth应用程序将要向用户请求的信息,例如电子邮件、姓名和个人资料照片。
如果在开发过程中出现问题,请清除cookie并重试。
## 示例
我创建了一个小型的Next.js(v14)应用程序,您可以使用它并查看我如何实现所有这些提供程序的身份验证。**额外奖励:我还成功创建了一个受保护的路由,只有经过身份验证的用户才能看到其中的内容。**
*应用程序:*[next-auth-providers-example](https://next-auth-providers-example-r4xt.vercel.app/)
*GitHub:*[next-auth-providers-example](https://github.com/kicoo7/next-auth-providers-example)
## 总结
* 安装NextAuth.js(`npm install next-auth`)。您需要在您的`.env.local`文件中添加`NEXTAUTH_SECRET`,以便NextAuth.js正常工作。
* 为NextAuth.js添加一个路由处理程序(或者对于较旧的Next.js版本,使用API路由)。您可以复制粘贴上面提供的示例。
* 为您要实现的提供程序创建一个OAuth应用程序,获取`clientId`和`clientSecret`,并将它们添加到您的`.env.local`文件中。
* 在您的路由处理程序(`route.ts`文件)中,导入提供程序并将它们添加到提供程序数组中,从您的`.env.local`文件中绕过`clientId`和`clientSecret`。