シンプルにSlackのAPIを利用したくてOAuth認証のコードを作成しました。
完成したアプリは問題なく動いていたのですが、ある日新機能追加のためにローカルで色々試していたところ突然認証が通らなくなりました。
最終的には解決できましたが、突破口の発見は正直偶然に近かったので同じハマりで困っている人の助けになればと記事に残しておきます。
起きた問題
下記はredilect_urlのサーバー内の処理です。
Slackから渡されるcodeをresponseから取り出して、それをそのままSlackの認証用APIに返すシンプルな作りです。
認証後にクライアントにレスポンスを返す部分は少しNext.jsですが、この問題には特に関係しないのでありのまま記載します。
import { Response } from 'express';
import querystring from 'querystring';
import { getOrCreateAxios } from '../../modules/createAxios';
import Server from 'next';
export const AuthController = (handle: ReturnType<ReturnType<typeof Server>['getRequestHandler']>) => async (
req: any,
res: Response
) => {
const code = req.query.code as string;
const error = req.query.error as string;
if (!code) {
res.redirect('/home');
return;
}
if (error === 'access_denied') {j
res.redirect('/home');
return;
}
console.log('code', code); // デバッグ用
const params = {
code: code,
client_id: 'validclientid', // 記事用の仮の値
client_secret: 'validclientsecret',
};
console.log('params', querystring.stringify(params)); // デバッグ用
const result = await axios.post(
'https://slack.com/api/oauth.v2.access',
querystring.stringify(params)
);
console.log('result', result.data); // invalid_codeが返されることがわかる
req.token = result.data;
req.botToken = appConst.SLACK_BOT_TOKEN;
handle(req, res);
};
そしてSlack認証用のフロント側のリンクのURLがこちら
ほとんどSlack公式からのコピー&ペーストなので特に問題のないものです。
https://[正しいワークスペース名].slack.com/oauth/[クライアントID]?client_id=[正しいクライアントID]&scope=[正しいスコープ]&user_scope=[正しいスコープ]&state=&granular_bot_scope=1&install_redirect=&response_type=&response_mode=&nonce=&openid_connect=0&single_channel=0&redirect_uri=http://localhost:3000/callback
で、axiosでの認証リクエストのレスポンスがこちら
{ ok: false, error: 'invalid_code' }
途中でcodeやparamsといった変数を出力していますが、どちらも期待通りの結果でした。
Slackから渡されたコードをそのまま出力できます。
解決編
原因は今でも腑に落ちていませんが、Slackに登録しているRedirect URLsでした。
登録値が**http://localhost:3000**になっていたのです。ボタンのURLで指定しているredirect_uriと一致していません。
http://localhost:3000 /callback に直すことで解決しました。
ドメインが同じであれば問題なくリダイレクトされる公式Docのどこかで読んだと思っていたのでパスを最後まで書いてはいませんでした。
どうやら他のプロダクトのAPIとの勘違いだったようで、下記にはAppセッティングでもURLパラメータでもサブディレクトリまで指定しろと書いてありました。
公式Doc: More on Redirect URLs
それにしてもエラーコードがinvalid_codeだったので気づくのが遅くなりました。
'bad_redirect_uri'というエラーコードもあるはずなのですが、今回なぜこちらが出なかったのかまで調べられていません。
とはいえ、起きた事実として共有させていただきます。
困っている人(あるいはまた同じハマり型をした未来の自分)の役に立てば幸いです。