LoginSignup
0
0

Slackからユーザー情報を取得する

Last updated at Posted at 2023-06-02

タイトルの通りSlackからユーザー情報を取得してみました。
取得する方法はQiitaにも書かれてる方が多いですが、3年前とか割と時が経っていたりもしたので。

今回はnode.jsを使っての取得ですが、リクエスト先は固定なので参考にしてみてください。
※Slackアプリケーションは登録済でOAuth情報がわかっていること前提で紹介しています

  1. Slackから認証情報を取得する
  2. Slackからユーザー情報を取得する
  3. [おまけ] 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が与えられます。今回はユーザー情報を取得したいので、そのために必要なscopeconst 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を取得します。

index.tsx
  useEffect(() => {
    (async () => {
      const params = new URLSearchParams(window.location.search);
      const code = params.get("code");

      if (code) {
        const { access_token, user_id } = await getAuthFromSlack(code);
      }
    })();
  }, []);
api.ts
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_idaccess_tokenを取得できたので、この値を使ってユーザー情報を取得します。

2. Slackからユーザー情報を取得する

1で取得した user_idaccess_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からユーザー情報を取得します。

index.tsx
const { access_token, user_id } = await getAuthFromSlack(code);
// ↓続き
if (!access_token || !user_id) return;
const data = await getUserProfileFromSlack(access_token, user_id);
api.ts
export const getUserProfileFromSlack = async (token: string, userId: string) => {
    return await mutation(
        '/auth/slack/user/profile',
        RequestType.POST,
        { userId, token }
    ) as SlackUserProfile
}
hook.ts
/**
 * 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からユーザー情報を取得する方法です。

backend.ts
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_idtokenaccess_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もあるようなのでそちらを使って取得してみても良いかもしれません。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0