🗝️
Honoで雑にOAuth2の流れを理解する
概要と経緯
Honoじゃなくてもなんでも良いのですが、js環境でOAuth2をライブラリなしで動かしたく、とりあえずどこかに備忘録として置いておきたかったという話です。
GoogleのOAuth2で試しました。
免責ですが、雑ゆえにエラーなど全く考慮していません。流れの確認以外には使えないコードであるとご了承ください。
おおまかな流れ
- 認可リクエストを送信
- リダイレクトURLに
code
が返ってくるので、それでアクセストークンを取得する - 試しに userinfo とか取得してみる
1. 認可リクエストの送信
事前に取得しておいた client_id
redirect_uri
で認可リクエストを送信(リダイレクト)します。
http://localhost:3000/auth/login
へ遷移するとGoogleでのログインプロセスに飛びます。
const CLIENT_ID = "XXXXXXXX.apps.googleusercontent.com";
const CLIENT_SECRET = "XXXXXXXXXX";
const REDIRECT_URI = "http://localhost:3000/auth/callback";
app.get("/auth/login", (c) => {
const url = "https://accounts.google.com/o/oauth2/v2/auth";
const params = new URLSearchParams({
client_id: CLIENT_ID,
redirect_uri: REDIRECT_URI,
response_type: "code",
scope: "email profile",
});
return c.redirect(`${url}?${params}`);
});
2. アクセストークンを取得する
リダイレクトURIに code
パラメータ付きでリダイレクトされるので、その code
を使ってアクセストークンを取得します。
取得できたアクセストークンは、とりあえず雑に cookie に焼いておきます。
app.get("/auth/callback", async (c) => {
const params = new URLSearchParams({
code: c.req.query("code") || "",
client_id: CLIENT_ID,
client_secret: CLIENT_SECRET,
redirect_uri: REDIRECT_URI,
grant_type: "authorization_code",
});
// アクセストークンを取得する
const res = await fetch("https://oauth2.googleapis.com/token", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: params.toString(),
});
const data = await res.json();
// アクセストークンはとりあえずcookieに焼いておく
if (data.access_token) {
setCookie(c, "token", data.access_token, {
httpOnly: true,
secure: true,
});
}
// /hello に飛ばしてそっちで動作確認しよう
return c.redirect("/hello");
});
3. 試してみよう
もらったアクセストークンを使って userinfo の取得など試してみます。 Authorization
ヘッダーにアクセストークンを付与します。
app.get("/hello", async (c) => {
const token = getCookie(c, "token");
const url = "https://www.googleapis.com/oauth2/v1/userinfo";
const res = await fetch(url, {
headers: {
Authorization: `Bearer ${token}`,
},
});
const data = await res.json();
return c.json(data);
});
悩みポイント
- アクセストークンを取得するURLの公式情報がなかなか見つけられず、各記事で記載されているURLもバラバラだったため、 OAuth 2.0 Playground で確認をした。
Discussion