タイトルの通りSlackからユーザー情報を取得してみました。
取得する方法はQiitaにも書かれてる方が多いですが、3年前とか割と時が経っていたりもしたので。
今回はnode.jsを使っての取得ですが、リクエスト先は固定なので参考にしてみてください。
※Slackアプリケーションは登録済でOAuth情報がわかっていること前提で紹介しています
- Slackから認証情報を取得する
- Slackからユーザー情報を取得する
- [おまけ] curlでサクッとリクエストしてみる
実行環境
- Node.js: v18.15.0
- npm: 9.5.0
- React: ^18.2.0
1. Slackから認証情報を取得する
ユーザー情報を取得する時に必要なAccessTokenとUserIdを取得します。
このAccessTokenとUserIdを取得するには、前提としてSlackのアプリケーション認証を許可した後にリダイレクトURLに含まれるcode
が必要です。
その辺の認証まわりはこちらの記事を参考にすると良いかなと思います。
https://bagelee.com/programming/Slack-oath-with-react/
code
を取得するリダイレクトURLは以下の通りです。
code
にはOAuth認証で許可されるscope
を含めています。
リダイレクト先で「あなたはscopeA,B,Cから許可された〇〇という情報をアプリに譲渡してもOK?」という画面が表示されるので、それを許可すると、scope
で許可されたデータを取得できるaccecc_token
が与えられます。今回はユーザー情報を取得したいので、そのために必要なscope
をconst scopes
で定義します。
export const slackLoginURI = () => {
const SLACK_CLIENT_ID = import.meta.env.VITE_SLACK_CLIENT_ID
const SLACK_REDIRECT_URI = import.meta.env.VITE_SLACK_REDIRECT_URI
const scopes = "identify,users.profile:read,users:read"
return `https://slack.com/oauth/authorize?client_id=${SLACK_CLIENT_ID}&scope=${scopes}&redirect_uri=${SLACK_REDIRECT_URI}`
}
import.meta.env
のところはvite仕様なので、envの読み取りは適宜変えてください。
urlからcode
の値を取得した後はfetchを使ってAccessTokenとUserIdを取得します。
useEffect(() => {
(async () => {
const params = new URLSearchParams(window.location.search);
const code = params.get("code");
if (code) {
const { access_token, user_id } = await getAuthFromSlack(code);
}
})();
}, []);
export const getAuthFromSlack = async (code: string) => {
const SLACK_CLIENT_ID = import.meta.env.VITE_SLACK_CLIENT_ID
const SLACK_CLIENT_SECRET = import.meta.env.VITE_SLACK_CLIENT_SECRET
const SLACK_REDIRECT_URI = import.meta.env.VITE_SLACK_REDIRECT_URI
const params = new URLSearchParams({
code,
client_id: SLACK_CLIENT_ID,
client_secret: SLACK_CLIENT_SECRET,
redirect_uri: SLACK_REDIRECT_URI
})
const result = await fetch('https://slack.com/api/oauth.access?' + params)
.then(response => response.json())
return {
user_id: result.user_id,
access_token: result.access_token
} as SlackAuthData
}
これでuser_id
とaccess_token
を取得できたので、この値を使ってユーザー情報を取得します。
2. Slackからユーザー情報を取得する
1で取得した user_id
とaccess_token
を使ってユーザー情報を取得します。
前提としてアプリケーションのScopesを以下の通りに変更します。
- Bot Token Scopes
- users.profile:read
- users:read
- User Token Scopes
- users.profile:read
- users:read
Scopeを変更後、アプリケーションのreinstallが必要なので忘れずしましょう。
(多分Slackからwarningポップアップが出ると思いますが)
fetchのままリクエストを送るとcorsブロックのpreflight response ~ と格闘する羽目になるので、こちらはnode.jsでリクエストします。expressを使ってバックエンド側にリクエストを流すことで、node.jsからユーザー情報を取得します。
const { access_token, user_id } = await getAuthFromSlack(code);
// ↓続き
if (!access_token || !user_id) return;
const data = await getUserProfileFromSlack(access_token, user_id);
export const getUserProfileFromSlack = async (token: string, userId: string) => {
return await mutation(
'/auth/slack/user/profile',
RequestType.POST,
{ userId, token }
) as SlackUserProfile
}
/**
* post / put / delete request
* @param {string} prefix
* @param {keyof typeof RequestType} method
* @param {any} body
* @returns
*/
export const mutation = async (prefix: string, method: keyof typeof RequestType, body: any) => {
const BACKEND_URL = import.meta.env.VITE_BACKEND_URL;
const url = `${BACKEND_URL}${prefix}`;
return await fetch(url, {
method,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify(body)
})
.then(response => {
return response.json()
})
}
mutation()
でリクエストをラップしてますが、要はfetchでバックエンドに流しているだけです。nodeだけの検証であれば上で紹介したapi.tsとhook.tsは無視してください。
以下ルーティングを解決した後にSlackからユーザー情報を取得する方法です。
import request from 'request'
/**
* get slack user profile
* @param {SlackProfileRequest} data
* @returns {SlackProfileResponse | null}
*/
export const getSlackUserProfile = async (data: SlackProfileRequest) => {
const { userId, token } = data
if (!userId || !token) return null
const options = {
url: `https://slack.com/api/users.profile.get?user=${userId}&pretty=1`,
method: 'GET',
headers: {
'Authorization': `Bearer ${token}`
},
json: true,
}
const result: SlackProfileResponse = await new Promise((resolve, reject) => {
request(options, (error, response, body) => {
if (!error && response.statusCode === 200) {
resolve(body);
} else {
reject(error);
}
})
})
return (result.ok) ? result.profile : null
}
userId
は1で取得したuser_id
、token
はaccess_token
にあたります。
リクエストURLに&token=xxxxxxx
を含めてリクエストする方法も別の記事でありましたが、こちらの方法は現在使えないようです。代わりに'Authorization': `Bearer ${token}`
とすることでリクエストから欲しい情報を取得できます。
今回のケースだとresult.profile
に欲しい情報があるのでそれを取得します。
結果は以下のようになります。
{
ok: boolean,
profile: {
title: string,
phone: string,
skype: string,
real_name: string,
real_name_normalized: string,
display_name: string,
display_name_normalized: string,
.
.
image_original: string,
email: string,
.
.
}
}
display_name
に表示アカウント名、image_original
にはアカウント使用の画像URLがあります。email
も取得できるので、Slackアカウントを通して認証機能を作ってみるのもありですね。
値の詳細は以下のURLから確認できます。
https://api.slack.com/methods/users.profile.get
[おまけ] curlでサクッとリクエストしてみる
curlでリクエストしたい方はこちら。
curl -H 'Authorization: Bearer xxxxxx' -X GET 'https://slack.com/api/users.profile.get?user=xxxxxx&pretty=1'
xxxxxxにaccess_token,user_idを置き換えて投げてください。
まとめ
今回は簡単にfetch等でリクエストしましたが、sdkもあるようなのでそちらを使って取得してみても良いかもしれません。