NextAuth.js와 Firebase Authentication의 협력
개시하다
NextAuth.js는 Next입니다.js를 위한 OSS 인증 라이브러리입니다.
이 프로그램 라이브러리의 장점은 주로 OAuth나 Email 인증을 받은 사용자의 정보와 연합 세션의 데이터베이스를 통해 자동으로 관리된다는 것이다.다른 인증 시스템에서 이미 인증된 사용자를 관리하는 방법도 있지만, 오옥스나 이메일 인증과 비교해 알기 쉬운 샘플 코드는 없다.나는 이곳에서 지식과 방어구록을 공유하고 싶다.
또 넥스트옥스에서는 로그인 중인 사용자의 정보를 리액트 컨텍스트로 저장firebase.auth.User할 수 없고, 사용자 ID 등 JSON(JWT의 유효 하중에 포함)으로 엄정하게 관리할 수 있는 내용만 대상으로 한다.이 글은 Firebase Authentication이 보유한 ID 토큰을 활용해 로그인한 사용자의 정보를 쿠키에 JWT로 저장해 로그인 상태를 유지하기 위한 목적으로 작성됐다.
NextAuth.js와Firebase Authentication 자체에 대한 입문이 거대해졌기 때문에 이 기사에는 쓰지 않습니다.
소스 코드
Vercel에서 depro의 물건은 아래 링크에 있습니다.
차리다
Next.새 js 응용 프로그램
npx create-next-app --ts nextauth-firebaseauth-example
cd nextauth-firebaseauth-example
npm install next-auth@beta firebase firebase-admin
이 글은 2021년 9월 말까지 베타 버전인 넥스트 앳v4를 사용했다.v3에서 v4로의 업데이트는 API에 파괴적인 변경을 하였으며, stable의 v3를 사용하려면 적당히 교체하십시오.참조: Upgrade Guide (v4)경로 별칭
이것은 개인의 취향입니다. 코드는 모두 프로젝트 루트에
src/
디렉터리를 만들고 그 중에서 관리하며 @/
의 별명을 미리 붙입니다.tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
}
}
Firebase 구성
Firebase 콘솔에서 새 프로젝트 만들기
웹 응용 프로그램의 설정값, 관리자용 기밀 키
project_id
, client_email
, private_key
를 .env.local
로 복사하여 환경 변수에 포함시킵니다(참조: 유연한 Firebase admin 초기화..env.local
# Firebase SDK の初期化に必要
NEXT_PUBLIC_FIREBASE_API_KEY=<apiKey>
NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=<authDomain>
NEXT_PUBLIC_FIREBASE_PROJECT_ID=<projectId>
NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=<storageBucket>
NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=<messagingSenderId>
NEXT_PUBLIC_FIREBASE_APP_ID=<appId>
NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID=<measurementId>
# Firebase Admin SDK の初期化に必要
FIREBASE_PROJECT_ID=<project_id>
FIREBASE_CLIENT_EMAIL=<client_email>
FIREBASE_PRIVATE_KEY=<private_key>
Firebase 라이브러리 초기화
Firebase SDK 및 Firebase Admin SDK를 초기화합니다.
Firebase SDK
src/lib/firebase.ts
import { initializeApp } from "firebase/app";
import type { FirebaseOptions } from "firebase/app";
const firebaseConfig: FirebaseOptions = {
apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY,
authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID,
measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID,
};
export const firebaseApp = initializeApp(firebaseConfig);
Firebase Admin SDK
src/lib/firebaseAdmin.ts
import * as admin from "firebase-admin";
import type { ServiceAccount } from "firebase-admin";
const cert: ServiceAccount = {
projectId: process.env.FIREBASE_PROJECT_ID,
clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
privateKey: process.env.FIREBASE_PRIVATE_KEY.replace(/\\n/g, "\n"),
};
export const firebaseAdmin =
admin.apps[0] ??
admin.initializeApp({
credential: admin.credential.cert(cert),
});
NextAuth 설정
공식 문서Example Code에 따라 가져오기
SessionProvider
.src/pages/_app.tsx
import type { AppProps } from "next/app";
import { SessionProvider } from "next-auth/react";
function MyApp({
Component,
pageProps: { session, ...pageProps }
}: AppProps) {
return (
<SessionProvider session={session}>
<Component {...pageProps} />
</SessionProvider>
);
}
export default MyApp;
인증 프로세스
인증 절차부터 파악해.
로그인 페이지
여기에는 Firebase Authentication을 통해 로그인하여 ID 토큰을 획득하는 것이 목적입니다.로그인 공급자가 GiitHub 및 Google을 선택했습니다.
src/pages/auth/signin.tsx
import { signIn } from "next-auth/react";
import {
getAuth,
signInWithPopup,
GithubAuthProvider,
GoogleAuthProvider,
} from "firebase/auth";
import type { AuthProvider } from "firebase/auth";
import { firebaseApp } from "@/lib/firebase";
export default function singIn() {
const auth = getAuth(firebaseApp);
const githubProvider = new GithubAuthProvider();
const googleProvider = new GoogleAuthProvider();
const handleOAuthSignIn = (provider: AuthProvider) => {
signInWithPopup(auth, provider)
// 認証に成功したら ID トークンを NextAuth に渡す
.then((credential) => credential.user.getIdToken(true))
.then((idToken) => {
signIn("credentials", { idToken });
})
.catch((err) => console.error(err));
};
return (
<>
<p>Choose your sign-in method:</p>
<button onClick={() => handleOAuthSignIn(githubProvider)}>GitHub</button>
<br />
<button onClick={() => handleOAuthSignIn(googleProvider)}>Google</button>
</>
);
}
중요한 것은 handleOAuthSignIn()
중의 다음과 같은 처리이다.signIn("credentials", { idToken });
signIn()
함수에 전달되는 매개 변수는 두 가지가 있다."credentials"
:NextAuth에 사용된 공급자의 IDNextAuth는 외부 인증 시스템의 정보를 사용할 때
CredentialsProvider
를 사용하는 공급자CredentialsProvider
의 ID는"credentials"
이다.{ idToken: idToken }
: CredentialsProvider
사용자 인증에 필요한 값NextAuth API 경로
참조: Credentials Provider
src/pages/api/auth/[...nextauth].ts
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { firebaseAdmin } from "@/lib/firebaseAdmin";
export default NextAuth({
providers: [
CredentialsProvider({
authorize: async (credentials, req) => {
const { idToken } = credentials;
if (idToken != null) {
try {
const decoded = await firebaseAdmin.auth().verifyIdToken(idToken);
return { ...decoded };
} catch (error) {
console.log("Failed to verify ID token:", error);
}
}
return null;
},
}),
],
callbacks: {
jwt: async ({ token, user }) => {
if (user) {
token = user;
}
return token;
}
}
});
CredentialsProvider
이전 로그인 페이지에
signIn("credentials", { idToken });
중의 { idToken }
는 authorize(credentials, req)
의 첫 번째 매개 변수credentials
로 교부된 대상이다.authorize()
에서 firebase-admin
를 통해 ID 영패를 JSON으로 디코딩하고 검증이 통과되면 이 영패를 되돌려주고 검증이 실패하면 오류null
로 되돌려준다.JWT 콜백
callbacks
옵션의 jwt()
은 로그인할 때 JWT가 생성되고 업데이트될 때 호출됩니다.jwt({ token, user })
매개 변수의 대상 속성 중 token
는 JWT를 나타내고 user
는 authorize()
가 되돌아오는 대상을 나타낸다.즉 이곳user
의 실체는DecodedIdToken이다.위의 코드는 NextAuth에서 발행한 JWT의 유효 하중을 디코딩된 ID 영패로 바꿉니다. 예를 들어
user
가지고 있는 정보의 일부분만 있으면 이렇게 고칠 수 있습니다.예: 사용자 ID만 사용
callbacks: {
jwt: async ({ token, user }) => {
if (user) {
token.sub = user.sub;
}
return token;
}
}
작성된 JWT는 쿠키에 next-auth.session-token
로 저장되며, jwt.io 등을 통해 쿠키를 디코딩하면 HS512가 서명한 Firebase Authentication의 ID 토큰과 유효 하중이 일치합니다.※ HS512는 넥스트옥스의 기본 서명 알고리즘
이상은 인증입니다.
참고 문장
(CredentialsProvider를 통해 분산 인증 시스템Magic과 연합하는 절차)
Reference
이 문제에 관하여(NextAuth.js와 Firebase Authentication의 협력), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/elpnt/articles/1af1047612992d텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)