LoginSignup
5
6

More than 1 year has passed since last update.

【LINE WORKS】PythonでAPI 2.0を呼び出してみる (Service Account認証パターン)

Last updated at Posted at 2022-04-07

はじめに

4/1にLINE WORKS APIの新しいバージョン「API2.0」が正式リリースされ、認証方式も新しくなったためPythonを実装例にまとめてみる。

まず、LINE WORKS API2.0には、認証方式が二種類ある。

  • User Account認証
    • LINE WORKSユーザーでログインを行い、Access Tokenを発行してAPIを利用する方法。
    • スマホアプリやWebアプリ等に組み込む場合はこちらをつかう。
  • Service Account認証  ←今回はこちら
    • 仮想管理者アカウントを使用して認証を行い、Access Tokenを発行してAPIを利用する方法。
    • チャットボットやバッチ処理等でシステムがAPIを利用する場合はこちらを使う。

今回は、Service Account認証によるアクセストークンの取得までの流れと、それを使ったAPI呼び出しの一例としてBotのメッセージ送信APIの実装例、そしてトークン更新についてまでをまとめる。

  1. 前準備
  2. JWTの生成
  3. アクセストークン発行
  4. APIリクエストを送る (トークにBotからメッセージ送信)
  5. リフレッシュトークンでアクセストークンを再発行

ドキュメント

前提

  • LINE WORKSテナントを作成済み、かつ、Developer Consoleの操作権限があること。
  • フリープラン以上 (有料プランである必要なし)
  • 環境
    • Python 3.9

1. 前準備

API2.0を使うために、まずはDeveloper Consoleで「アプリ」作成を行う。

image.png

API2.0では、API利用のための認証情報・権限設定はこのアプリで設定でき、また、用途に分けて複数のアプリを作成できる。

API利用のための以下の情報をアプリから取得する。

項目 取得方法
Client ID アプリ作成時に自動生成
Client Secret アプリ作成時に自動生成
Service Account Service Account認証で利用される仮想管理者アカウント。「発行」から作成する。
Private Key Service Account認証で利用される、秘密鍵。Service Accountの発行後に発行する。

image.png

次に、アクセストークンに与える権限を「OAuth Scopes」で指定する。今回は、Botのメッセージ送信を行うために bot scopeにチェックしておく。

image.png

2. JWTの生成

前準備としてアプリの設定の完了後、アクセストークン取得を実装していく。

Service Account認証には、OAuth 2.0の拡張仕様 「JWT Bearer Token Grant Type Profile for OAuth 2.0」 RFC7523 が採用されており、JWTを生成しアクセストークン発行を行う。

アクセストークンの取得のための情報をJWTの形でまとめて、署名付きフォーマット (= JWS ) として作成する。

JWSの作成に必要な情報は以下の通り。

  • Client ID
  • Service Account
  • Private Key

今回は PyJWT を使ってJWS生成を実装する。

import jwt
from datetime import datetime


def get_jwt(client_id, service_account_id, privatekey):
    """アクセストークンのためのJWT取得
    """
    current_time = datetime.now().timestamp()
    iss = client_id
    sub = service_account_id
    iat = current_time
    exp = current_time + (60 * 60) # 1時間

    jws = jwt.encode(
        {
            "iss": iss,
            "sub": sub,
            "iat": iat,
            "exp": exp
        }, privatekey, algorithm="RS256")

    return jws

3. アクセストークン発行

上記で作成したJWSを使ってアクセストークンを発行する。

アクセストークン発行では、以下の情報が必要。

  • Client ID
  • Client Secret
  • Scope
    • 今回は bot を指定する。
  • 作成したJWS
import urllib
import requests

BASE_AUTH_URL = "https://auth.worksmobile.com/oauth2/v2.0"


def get_access_token(client_id, client_secret, scope, jws):
    """アクセストークン取得"""
    url = '{}/token'.format(BASE_AUTH_URL)

    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }

    params = {
        "assertion": jws,
        "grant_type": urllib.parse.quote("urn:ietf:params:oauth:grant-type:jwt-bearer"),
        "client_id": client_id,
        "client_secret": client_secret,
        "scope": scope,
    }

    form_data = params

    r = requests.post(url=url, data=form_data, headers=headers)

    body = json.loads(r.text)

    return body

