LINE WORKS Service Account 認証 (JWT) の確認ポイント
LINE WORKS API の Service Account 認証のエラーで悩んだら、JWT (JSON Web Token) の RFC 準拠を確認してみましょう。RFC 非準拠によるエラーの可能性があります。
LINE WORKS API を利用する際の Service Account 認証では、JWT を用いてトークン生成を行います。JWT の取り扱いにおいては、RFC-7519 (JWT)、RFC-7515 (JWS)、および RFC-7523 (JWT Profile for OAuth 2.0) に準拠する必要があります。これにより、標準に沿ったトークン生成が可能となり、LINE WORKS API の認証が正しく行われます。
確認したいポイント
1. Base64 エンコード
JWT のヘッダーとペイロード部分は、「Base64 URL エンコード」でエンコードする必要がありますが、一般的な Base64 エンコードを用いるケースが見受けられます。
RFC-7515 (JSON Web Signature) の該当箇所
Base64url Encoding
...
No padding (e.g., using "=") characters are used in base64url-encoded data.
例えば、Google Apps Script (GAS) を使用する場合、Utilities.base64EncodeWebSafe を利用します。これは、URL セーフな Base64 エンコードを行い、+
を -
、/
を _
に置き換え、さらに不要なパディング文字である =
を削除 します。
もし Utilities.base64Encode
を使用すると、URL セーフではない形式でエンコードするため、JWT の仕様に準拠しません。
- RFC 準拠:
var encodedHeader = Utilities.base64EncodeWebSafe(JSON.stringify(header));
var encodedPayload = Utilities.base64EncodeWebSafe(JSON.stringify(payload));
- 非準拠:
var encodedHeader = Utilities.base64Encode(JSON.stringify(header));
var encodedPayload = Utilities.base64Encode(JSON.stringify(payload));
2. Claim Set (exp
, iat
) の型
exp
(有効期限) や iat
(発行時刻) は、UNIX タイムスタンプとして数値型で記述する必要があります。しかし、これを文字列型で指定してしまう例があります。
誤りの例
{
"exp": "1672531200",
"iat": "1672527600"
}
正しい方法
{
"exp": 1672531200,
"iat": 1672527600
}
RFC-7519 (JSON Web Token) の該当箇所
The "exp" (expiration time) claim identifies the expiration time on or after which the JWT MUST NOT be accepted for processing. The value MUST be a number representing seconds since the epoch.
The "iat" (issued at) claim identifies the time at which the JWT was issued. The value MUST be a number representing seconds since the epoch.
JWT の生成方法例
以下に、Python と Google Apps Script を使用した正しい JWT 生成の例を示します。
Python の例
import jwt
import time
# JWT ヘッダー
header = {
"alg": "RS256",
"typ": "JWT"
}
# JWT ペイロード
payload = {
"iss": "your_client_id",
"sub": "your_service_account",
"iat": int(time.time()), # 発行時刻
"exp": int(time.time()) + 3600 # 有効期限
}
# 秘密鍵
private_key = """-----BEGIN PRIVATE KEY-----
your_private_key
-----END PRIVATE KEY-----"""
# JWT 生成
token = jwt.encode(payload, private_key, algorithm="RS256", headers=header)
print("Generated JWT:")
print(token)
Google Apps Script の例
function createJWT() {
var header = {
"alg": "RS256",
"typ": "JWT"
};
var payload = {
"iss": "your_client_id",
"sub": "your_service_account",
"iat": Math.floor(Date.now() / 1000), // 発行時刻 (数値型)
"exp": Math.floor(Date.now() / 1000) + 3600 // 有効期限 (数値型)
};
var encodedHeader = Utilities.base64EncodeWebSafe(JSON.stringify(header));
var encodedPayload = Utilities.base64EncodeWebSafe(JSON.stringify(payload));
var signature = Utilities.computeRsaSha256Signature(encodedHeader + "." + encodedPayload, privateKey);
var encodedSignature = Utilities.base64EncodeWebSafe(signature);
return encodedHeader + "." + encodedPayload + "." + encodedSignature;
}
まとめ
JWT を正しく生成するためには、以下のポイントを守ることが重要です。
-
Base64 URL エンコードを使用
一般的な Base64 エンコードではなく、URL セーフな形式を使用する。 -
Claim Set (
exp
,iat
) を数値型で指定
RFC に準拠するため、UNIX タイムスタンプを使用する。
これらの実装ミスを避けることで、LINE WORKS との認証連携を円滑に行うことができます。