はじめに
Box API を OAuth2 認証経由で利用するまでの手順と、TypeScript によるトークン管理・API 呼び出しの実装方法を紹介します。
1. アプリ登録(Box Developer Console)
-
https://app.box.com/developers/console
にアクセス - アプリを作成
- 「Custom App (OAuth 2.0 with JWT or OAuth 2.0)」を選択
- 必要なスコープ(権限)を設定(例:
Read and write all files and folders
) - 管理者の承認をリクエスト(企業アカウントで必要)
2. クライアント情報を取得
-
Client ID
とClient Secret
をメモ - リダイレクト URI に以下を設定
https://oauth.pstmn.io/v1/callback
企業内で Self-signed certificate を使用している場合、SDK の使用は困難なため、API による実装を選択します。
3. 認可コードの取得(ブラウザ)
以下の URL にアクセス:
https://account.box.com/api/oauth2/authorize?client_id={Client ID}&response_type=code
アクセス後、次のような URL にリダイレクトされます:
https://oauth.pstmn.io/v1/callback?state=&code=xxx
この code
を控えておきます。
4. リフレッシュトークンの取得(Postman)
リクエスト設定
- Method: POST
-
URL:
https://api.box.com/oauth2/token
-
Body:
x-www-form-urlencoded
Key | Value |
---|---|
client_id |
{Client ID} |
client_secret |
{Client Secret} |
code |
前ステップで取得した code
|
redirect_uri |
https://oauth.pstmn.io/v1/callback |
grant_type |
authorization_code |
レスポンス例
{
"access_token": "...",
"refresh_token": "...",
"expires_in": 3599,
"token_type": "Bearer"
}
-
refresh_token
はファイル等に安全に保存して管理します。
5. TypeScript で Box API を使うクラスを実装
refresh_token を管理するストレージ
storage.json
{
"BOX_REFRESH_TOKEN": "xxx"
}
トークン管理付きの Box クラス実装
以下に、あなたの Box.ts
クラスを機能ごとに分割して説明します。各部分の役割や考え方も補足しています。
インポート
Box.ts
import fs from "fs";
import credentials from "@utils/constants/credentials";
import Postman from "@utils/Postman"; // 自作のHTTPユーティリティ
import Logger from "@utils/Logger"; // 自作のログユーティリティ
-
fs
:refresh_token
を保存しているファイル(例:storage.json
)の読み書きに使用。 -
credentials
:client_id
やclient_secret
など、Box API 認証に必要な情報を保持。 -
Postman
: HTTP リクエストを簡潔に記述するためのラッパー。 -
Logger
: エラー発生時のログ出力用。
クラスの定義と初期状態
Box.ts
class Box {
private expiredAt = 0;
private accessToken = "";
-
expiredAt
: アクセストークンの有効期限(Date.now()
形式のタイムスタンプ)。 -
accessToken
: 現在のアクセストークン(API 呼び出し時に使用)。
Box.ts
private async checkToken(): Promise<void> {
if (Date.now() >= this.expiredAt) {
await this.refreshAccessToken();
}
}
- アクセストークンが期限切れであれば、
refreshAccessToken
を呼び出して更新します。 - 毎回の API 呼び出し前にチェックすることで、トークン切れによる失敗を防止します。
refresh_token の取得/保存
Box.ts
private getRefreshToken(): string {
const path = "storage.json";
const storage = JSON.parse(fs.readFileSync(path, "utf-8"));
return storage.BOX_REFRESH_TOKEN;
}
private setRefreshToken(token: string): void {
const path = "storage.json";
const storage = JSON.parse(fs.readFileSync(path, "utf-8"));
storage.BOX_REFRESH_TOKEN = token;
fs.writeFileSync(path, JSON.stringify(storage, null, 2));
}
-
getRefreshToken
: ローカルファイルからrefresh_token
を読み込みます。 -
setRefreshToken
: 取得した新しいrefresh_token
をファイルに保存します。
Box の refresh_token
は毎回変わるため、毎回更新して保存する必要があります。
アクセストークンのリフレッシュ処理
Box.ts
private async refreshAccessToken(): Promise<void> {
const url = `https://api.box.com/oauth2/token`;
const body = {
client_id: credentials.BOX_CLIENT_ID,
client_secret: credentials.BOX_CLIENT_SECRET,
refresh_token: this.getRefreshToken(),
grant_type: "refresh_token",
};
try {
const res = await Postman.postWithEncodedString(url, body);
if (res.status === 200) {
this.accessToken = res.data.access_token;
this.expiredAt = Date.now() + res.data.expires_in * 1000;
this.setRefreshToken(res.data.refresh_token);
} else {
Logger.error(`Token refresh failed: ${res.status} ${JSON.stringify(res.data)}`);
throw new Error("Token refresh failed");
}
} catch (error) {
Logger.error(`Error refreshing token: ${error}`);
throw error;
}
}
-
refresh_token
を使って新しいaccess_token
を取得。 - レスポンスが 200 の場合:
- アクセストークンを更新
- 有効期限を再設定(現在時刻+期限秒数)
-
refresh_token
を保存
- エラー時はログを出力し、例外をスロー。
ファイルのメタデータ取得API
Box.ts
public async getFileMeta(id: string): Promise<void> {
await this.checkToken();
const url = `https://api.box.com/2.0/files/${id}`;
const res = await Postman.get(url, this.accessToken);
console.log(JSON.stringify(res.data, null, 2));
}
- 指定された
fileId
をもとに Box API からメタデータを取得。 -
API を叩く前に
checkToken()
を必ず呼んで、アクセストークンの有効性を保証。
クラスのインスタンスをエクスポート
Box.ts
export default new Box();
-
Box
クラスのシングルトンインスタンスをエクスポート。 - 複数箇所で共通のトークン管理が可能になります。
まとめ:このクラスの設計思想
-
責務の分離:
- 認証処理、トークン管理、API 呼び出しをそれぞれ独立して実装。
-
堅牢性:
- 有効期限切れを事前に検知し、自動更新。
-
セキュリティと可搬性の両立:
-
refresh_token
をローカルファイルで保持し、SDK に依存せずに軽量実装。
-
6. 使用例
sandbox.ts
import "module-alias/register";
import Box from "@class/manager/Box";
(async () => {
await Box.getFileMeta("1234567890"); // 取得したいファイルID
process.exit(0);
})();
補足:セキュリティ上の注意
-
client_secret
やrefresh_token
は.env
や secure vault 等で安全に保管してください - ログや Git にアクセストークンを記録しないように注意してください