コンピューターサイエンスで最も難しい2つの問題は、キャッシュの無効化とネーミングだと言われています。正直なところ、それは間違っていません。これらは超難問です。
ネーミングを難しくするのは、明確でありながら簡潔であることです。変数、用語、関数、クラスの意味について疑問があってはなりません。もし、ある用語が2つの意味のどちらかであると考えるなら、それは正しく命名されていないということです。
APIキーとトークンがそうです。先日、この2つの言葉が同じように飛び交うディスカッションをしました。2分ほどで会話を中断し、”これらは違うものだと知っているよね?”と言わなければなりませんでした。
どうやら彼らは知らなかったようです。結局のところ、多くの人がAPIキーとトークンの違いを教えてくれないのです。だから、整理しましょう。
定義
APIキーとトークンは以下の定義で区別できます:
・APIキー – APIを呼び出す際に、呼び出し元を特定し認証するためにコードから提供される値。プログラムで使用されることを意図しており、多くの場合、文字と数字の長い文字列です。
・トークン – ユーザー・セッションまたは特定の権限を表すデータの一部。個々のユーザーが限られた期間だけ使用します。
生成
作成方法も通常、両者で異なります。
・APIキー – 多くの場合、ユーザー・インターフェースを介して1回だけ作成され、ローテーションされるまで固定されます。オプションで、一定時間が経過すると失効するように設定することもできます。
・トークン – 認証やログインが成功した際に動的に生成されます。多くの場合、有効期限は短いが、より長い期間リフレッシュすることができます。
範囲
パーミッションのスコープとは、認可の部分、つまり、提供されたauthメソッドを使用するときに実行できる機能のことです。
・APIキー – アプリの機能に対する固定された不変の権限セット。キーを持っている人は誰でも許可されたリソースにアクセスできます。
・トークン – 個人がアクセスできる特定のデータや機能に限定されます。これは、ロールやその他のビジネスレベルの要件に影響される可能性があります。データ制限に重点を置く傾向があります。
セキュリティ
それぞれの方法の安全性は?キーやトークンが漏洩したり、悪意のあるユーザーに取得された場合、潜在的な損害はどの程度でしょうか?
・APIキー – これらは一般的に寿命が長く、データへのアクセスを制限しないため、漏洩すると壊滅的な打撃を受ける可能性があります。これらのキーは、唯一の解決手段として失効させる必要があります。多くの場合、アプリケーションは漏洩したキーを特定し、悪意のあるユーザーを見つけるために、優れた観測性を持つ必要があります。
・トークン – セキュリティを考慮して設計されています。一般に寿命が短く、簡単に失効します。漏洩したトークンは、そのユーザーがアクセスできるデータの範囲しか持たず、自動的に失効します。
利用方法
では、どんな場合にどちらを使うのか?長所と短所のバランスがとれているように思えます。
・APIキー – サーバー間通信、天気APIのような公開データへのアクセス、サードパーティーシステムとの統合に使用します。
・トークン – ユーザー認証、きめ細かなアクセス制御(FGAC)、リソースへの一時的なアクセス許可、ブラウザアクセス、ユーザーセッションの管理に使用します。
実際の例
この2つの違いを理解したところで、Momento JavaScript SDKを使用した2つの実践例を見てみましょう。
API Keys
APIキーは一般的にユーザー・インターフェースを介して発行されると言いました。そのことを念頭に置いて、共有できるコードサンプルはありません。しかし、以下にユーザとしてMomento ConsoleからAPIキーを取得する方法を示します。
必要な権限を選択し、オプションで有効期限を設定し、生成します。その後、ワークフローですぐにAPIキーを使うことができます。
トークン
ログインに成功すると発行されるユーザーベースの使い捨てトークンとは対照的です。ロールベースの例として、calendar-events キャッシュへのアクセスは読み取り専用だが、コラボレーションのためのトピックへのアクセスは公開と購読が可能なユーザを考えてみましょう。
// called on successful login
exports.handler = async (event) => {
const user = await loadUserMetadata(event.userId);
let token;
switch (user.role) {
case 'data-entry':
token = await getDataEntryToken(user.tenantId);
break;
case 'admin':
token = await getAdminToken(user.tenantId);
break;
default:
throw new Error('Role not supported');
}
return token;
};
const getDataEntryToken = async (tenantId) => {
const scope = {
permissions: [
{
role: 'readonly',
cache: 'calendar-events',
item: {
keyPrefix: tenantId
}
},
{
role: 'publishsubscribe',
cache: 'collaboration',
topic: `${tenantId}-events`
}
]
};
const response = await authClient.generateDisposableToken(scope, ExpiresIn.minutes(15));
return {
token: response.authToken,
expiresAt: response.expiresAt.epoch()
};
};
ここでは、15分間有効なトークンを作成し、capabilitiesのreadonlyパーミッションをスコープし、ユーザーが所属するtenantIdで始まるキャッシュアイテムのみにアクセスできるようにしています。つまり、ユーザーの属性に基づいて、機能とデータの両方を制限しています。
ポイントのまとめ
APIキーとトークンには長所と短所があります。どちらが優れているということはありません。コンピュータ・サイエンスのあらゆることと同じように、それはあなたのユースケースに依存します。どの認証メカニズムを実装するかを決める際には、ユーザーがアプリケーションとどのようにやりとりするかを考慮することが重要です。
ウェブ上のユーザーベースのセッションの場合、トークンを使ってください。どのデータが利用可能かをスコープする必要がなく、プログラムによるアクセスのみを想定しているかもしれない場合、APIキーを使用しましょう。クイック・リファレンスのために、上のリファレンス・テーブルを自由に保存してください。
どのような道を選ぶにせよ、データを安全に保管することを忘れないでください。誰もデータ漏洩で廃業に追い込まれることは望んでいません。安全第一で。
Momentoの使い方に興味があったり、アクセスコントロールのレベルを決めるのに助けが必要な場合は、いつでも私たちのDiscordに飛び込んで、チームに直接質問してください。また、開発者向けのドキュメントも 24 時間 365 日閲覧可能です。
Happy coding!