すべてのプロダクト
Search
ドキュメントセンター

Identity as a Service:Java アプリケーションを IDaaS に接続してアカウントを同期する

最終更新日:Mar 20, 2025

このトピックでは、Java アプリケーションを Identity as a Service (IDaaS) に接続する方法について説明します。

接続の仕組みと呼び出しプロセスについて詳しくは、「概要」をご参照ください。

アカウント同期を実装するには、次の 1 つまたは 2 つのステップを実行する必要があります。

  • 署名検証

  • 復号 (オプション)

上記の手順が完了すると、アプリケーションはこのイベントのリクエストを受信し、リクエストを処理します。

1. 署名検証

アプリケーションの同期構成から公開鍵エンドポイントを取得します。詳細については、「アカウント同期 - アプリケーションで IDaaS アカウントを同期する」をご参照ください。

image

このトピックでは、公開鍵エンドポイントから直接公開鍵を取得する Java ユーティリティクラスを提供しています。使用しているプログラミング言語で公開鍵情報が必要な場合は、公開鍵エンドポイント URL をクリックして公開鍵を取得し、公開鍵をローカルの .pem ファイルに保存する必要がある場合があります。

次のコードは、公開鍵の例を示しています。

{
  "keys": [
    {
      "kty": "RSA",
      "e": "AQAB",
      "use": "sig",
      "kid": "KEY3PdQDx97********h83p8husNSC9AKMH",
      "n": "rLUnH5PNeGUZE-********GGIxyM5O7TDdaG4********D9mV1CjE8hVHBxXM96IcCCH_1xmUZEZRp_MBP6m2XeNWUXanCpeyuIAD2kxmaQAqituZdIlT4l3-q9gtccdY-khaE-OfH9qYZhlxFcYj0gVtOvKZFIkuGhME4IQJd_RAWS3OPXxtbGhO2fZYCiuuc8NWub5mcVQnqsy5aJPLwHbVwVUwYNOmaq97_m2TtPcIVWtw7AOzX8O78UrYnYt_QPrv7uVdJMbHleSOx2A1IXqrAkJWecwFfvTsBTCUOPPDeVRQEHzzwmf3zpz5KMgHZU1I5pyqi0KJ6BuMHWw"
    }
  ]
}

次の例は、Maven プロジェクトに依存関係を追加する方法を示しています。

<dependency>
  <groupId>org.bitbucket.b_c</groupId>
  <artifactId>jose4j</artifactId>
  <version>0.7.9</version>
</dependency>

次のコードは、IDaaS 公開鍵エンドポイントから公開鍵を取得し、署名を検証するために使用されるユーティリティクラスです。コードを直接コピーして使用できます。

import org.apache.commons.codec.binary.StringUtils;
import org.jose4j.jwk.JsonWebKey;
import org.jose4j.jwk.JsonWebKeySet;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
import org.jose4j.lang.JoseException;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

// IDaaS 公開鍵エンドポイントから公開鍵を取得し、署名を検証するためのユーティリティクラス
public class JwtUtil {
    private final static ConcurrentMap<String, JsonWebKeySet> IDAAS_SIGN_JWK_SET_MAP = new ConcurrentHashMap<>();

    public static JwtConsumer createJwtConsumerFromUrl(String jwkUrl, String appId) {
        try {
            final JsonWebKeySet jsonWebKeySet = getJsonWebKeySetByUrl(jwkUrl);
            return createJwtConsumer(jsonWebKeySet, appId);
        } catch (Exception e) {
            throw new RuntimeException("URL から JWK の取得に失敗しました: " + e.getMessage() + ", " + jwkUrl, e);
        }
    }

    public static JwtConsumer createJwtConsumer(JsonWebKeySet jsonWebKeySet, String appId) {
        final JwtConsumerBuilder jwtConsumerBuilder = new JwtConsumerBuilder();
        jwtConsumerBuilder.setExpectedIssuer("urn:alibaba:idaas:app:event");
        jwtConsumerBuilder.setRequireExpirationTime();
        jwtConsumerBuilder.setRequireJwtId();
        jwtConsumerBuilder.setRequireIssuedAt();
        jwtConsumerBuilder.setRequireExpirationTime();
        jwtConsumerBuilder.setMaxFutureValidityInMinutes(1);
        jwtConsumerBuilder.setAllowedClockSkewInSeconds(120);
        jwtConsumerBuilder.setExpectedAudience(appId);
        jwtConsumerBuilder.setVerificationKeyResolver((jws, nestingContext) -> {
            final String signKeyId = jws.getKeyIdHeaderValue();
            for (JsonWebKey jsonWebKey : jsonWebKeySet.getJsonWebKeys()) {
                if (StringUtils.equals(jsonWebKey.getKeyId(), signKeyId)) {
                    return jsonWebKey.getKey();
                }
            }
            throw new RuntimeException("検証キーが見つかりません: " + signKeyId);
        });
        return jwtConsumerBuilder.build();
    }

    synchronized private static JsonWebKeySet getJsonWebKeySetByUrl(String jwkUrlString) throws IOException, JoseException {
        JsonWebKeySet jsonWebKeySet = IDAAS_SIGN_JWK_SET_MAP.get(jwkUrlString);
        if (jsonWebKeySet == null) {
            jsonWebKeySet = innerGetJsonWebKeySetByUrl(jwkUrlString);
            IDAAS_SIGN_JWK_SET_MAP.put(jwkUrlString, jsonWebKeySet);
        }
        return jsonWebKeySet;
    }

