SSIトークンライブラリ
SSIトークンライブラリは、リンクとSSIトークンを生成および検証するためのユーティリティクラスを含むJavaライブラリです。このライブラリを使用すると、次のアクションを実行できます。
- アカウントリンクの設定中にAmazonに発行するリンクトークンを生成する。
- アプリへの新規サインインリクエスト時に、SSIトークンを検証してデコードする。
- アプリへの新規サインインリクエスト時にリンクトークンを検証してデコードする。SSIトークンのデコードにより、リンクトークンが抽出される。
- SSIトークンを生成し、内部テストでのAmazon SSIサーバーの動作を模倣する。
プロジェクトでSSIトークンライブラリを使用するには、SimpleSignInTokenCommon-<x.y>.jarというJARファイルを追加します。このJARはここでダウンロードするか、Appstore SDKに含まれているSSIサンプルアプリのlibsフォルダから取得できます。このJARファイルはプロジェクトの依存関係になります。Mavenの直接的および遷移的な依存関係については、SSIサンプルアプリのbuild.gradleファイルを参照してください。
以下のセクションでは、上記のアクションでのライブラリの使用方法と、サンプルコードのリファレンスについて説明します。Javadoc形式の個々のクラスとメソッドの詳細については、SSIトークンライブラリAPIリファレンスを参照してください。
リンクトークンの生成
LinkTokenV1Provider
クラスは、リンクトークンを生成するためのAPIを提供します。LinkTokenV1Provider
のインスタンス化に使用されるコンストラクターは、2つの入力パラメーターを受け取ります。ILinkTokenCryptoKeyProvider
インターフェイスとIAppStorePublicKeyProvider
インターフェイスの実装インスタンスです。これらの実装には、キーストアから暗号化キーを取得するロジックが含まれています。
暗号化キーとパブリックキーペアを取得するロジックは、ILinkTokenCryptoKeyProvider
インターフェイスおよびIAppStorePublicKeyProvider
インターフェイス内にあります。次のコードを使用して、リンクトークンの生成に使用するLinkTokenV1Provider
オブジェクトを作成します。
LinkTokenV1Provider linkTokenV1Provider =
new LinkTokenV1Provider(
new LinkTokenCryptoKeyProvider(), new AppStorePublicKeyProvider());
キーの生成とキャッシュ
次のILinkTokenCryptoKeyProvider
の実装例では、クラスのインスタンス化中にAES 128ビットキーを生成してキャッシュし、リクエストされたらいつでもこのキーを提供します。実際の実装では、事前に作成されたアプリキーが格納されているセキュアストアからキーを取得するロジックを追加する必要があります。
static class LinkTokenCryptoKeyProvider implements ILinkTokenCryptoKeyProvider {
SimpleSignInCryptoKey < SecretKey > cryptoKey;
LinkTokenCryptoKeyProvider() throws TokenException {
try {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128, new SecureRandom());
SecretKey secretKey = keyGenerator.generateKey();
cryptoKey = new SimpleSignInCryptoKey(secretKey, "key.1");
} catch (NoSuchAlgorithmException e) {
throw new TokenException(e);
}
}
@Override
public SimpleSignInCryptoKey < SecretKey > getEncryptionKey(IRequestContext iRequestContext) throws TokenException {
/*
対象アプリリビジョンに使用する暗号化キーを返します。それぞれに複数の
リビジョンがある複数のアプリの所有者は、リクエスト元に関連する
コンテキストを渡すIRequestContextオブジェクトを使用して、
適切なキーを選択できます。
*/
return cryptoKey;
}
@Override
public SimpleSignInCryptoKey < SecretKey > getDecryptionKey(IRequestContext iRequestContext, String s) throws TokenException {
/*
対象アプリリビジョンに使用する復号化キーを返します。それぞれに複数の
リビジョンがある複数のアプリの所有者は、リクエスト元に関連する
コンテキストを渡すIRequestContextオブジェクトを使用して、
適切なキーを選択できます。
*/
return cryptoKey;
}
}
静的キーペアの生成
次の2つのコードサンプルでは、IAppStorePublicKeyProvider
を実装して、静的キーペアをローカルで生成し、生成されたキーペアのパブリックキーコンポーネントをgetPublicKey()
メソッドで公開します。実際の実装では、Amazonアプリストアによって割り当てられたパブリックキーが保存されているセキュアストアからキーマテリアルを取得するためのロジックを追加する必要があります。
private static KeyPair appStoreKeyPair;
static {
KeyPairGenerator keyPairGenerator;
try {
keyPairGenerator = KeyPairGenerator.getInstance("RSA");
} catch (NoSuchAlgorithmException ex) {
throw new RuntimeException(ex);
}
keyPairGenerator.initialize(2048);
appStoreKeyPair = keyPairGenerator.generateKeyPair();
}
static class AppStorePublicKeyProvider implements IAppStorePublicKeyProvider {
@Override
public SimpleSignInCryptoKey < PublicKey > getPublicKey(IRequestContext iRequestContext)
throws AppStorePublicKeyException {
/*
ここではKeyIdentifier「key.1」はハードコードされています。実際の実装では、開発者によってリクエスト元に関する
関連情報(アプリとそのバージョンなど)がIRequestContextオブジェクトに
追加されているでしょう。その内容は、キーIDおよび使用するのに適切なパブリックキーを
決定するために使用されます。
*/
SimpleSignInCryptoKey < PublicKey > appStorePublicKey =
new SimpleSignInCryptoKey < > (appStoreKeyPair.getPublic(), "key.1");
return appStorePublicKey;
}
}
リンクトークンの生成
generateLinkToken()
メソッドを呼び出せばリンクトークンを生成できます。GenerateLinkTokenV1Request
タイプのリクエストオブジェクトには、トークン内でエンコードされる詳細情報が含まれています。
GenerateLinkTokenV1Request request = GenerateLinkTokenV1Request.builder()
.directedAmazonUserId("amazonUserId")
.partnerUserId("partnerUserId")
.customFields(null) // カスタムフィールドのマップ
.requestContext(requestContext)
.build();
LinkTokenContainer linkTokenContainer = linkTokenV1Provider.generateLinkToken(request);
出力として返されるLinkTokenContainer
オブジェクトには、以下のデータが含まれます。
- token: リンクトークンペイロード。システム内のユーザーのIDをキャプチャするプレーンな文字列です。Amazonユーザーとのリンクを証明するために使用されます。
- tokenSchema: リンクトークンスキーマ
LINK-TOKEN-1.0
。 - linkSigningKeyEncrypted: リンク署名キー。このリンクのSSIトークンに署名するECプライベートキー。Amazonアプリストアのパブリックキーを使用して暗号化されます。
SSIトークンの検証とデコード
SSIトークンを検証してデコードするには、SSITokenV1Validator
クラスのdecodeAndVerifyToken()
メソッドを使用します。このメソッドは、SSIトークンの署名を検証し、トークンの有効期限が切れていないことを確認します。
SSITokenV1Validator ssiTokenV1Validator
= new SSITokenV1Validator(linkTokenV1Provider);
SSITokenInfo ssiTokenInfo = ssiTokenV1Validator
.decodeAndVerifyToken(ssiToken, requestContext);
この例で使用されている入力パラメーターは以下のとおりです。
linkTokenV1Provider
-SSITokenV1Validatorのコンストラクターに渡される
LinkTokenV1Provider
オブジェクト。これは、リンクトークンの生成用に設定したLinkTokenV1Provider
のインスタンスと同じです。requestContext
-IRequestContext
インターフェイスの実装のインスタンス。このオブジェクトには、ILinkTokenCryptoKeyProvider
を実装して、適切な復号化キーの取得、リンクトークンの復号化、リンク検証キーの抽出を行うために必要な詳細情報が含まれています。リンク検証キーは、その中に埋め込まれたSSIトークン署名を検証するために使用されます。ssiToken
- デコードして検証するSSIToken
オブジェクト。
SSIトークン
SSIトークンの形式は、SSIToken(token=<xxxxx.yyyyy.zzzzz>, schema=SSI-TOKEN-1.0)
です。このトークン
はJSON Web Token(JWT)で、通常は「xxxxx.yyyy.zzzzz」のように表示されます。xxxxxはBase64Urlでエンコードされたヘッダー、yyyyyはBase64Urlでエンコードされたペイロード、zzzzzはxxxxxとyyyyyの計算された署名で、アプリ固有のプライベートキーを使用します。
デコードされたSSIトークンの形式は以下のとおりです。
SSITokenInfo(linkInfo=SSITokenInfo.LinkInfo(directedAmazonUserId=amazonUserId,
directedPartnerUserId=partnerUserId,
linkToken=LinkToken(token=<システム内のユーザーのIDをキャプチャし、
Amazonユーザーとのリンクを証明するプレーンな文字列のリンクトークン。このトークンの
文字列はアカウントリンクのリクエスト中に渡されました>, tokenSchema=LINK-TOKEN-1.0)),
tokenMetadata=SSITokenV1Metadata(super=SSITokenMetadata(issuedAt=1628082286000,
notValidBefore=1628082286000, expiresAt=1628082586000),issuer=http://ssi.amazon.com,
audience=TEST_DEVELOPER_ID,jwtId=66141c38-1bb5-4336-a2a6-55247345dc99))
decodeToken()
メソッドを使用できます。リンクトークンの検証とデコード
SSIトークンが正常に検証されたら、ラップされたリンクトークンを検証し、トークンからユーザーIDの詳細を抽出します。これを実行するには、LinkTokenV1Provider
のvalidateLinkToken()
メソッドを使用します。
LinkTokenInfo linkTokenInfoFromSSIToken = linkTokenV1Provider
.validateLinkToken(ssiTokenInfo, requestContext);
この例で使用されているvalidateLinkToken()
メソッドの入力パラメーターは以下のとおりです。
ssiTokenInfo
-SSITokenInfo
タイプのインスタンス。SSIトークンからデコードされた詳細情報が含まれています。requestContext
-IRequestContext
インターフェイスの実装のインスタンス。このオブジェクトには、リンクトークンの復号に使用する復号化キーを取得するためのILinkTokenCryptoKeyProvider
の実装に必要な詳細情報が含まれています。
SSIトークンの生成
本番アプリではSSIトークンを自分で生成する必要はありませんが、テスト目的ではトークンを生成することができます。SSIトークンライブラリを使用してSSIトークンを生成する手順は以下のとおりです。
- リンクトークンの生成で説明されている手順に従ってリンクトークンを生成します。
-
テストアプリで、Amazonアプリストアのキーペアのプライベートキーとパブリックキーの両方にアクセスできると仮定します。ただし、本番アプリの場合、アクセスできるのはパブリックキーだけです。
IAppStorePrivateKeyProvider
インターフェイスを実装し、プライベートキーにアクセスしてリンク署名キーを復号できるようにします。このリンク署名キーは、リンクトークンと共に発行され、Amazonアプリストアのパブリックキーを使用して暗号化されます。次の
IAppStorePrivateKeyProvider
インターフェイスの実装例では、静的キーペアをローカルで生成し、getPrivateKey()
メソッドを使用してプライベートキーを公開します。両方のコードサンプルを使用します。private static KeyPair appStoreKeyPair; static { KeyPairGenerator keyPairGenerator; try { keyPairGenerator = KeyPairGenerator.getInstance("RSA"); } catch (NoSuchAlgorithmException ex) { throw new RuntimeException(ex); } keyPairGenerator.initialize(2048); appStoreKeyPair = keyPairGenerator.generateKeyPair(); }
static class AppStorePrivateKeyProvider implements IAppStorePrivateKeyProvider { @Override public SimpleSignInCryptoKey < PrivateKey > getPrivateKey(String app, String appVersion) throws AppStorePrivateKeyException { SimpleSignInCryptoKey < PrivateKey > appStorePrivateKey = new SimpleSignInCryptoKey < > (appStoreKeyPair.getPrivate(), "key.1"); return appStorePrivateKey; } }
-
LinkSigningKeyDecryptor
オブジェクトを使用してリンク署名キーを復号化します。LinkSigningKeyDecryptor
インスタンスは、IAppStoreprivateKeyProvider
インターフェイスの実装を使用して構築されます。LinkSigningKeyDecryptor linkSigningKeyDecryptor = new LinkSigningKeyDecryptor(new AppStorePrivateKeyProvider()); String linkSigningKey = linkSigningKeyDecryptor .decryptLinkSigningKey(linkTokenContainer.getLinkSigningKeyEncrypted(), "TEST_ASIN", "TEST_APP_VERSION");
-
次のように
Link
オブジェクトを作成し、アカウントのリンク関係を表すAmazonでの表記を生成します。Link link = Link.builder() .linkId("amzn1.ssi.link.123456") .directedAmazonUserId("amazonUserId") .directedPartnerUserId("partnerUserId") .identityProvider("partnerIdp") .linkedTime(System.currentTimeMillis()) .linkSigningKey(linkSigningKey) .linkToken(linkTokenContainer.getLinkToken()) .build();
- 前の手順で作成した
Link
オブジェクトを使用して、リンク済みアカウントのSSIトークンを生成します。SSITokenV1Generator
クラスで公開されたgenerateToken()
APIを使用して、次のようにSSIトークンを作成します。
SSITokenV1Generator ssiTokenV1Generator = new SSITokenV1Generator();
ProductInfo productInfo = ProductInfo.builder()
.vendorId("TEST_DEVELOPER_ID")
.asin("TEST_ASIN")
.productVersion("TEST_APP_VERSION")
.build();
SSIToken ssiToken = ssiTokenV1Generator.generateToken(link, productInfo);