コンソール画面での設定
CreateでProviderを作成します。
以上でチャンネルの作成が完了しました。
ログインをする
こちらにある例を参考に進めていきます。
redirect_uriはコンソールで登録したコールバックURLにします。
stateはひとまずサンプルと同じに「12345abcde」とします。
scopeは「profile%20openid%20email」にします。
そして、以下のようにLinkを作ります。
ここではNext.jsで使用します。
<Link href='https://access.line.me/oauth2/v2.1/authorize?response_type=code&client_id=${CHANNNEL_ID}&redirect_uri=${CALLBACL_URL}&state=12345abcde&scope=profile%20openid%20email'>
Lineログイン
</Link>
その後、redirect_uriに設定したURLにリダイレクトされます。その時URLにcodeとstateが付されます。
${redirect_uri}?code=${code}&state=12345abcde
上記URLのcode部分を取り出してlineLoginServerComponent内でレスポンスに含まれるrefresh tokenをクッキーとして格納します。
次に、lineLoginServerComponentのレスポンスに含まれるaccess_tokenを利用してgetLinProfileServerComponentを実行してユーザーのプロフィールを取得します。
リダイレクト先
'use client';
import { lineLoginServerComponent } from '@/app/actions/set-cookie';
export default function App() {
useEffect(() => {
lineLogin();
}, []);
const lineLogin = async () => {
const params = new URLSearchParams();
if (searchParams.get('code') != null) {
params.append('code', searchParams.get('code')!);
const data = await lineLoginServerComponent(searchParams.get('code')!);
console.log(data);
const profile = await getLinProfileServerComponent(data.access_token);
console.log(profile);
setUser({ ...user, uid: profile.userId, displayName: profile.displayName });
}
};
}
client_secretはchannelのChannel secretを使用します。
app/actions/set-cookie.tsx
export async function lineLoginServerComponent(searchParams: string) {
try {
const params = new URLSearchParams();
params.append('grant_type', 'authorization_code');
params.append('code', searchParams);
params.append('redirect_uri', `${process.env.NEXT_PUBLIC_LINE_REDIRECT_URI}`);
params.append('client_id', `${process.env.NEXT_PUBLIC_LINE_CLIENT_ID}`);
params.append('client_secret', `${process.env.NEXT_PUBLIC_LINE_CLIENT_SECRET}`);
const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: params.toString(),
};
const response = await fetch('https://api.line.me/oauth2/v2.1/token', requestOptions);
const data = await response.json();
if (response.ok) {
console.log(data);
await setCookieAction(data.refresh_token, data.expires_in);
return data;
} else {
console.log('Error:', data);
}
} catch (error) {
console.error('Error during LINE login:', error);
}
}
export async function getLinProfileServerComponent(access_token: string) {
try {
const requestOptions = {
method: 'GET',
headers: {
Authorization: `Bearer ${access_token}`,
},
};
const response = await fetch('https://api.line.me/v2/profile', requestOptions);
const data = await response.json();
if (response.ok) {
console.log(data);
return data;
} else {
console.log('Error:', data);
}
} catch (error) {
console.error('Error fetching profile:', error);
}
}
export async function setCookieAction(token: string, expire: number): Promise<void> {
await cookies().set({
name: 'line_refresh_token',
value: token,
httpOnly: true,
domain: `${process.env.NEXT_PUBLIC_COOKIE_DOMAIN}`,
maxAge: 7776000,
sameSite: 'lax',
secure: true,
path: '/',
});
}
以上でログイン、プロフィールの取得が完了です。
ログインを維持する
次に、リロードなどした際にもログインを維持する処理をcontextに組み込みます。
@/context/AuthContext.tsx
'use client';
import {
getLinProfileServerComponent,
updateTokenServerComponent,
} from '@/app/actions/set-cookie';
useEffect(() => {
getProfile();
}, []);
const getProfile = async () => {
const data = await updateTokenServerComponent();
console.log(data);
if (data) {
const profile = await getLinProfileServerComponent(data.access_token);
console.log(profile);
setUser({ ...user, uid: profile.userId, displayName: profile.displayName });
}
};
app/actions/set-cookie.tsx
export async function updateTokenServerComponent() {
try {
const hasCookie = await haveCookieAction(); // Assuming haveCookieAction is defined elsewhere
if (!hasCookie) {
throw new Error('No cookie found');
}
const params = new URLSearchParams();
params.append('grant_type', 'refresh_token');
params.append('refresh_token', hasCookie.value);
params.append('client_id', `${process.env.NEXT_PUBLIC_LINE_CLIENT_ID}`);
params.append('client_secret', `${process.env.NEXT_PUBLIC_LINE_CLIENT_SECRET}`);
const requestOptions = {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: params.toString(),
};
const response = await fetch('https://api.line.me/oauth2/v2.1/token', requestOptions);
const data = await response.json();
if (response.ok) {
console.log(data);
await getLinProfileServerComponent(data.access_token);
await setCookieAction(data.refresh_token, data.expires_in);
return data;
} else {
console.log('Error:', data);
}
} catch (error) {
console.error('Error updating token:', error);
}
}
参考