    private static JsonWebKeySet innerGetJsonWebKeySetByUrl(String jwkUrlString) throws IOException, JoseException {
        final URL jwkUrl = new URL(jwkUrlString);
        final URLConnection urlConnection = jwkUrl.openConnection();
        urlConnection.setConnectTimeout(50000);
        urlConnection.setReadTimeout(50000);
        final String jwkSetJson = new String(readAll(urlConnection.getInputStream()), StandardCharsets.UTF_8);
        return new JsonWebKeySet(jwkSetJson);
    }

    public static byte[] readAll(InputStream inputStream) throws IOException {
        final byte[] buffer = new byte[1024 * 8];
        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
        for (int len; ((len = inputStream.read(buffer)) != -1); ) {
            baos.write(buffer, 0, len);
        }
        return baos.toByteArray();
    }
}

次のコードは、呼び出しの例を示しています。

// 公開鍵 -> IDaaS のアプリケーションの同期構成で公開鍵エンドポイントにアクセスして公開鍵を取得します。
String publicKey = "{\n"
            + "  \"keys\": [\n"
            + "    {\n"
            + "      \"kty\": \"RSA\",\n"
            + "      \"e\": \"AQAB\",\n"
            + "      \"use\": \"sig\",\n"
            + "      \"kid\": \"KEYHH4yFa1c*******qNo1nJ7nM2FR3595P1\",\n"
            + "      \"n\": \"oy_xxxxxxxxxxxxxxxxxxxxxxx95d1padSEABqIbcTKcnlTaET3WHaR"
            + "-3MvsooeZWluv94GQEp-U2jzM1adgTqBl_7KPjUk0dwrZbob_8pOLX5UQMF7Oo_nH5-H5EyL9-yGGhFA4oeuA"
            + "-b73qXShxP7eHs5xTT1kiYEu2NE3rBZdtrRwUiC_h1DvZMtyWFOPwm3dpLiwCcdlgcKvVuSEXyCBj6Gjevn3_G1guVQ2kHlNOVyNn6Ky1iGQJzXctJCEJ5fnBRs4XZZbPNSciYMD2-__cRdbYPtGyyuoEAfouw\"\n"
            + "    }\n"
            + "  ]\n"
            + "}";;

// アプリケーション ID -> アプリケーションリストでアプリケーションの ID を見つけます。
String appId = "app_mjavzivahje6zxxxx";
// JwtUtil -> JwtUtil ユーティリティクラスは以下で提供されています。
JwtConsumer jwtConsumer = JwtUtil.createJwtConsumer(new JsonWebKeySet(publicKey),appId);

// JSON Web トークン (JWT) 署名が検証された後にペイロードを取得します。
// event パラメータの値 -> API 操作で受信したパラメータ値。
JwtClaims jwtClaims=jwtConsumer.processToClaims("event パラメータの値");
// 特定のペイロードを取得します。
Map<String, Object> map = jwtClaims.getClaimsMap();
// 特定のデータに基づいてビジネスを処理します。

2. 復号 (オプション)

データの復号

アプリケーションでサービスデータ暗号化が有効になっている場合、イベントデータは暗号化され、cipher_data で送信されます。アプリケーションは cipher_data の値を復号してイベントデータを取得する必要があります。

暗号鍵を入力するか、[鍵の生成] をクリックして暗号鍵を生成できます。

image

鍵をコピーして、復号中に使用します。

次の例は、Maven プロジェクトに依存関係を追加する方法を示しています。

<dependency>
  <groupId>org.bitbucket.b_c</groupId>
  <artifactId>jose4j</artifactId>
  <version>0.7.9</version>
</dependency>
<dependency>
  <groupId>org.bouncycastle</groupId>
  <artifactId>bcprov-jdk15on</artifactId>
  <version>1.70</version>
</dependency>

次のコードは、復号の例を示しています。

public String decrypte(String cipherData,String key) throws JoseException {
    String alg = "AES";
    
    // 鍵を使用して KeySpec を生成します。
    SecretKeySpec secretKeySpec = new SecretKeySpec(Hex.decode(key), alg);
    JsonWebKey jsonWebKey = JsonWebKey.Factory.newJwk(secretKeySpec);
    
    JsonWebEncryption receiverJwe = new JsonWebEncryption();
    
    // 暗号化および復号メカニズムを設定します。
    AlgorithmConstraints algConstraints = new AlgorithmConstraints(AlgorithmConstraints.ConstraintType.PERMIT, new String[]{"dir"});
    receiverJwe.setAlgorithmConstraints(algConstraints);
    
    AlgorithmConstraints encConstraints = new AlgorithmConstraints(
        AlgorithmConstraints.ConstraintType.PERMIT, new String[]{"A256GCM", "A192GCM", "A128GCM"});
    receiverJwe.setContentEncryptionAlgorithmConstraints(encConstraints);
    
    // 鍵と暗号文を指定します。
    receiverJwe.setKey(jsonWebKey.getKey());
    receiverJwe.setCompactSerialization(cipherData);
    
    // 復号されたコンテンツを返します。
    return new String(receiverJwe.getPlaintextBytes(), StandardCharsets.UTF_8);
}