Blitz.jsでGoogle OAuth 2.0を使ったログインを実装する
はじめに
本記事では、Blitz.jsにNext.jsのAPI機能とPassport.jsを使ってGoogleGoogle Oauth 2.0を使ったログインを実装します!
Blitz.jsで認証はどうなってるのか
Blitz.jsでは、blitz new
でプロジェクト生成した時点でメールアドレスでの認証とセッション管理が生成されています。すごい
Blitz.jsのセッション管理では、SuperToknesと同じアプローチを採用しているらしく、SuperTokensのCTOであるRishabh Poddar氏が監修をしているらしい。
そしてBlitz.jsにはPssport.jsというNode.jsの認証ミドルウェアのStrategyと呼ばれるプラグイン的な物でverify
コールバックを使用するものをサポートしています。
Passport.jsのサイトで500以上のStrategyを探すことができる
↓SuperTokensのトップページにBlitz.js作者が載ってた
Googleの認証情報を作る
Google Cloud Platformの「APIとサービス」から認証情報の画面で
認証情報の作成→OAuthクライアントID
アプリケーションの種類をWebにして名前をつける
- リクエストのホワイトリストにhttp://localhost:3000
- リダイレクトURIにhttp://localhost:3000/api/auth/google/callback
などを追加する
そして、生成されてたクライアントIDとクライアントシークレットを.env.localに入れる
GOOGLE_CLIENT_ID="クライアントID"
GOOGLE_CLIENT_SECRET="クライアントシークレット"
Passport.jsを使ってGoogleログインを実装する
passport.jsのGoogle OAuth 2.0 Strategyを使う
yarn add passport-google-oauth20
Blitz.jsでは app/api/auth/[...auth].ts
を作ると
- /api/auth/[strategyName] がログインを開始するためのURL
- /api/auth/[strategyName]/callback が先ほどGCPで指定したコールバックURL
となる2つのルーティング設定が生成される。賢い
今回の場合、/api/auth/google にアクセスするとGoogleのログイン画面に遷移するようになる
また、blitz new
で生成されるUser modelに今回はGoogleから取得するアイコン画像を加えるためにモデルを更新します
blitz generate model User icon:string
import { passportAuth } from "blitz"
import db from "db"
import { Strategy as GoogleStrategy } from "passport-google-oauth20"
export default passportAuth({
successRedirectUrl: "/",
errorRedirectUrl: "/",
strategies: [
{
strategy: new GoogleStrategy(
{
clientID: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
callbackURL:
process.env.NODE_ENV === "production"
? "デプロイ先/api/auth/google/callback"
: "http://localhost:3000/api/auth/google/callback",
scope: ["email", "profile"],
},
async function (_token, _tokenSecret, profile, done) {
const email = profile.emails && profile.emails[0]?.value
const user = await db.user.upsert({
where: { email },
create: {
email,
name: profile.displayName,
icon: profile.photos[0]?.value,
},
update: { email },
})
const publicData = {
userId: user.id,
roles: [user.role],
source: "google",
}
done(null, { publicData })
}
),
},
],
})
これだけGoogleログインが実装できました!Blitz.jsすごい
試してみる
- TOPページのログインボタンを
/api/auth/google
へのLinkに変えてユーザー名を表示するようにする -
<img src={currentUser.icon} alt="user-icon" />
でアイコン画像を表示してみる
const UserInfo = () => {
const currentUser = useCurrentUser()
const [logoutMutation] = useMutation(logout)
if (currentUser) {
return (
<>
<button
className="button small"
onClick={async () => {
await logoutMutation()
}}
>
Logout
</button>
<div>
User id: <code>{currentUser.id}</code>
<br />
User role: <code>{currentUser.role}</code>
+ <br />
+ User name: <code>{currentUser.name}</code>
+ <img src={currentUser.icon} alt="user-icon" />
</div>
</>
)
} else {
return (
<>
<Link href="/signup">
<a className="button small">
<strong>Sign Up</strong>
</a>
</Link>
<Link href="/api/auth/google">
<a className="button small">
<strong>Log In With Google</strong>
</a>
</Link>
</>
)
}
}
作成したログインボタンから任意のGoogleアカウントでログインすることができ、ユーザー名とアイコン画像を表示することができました。
Blitz.jsはすごい
4月に正式リリースするらしいので楽しみ
Discussion