【Next.js,LINE】Next.jsでLINEログイン機能を実装する
はじめに
今回は、LINEログイン機能の実装をNextAuth.jsを用いた方法とLIFFを用いた方法の2パターンを、備忘録として書いていきます。
Next.jsのバージョンは14.1.0です。
(共通) 準備
Next.jsのプロジェクト作成
作成
任意のディレクトリで、以下のコマンドを用いて作成します。
npx create next-app@latest [プロジェクト名]
選択肢は全てデフォルトにしておきます。以下の画像のようになればok。
globals.cssの編集
app/globals.css
のファイルの中身を以下のように編集します。
@tailwind base;
@tailwind components;
@tailwind utilities;
page.tsxの編集
app/page.tsx
のファイルの中身を以下のように編集しておきます。
export default function Home() {
return (
<div>
<h1>Home</h1>
</div>
);
}
LINE Developersサイトからチャネル作成
こちらを参考にして、作成してください。
準備が終わったので、次からNextAuth.jsを用いた方法とLIFFを用いた方法の2パターンを書いていきます。
NextAuth.jsを用いた方法
準備
(共通)準備を参考に、必要な準備をしてください。
NextAuth.jsをインストール
まず、Next.Auth.jsをインストールします。
ターミナルで以下のコマンドを実行します。
npm add next-auth
.envファイルを作成
ルートディレクトリに.env
ファイルを作成し、以下のように編集します。
LINE_CLIENT_ID=作成したチャネルのチャネルID
LINE_CLIENT_SECRET=作成したチャネルのチャネルシークレット
NEXTAUTH_SECRET=以下のようにして作成
NEXTAUTH_SECRET
には、以下のコマンドをターミナルで実行して得られた文字列を設定します。
openssl rand -base64 32
app/components/buttons.tsxを作成
ログイン用のボタンとログアウト用のボタンを作成します。
app
ディレクトリの配下にcomponents
フォルダを作成し、その直下にbuttons.tsx
ファイルを作成します。
以下のようにファイルの中身を記述します。
"use client";
import { signIn, signOut } from "next-auth/react";
export const LoginButton = () => {
return (
<button
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
onClick={() => signIn('line', { callbackUrl: '/' })}
>
ログイン
</button>
);
};
export const LogoutButton = () => {
return (
<button
className="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
onClick={() => signOut()}
>
ログアウト
</button>
);
};
signIn()
が認証をさせるためのメソッドで、signOut()
は認証後のセッションを切るメソッドです。これらの処理は、クライアンコンポーネントである必要からuse client
と冒頭で宣言しています。
app/options.tsxを作成
LINEを利用した認証機能を持たせます。
app
ディレクトリ直下にoptions.ts
ファイルを作成し、以下のようにファイルの中身を記述します。
import { NextAuthOptions } from "next-auth";
import LineProvider from "next-auth/providers/line";
export const authOptions: NextAuthOptions = {
debug: true,
session: { strategy: "jwt" },
providers: [
LineProvider({
clientId: process.env.LINE_CLIENT_ID!,
clientSecret: process.env.LINE_CLIENT_SECRET!
})
]
}
app/api/auth/[...nextauth]/route.tsを作成
NextAuth.jsを使用する際の決まり事のようなものですが、app/api/auth/[...nextauth]/route.ts
を作成し、ファイルの中身を以下のように記述します。
import { authOptions } from "@/app/options";
import NextAuth from "next-auth";
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST }
app/page.tsxを編集
表示する画面を作成していきます。
app
ディレクトリ直下のpage.tsx
を以下のように編集します。
import { getServerSession } from 'next-auth';
import { LogoutButton } from './components/buttons'
import { authOptions } from './options';
import { redirect } from 'next/navigation';
export default async function Home() {
const session = await getServerSession(authOptions);
if (!session) {
redirect('/sign_in')
}
return (
<main className="flex min-h-screen flex-col items-center justify-center">
<div>Welcome: {session?.user?.name}</div>
<LogoutButton/>
</main>
)
}
ここでは、ログイン状態のユーザーには、ユーザー名とログアウトボタンを表示し、未ログイン状態のユーザーには、singInページへ遷移させます。
app/signIn/page.tsxを作成
ユーザーがログインするためのページを作成します。
app
ディレクトリ配下にsignIn
フォルダを作成し、その直下にpage.tsx
ファイルを作成します。page.tsx
ファイルの中身を以下のように記述します。
import { LoginButton } from '../components/buttons'
export default async function Home() {
return (
<main className="flex min-h-screen flex-col items-center justify-center">
<LoginButton/>
</main>
)
}
ここでは、LoginButton
コンポーネントを呼び出して、ユーザーにログインボタンを提示します。
LIFFを用いた方法
ここでは、クライアント側でログインし、プロフィールを取得します。
サーバーサイドで、ユーザー情報を扱いたい場合はこちら(準備中なので、コメントで急かしてください)を参照してください。
LINE DevelopersサイトからLIFFアプリを追加
こちらを参考に、(共通)で作成したチャネルにて、LIFFアプリを追加してください。
エンドポイントURLは、LINEログイン完了後に遷移する先です。
LIFFアプリ作成時はhttps://localhost
とでも設定しておきましょう。
また後ほど設定します。
LIFF IDを使用するので、メモしておきましょう。
参考画像
準備
(共通)準備を参考に、必要な準備をしてください。
LINE Front-end Framework(LIFF)のSDKをインストール
まず、LINE Front-end Framework(LIFF)のSDKをインストールします。
ターミナルで以下のコマンドを実行します。
npm install @line/liff
.envファイルを作成
ルートディレクトリに.env
ファイルを作成し、以下のように編集します。
NEXT_PUBLIC_LIFF_ID=LIFF アプリを作成して取得したLIFF ID
NEXTAUTH_SECRET=以下のようにして作成
NEXTAUTH_SECRET
には、以下のコマンドをターミナルで実行して得られた文字列を設定します。
openssl rand -base64 32
NEXT_PUBLIC_LIFF_ID
はクライアント側で呼び出すので、NEXT_PUBLIC_
が必要です。
app/page.tsxの編集
app
ディレクトリ直下のpage.tsx
ファイルを以下のように編集します。
"use client";
import liff from "@line/liff";
import React, { useState, useEffect } from "react";
export default function Home() {
const [idToken, setIdToken] = useState<string | null>(null);
const [displayName, setDisplayName] = useState<string | null>(null);
useEffect(() => {
liff
.init({ liffId: process.env.NEXT_PUBLIC_LIFF_ID as string })
.then(() => {
console.log("LIFF init succeeded.");
if (liff.isLoggedIn()) {
const token = liff.getIDToken();
setIdToken(token);
} else {
liff.login();
}
})
.catch((e) => {
console.error("LIFF init failed.", e);
setIdToken('');
});
liff.ready.then(async () => {
const userProfile = await liff.getProfile();
console.log(userProfile);
setDisplayName(userProfile.displayName);
})
}, []);
if (idToken === null) {
return <div>Loading...</div>;
}
return (
<div>
<h1>Hello {displayName}</h1>
</div>
);
}
以下の部分では、ユーザーが未ログイン状態のときにログインさせるようにしています。
if (liff.isLoggedIn()) {
const token = liff.getIDToken();
setIdToken(token);
} else {
liff.login();
}
以下の部分は、ログイン後に実行される処理です。
ここで、ユーザーのプロフィールを取得します。
liff.ready.then(async () => {
const userProfile = await liff.getProfile();
console.log(userProfile);
setDisplayName(userProfile.displayName);
})
以下では、idToken
の値を元にローディング画面を表示させています。
if (idToken === null) {
return <div>Loading...</div>;
}
以上で、実装自体はokです。
npm run dev
で立ち上げ、ngrok http 3000
でngrokを発行してください。
ここでhttps://localhost
と設定したエンドポイントURLを発行したngrokに変更してください。
そして、発行したngrokにアクセスすると、ログインができます。
この先
liffを用いて、サーバーサイドでユーザー情報を扱う実装をする。
liffを使用して、ユーザーの課金管理を行う。
などをしていきます。
参考
Discussion