1import { signInWithCustomToken, signOut } from 'firebase/auth';
2import { collection, doc, setDoc } from 'firebase/firestore';
3import { useRouter } from 'next/router';
4import React, { useEffect } from 'react';
5import { useAuth } from '../context/auth';
6import { auth, db } from '../firebase/client';
7import { Site } from '../lib/site';
8
9const AuthLine = () => {
10 const router = useRouter();
11 const { user } = useAuth();
12
13 const openLineLoginPage = async () => {
14 const stateRef = doc(collection(db, 'lineStates'));
15 const state = stateRef.id;
16
17 await setDoc(stateRef, {
18 createdAt: Date.now(),
19 });
20
21 const url = new URL('https://access.line.me/oauth2/v2.1/authorize');
22 url.search = new URLSearchParams({
23 response_type: 'code',
24 client_id: process.env.NEXT_PUBLIC_LINE_CLIENT_ID as string,
25 redirect_uri: `${Site.origin}/line-login`,
26 state,
27 scope: 'profile openid',
28 }).toString();
29
30 location.assign(url);
31 };
32
33 useEffect(() => {
34 if (router.query.code && router.query.state) {
35 fetch('/api/line-custom-token', {
36 method: 'POST',
37 headers: {
38 'Content-Type': 'application/json',
39 },
40 body: JSON.stringify({
41 code: router.query.code as string,
42 state: router.query.state as string,
43 }),
44 })
45 .then((res) => res.text())
46 .then((token) => {
47 signInWithCustomToken(auth, token).then(() => {
48 router.replace(
49 {
50 query: {
51 id: router.query.id,
52 },
53 },
54 undefined,
55 {
56 shallow: true,
57 }
58 );
59 });
60 });
61 }
62 }, [router.query.code]);
63
64 return (
65 <div>
66 <button
67 className="bg-[#06c755] px-3 py-2 rounded shadow text-white"
68 onClick={openLineLoginPage}
69 >
70 LINE でログイン
71 </button>
72 {user && (
73 <div className="mt-4">
74 <p className="mb-2">ログイン中です</p>
75
76 <div className="flex items-center space-x-4">
77 <img
78 className="rounded-full w-10 h-10"
79 src={user.photoURL}
80 alt=""
81 />
82 <p>{user.name}</p>
83 <button className="text-pink-600" onClick={() => signOut(auth)}>
84 ログアウト
85 </button>
86 </div>
87 </div>
88 )}
89 </div>
90 );
91};
92
93export default AuthLine;
LINEからメールアドレスも取得したい場合メールアドレスの取得権限を申請し、リクエスト時のスコープ設定を profile openid email
に設定してください。
なし