リクエストに成功すると、以下のようにアクセストークンを含むJsonが返る。

{
    "access_token":"jp1AAABFNKyxc7xsVRQVKrTNFchiiMkQrfJMDM6whobYxfbO4fsF23mvuxRvSuMY57DG4uPI/NI4eNMSt8sroqpqFhe3HemLI3OvCar5FFfOQdqUBgqFA/MaHZVXHqsNJgoX7KaGwDTum+zhEyfwjGSrrJZfSoRpTHHrwny4F4UDEA1Lep3dVUUUKAIQHcq0TwCjiWkMnJAXMEFFfbdVzH3FCv+kpb2OH1NbYzL376fXLh3vMUlyRBXPTf3Lv0bK5NsvjR3BNMR3GSvVzjM59lR5ctBK8PvtTdmaHbVGXzJBHv+S3mp1UuD0szSuxCsWUrdCS7/PiWbQwM4++k+WM/bta5EB9v9s9YQGlyklE3fqhnYLGx/9jWanFgrvptCambOW8lv5A==",
    "refresh_token":"jp1AAAAVq8kTeVPKkD11iLMP1mTqzYOd2T/r2x6QoBM2P3D8X6FfDi9wG5Hepsmh/LVpo3n3d/jcP/rnhtEw1VOpU4MJnxHVzu1x5VhKRmG/o63HERu2bnMtFHQVsjhljcf5fpm+Q==",
    "scope": "bot",
    "token_type": "Bearer",
    "expires_in": 86400
}

これに含まれる access_token を使ってAPIリクエストを送り、また、 refresh_token を使ってアクセストークンの再発行を行う。

4. APIリクエストを送る (トークにBotからメッセージ送信)

発行したアクセストークンを用いてAPIリクエストを送ってみる。

今回は、Botからトークへメッセージを送信するリクエストを送る。

※ Botの作成の仕方は割愛。 参考

import requests
import json

BASE_API_URL = "https://www.worksapis.com/v1.0"


def send_message(content, bot_id, user_id, access_token):
    """メッセージ送信"""
    url = "{}/bots/{}/users/{}/messages".format(BASE_API_URL, bot_id, user_id)

    headers = {
          'Content-Type' : 'application/json',
          'Authorization' : "Bearer {}".format(access_token)
        }

    params = content
    form_data = json.dumps(params)

    r = requests.post(url=url, data=form_data, headers=headers)

    r.raise_for_status()

実行すると、このようなメッセージが届く。
image.png

5. リフレッシュトークンでアクセストークンを再発行

アクセストークンは「24時間」が有効期限となっており、継続してAPIを使うためには再発行が必要。
再発行をするには、アクセストークンの取得時に返るリフレッシュトークン refresh_token を使い、再発行リクエストを送る。

なお、リフレッシュトークンの有効期限は「90日間」となっている。

必要な情報は以下の通り。

  • Client ID
  • Client Secret
  • リフレッシュトークン
    • アクセストークン取得時に返る refresh_token

再発行されるアクセストークンには、初回取得時に設定したScopeがそのまま付与される。

import requests

BASE_AUTH_URL = "https://auth.worksmobile.com/oauth2/v2.0"


def refresh_access_token(client_id, client_secret, refresh_token):
    """アクセストークン更新"""
    url = '{}/token'.format(BASE_AUTH_URL)

    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }

    params = {
        "refresh_token": refresh_token,
        "grant_type": "refresh_token",
        "client_id": client_id,
        "client_secret": client_secret,
    }

    form_data = params

    r = requests.post(url=url, data=form_data, headers=headers)

    body = json.loads(r.text)

    return body

まとめ

従来のAPIと比べると変わった点もいくつかあるが、scope周りも含めスッキリとまとまった印象。

ここまでのサンプルソースコードはこちら。
https://github.com/mmclsntr/lw-api-2_0-python-send-message-sample

5
6
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
5
6