Todos os produtos
Search
Central de documentação

Identity as a Service:Conecte aplicações Java ao IDaaS para sincronização de contas

Última atualização: Jun 28, 2026

Conecte sua aplicação Java ao Identity as a Service (IDaaS) para receber e processar eventos de sincronização de contas. O IDaaS envia eventos ao endpoint HTTP da sua aplicação como JSON Web Tokens (JWTs) assinados. Antes de processar qualquer evento, verifique a assinatura para confirmar a autenticidade da solicitação. Ignorar esta etapa permite que invasores enviem eventos falsificados e acionem alterações não autorizadas nas contas.

Execute uma ou ambas as etapas a seguir para implementar a sincronização de contas:

  • Verificação de assinatura (obrigatória): valida se o IDaaS enviou o evento e se não houve adulteração.

  • Descriptografia (opcional): descriptografa o payload do evento quando a Criptografia de Dados de Serviço está ativada.

Para obter detalhes sobre o envio de eventos pelo IDaaS e o fluxo geral de chamadas, consulte Visão geral.

Pré-requisitos

Antes de começar, certifique-se de ter:

  • Uma aplicação Java com um endpoint HTTP acessível publicamente.

  • Acesso à configuração de sincronização da sua aplicação no IDaaS.

  • O Maven configurado no seu projeto.

Verifique a assinatura

O IDaaS assina todo evento enviado com uma chave privada RSA. Sua aplicação verifica a assinatura usando a chave pública correspondente, publicada no endpoint de chave pública na configuração de sincronização da aplicação.

Funcionamento da verificação de assinatura:

  1. Obtenha o JSON Web Key Set (JWKS) do endpoint de chave pública.

  2. Associe o ID da chave (kid) no cabeçalho do JWT a uma chave no JWKS.

  3. Verifique a assinatura do JWT usando a chave pública RSA associada.

  4. Valide as claims do JWT: emissor (urn:alibaba:idaas:app:event), audiência (ID da sua aplicação), tempo de expiração e tempo de emissão.

O consumidor de JWT usa dois parâmetros de janela de tempo na configuração:

  • setMaxFutureValidityInMinutes(1): rejeita tokens datados com mais de 1 minuto no futuro para proteger contra manipulação de relógio.

  • setAllowedClockSkewInSeconds(120): permite até 120 segundos de diferença de relógio entre o IDaaS e seu servidor.

Etapa 1: Obtenha a URL do endpoint de chave pública

Localize a URL do endpoint de chave pública na configuração de sincronização da sua aplicação no IDaaS.

image

Para obter instruções sobre como acessar a configuração de sincronização, consulte Sincronização de contas - Sincronizar contas do IDaaS em uma aplicação.

O endpoint retorna um documento JWKS no seguinte formato:

{
  "keys": [
    {
      "kty": "RSA",
      "e": "AQAB",
      "use": "sig",
      "kid": "KEY3PdQDx97********h83p8husNSC9AKMH",
      "n": "rLUnH5PNeGUZE-********GGIxyM5O7TDdaG4********D9mV1CjE8hVHBxXM96IcCCH_1xmUZEZRp_MBP6m2XeNWUXanCpeyuIAD2kxmaQAqituZdIlT4l3-q9gtccdY-khaE-OfH9qYZhlxFcYj0gVtOvKZFIkuGhME4IQJd_RAWS3OPXxtbGhO2fZYCiuuc8NWub5mcVQnqsy5aJPLwHbVwVUwYNOmaq97_m2TtPcIVWtw7AOzX8O78UrYnYt_QPrv7uVdJMbHleSOx2A1IXqrAkJWecwFfvTsBTCUOPPDeVRQEHzzwmf3zpz5KMgHZU1I5pyqi0KJ6BuMHWw"
    }
  ]
}
Nota: Para linguagens diferentes de Java, clique em na URL do endpoint de chave pública na configuração de sincronização para baixe a chave pública e armazene-a em um arquivo .pem local.

Etapa 2: Adicione a dependência do Maven

Adicione a seguinte dependência ao seu pom.xml:

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

Etapa 3: Adicione a classe utilitária JwtUtil

Copie a seguinte classe utilitária para o seu projeto. Ela busca o JWKS do endpoint de chave pública, armazena-o em cache na memória e constrói um consumidor de JWT configurado.

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;

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("Fetch JWKs from url failed: " + 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();
        // Reject tokens dated more than 1 minute in the future (prevents clock manipulation attacks)
        jwtConsumerBuilder.setMaxFutureValidityInMinutes(1);
        // Allow up to 120 seconds of clock drift between IDaaS and your server
        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("Cannot find verification key: " + 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();
    }
}

Etapa 4: Verifique o evento

Chame JwtUtil no seu manipulador de eventos para verificar o JWT e extrair o payload:

// Public key — get the JWKS from the public key endpoint in the application's synchronization configuration
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"
            + "}";;

// Application ID — find the ID of your application in the application list
String appId = "app_mjavzivahje6zxxxx";

// Build a JWT consumer using the JWKS and application ID
JwtConsumer jwtConsumer = JwtUtil.createJwtConsumer(new JsonWebKeySet(publicKey), appId);

// Verify the signature and extract the payload
// Pass the raw value of the event parameter received by your endpoint
JwtClaims jwtClaims = jwtConsumer.processToClaims("The value of the event parameter");

// Access the payload data
Map<String, Object> map = jwtClaims.getClaimsMap();
// Process your business logic using the event data

Descriptografe o payload do evento (opcional)

Se a Criptografia de Dados de Serviço estiver ativada para sua aplicação, o IDaaS criptografa os dados do evento usando AES (Advanced Encryption Standard) antes do envio. Os dados criptografados são transmitidos no campo cipher_data do payload do evento. Descriptografe cipher_data para obter os dados originais do evento.

Etapa 1: Obtenha a chave de criptografia

Nas configurações da sua aplicação no IDaaS, insira uma chave de criptografia ou clique em Generate Key para gerar uma.

image

Copie a chave para usá-la no código de descriptografia.

Etapa 2: Adicione as dependências do Maven

Adicione ambas as dependências ao seu pom.xml:

<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>

Etapa 3: Descriptografe cipher_data

O método a seguir descriptografa o valor de cipher_data usando JSON Web Encryption (JWE) com AES-GCM:

public String decrypte(String cipherData, String key) throws JoseException {
    String alg = "AES";

    // Build the AES key from the hex-encoded encryption key
    SecretKeySpec secretKeySpec = new SecretKeySpec(Hex.decode(key), alg);
    JsonWebKey jsonWebKey = JsonWebKey.Factory.newJwk(secretKeySpec);

    JsonWebEncryption receiverJwe = new JsonWebEncryption();

    // Restrict the allowed key agreement algorithm to "dir" (direct encryption)
    AlgorithmConstraints algConstraints = new AlgorithmConstraints(AlgorithmConstraints.ConstraintType.PERMIT, new String[]{"dir"});
    receiverJwe.setAlgorithmConstraints(algConstraints);

    // Restrict the allowed content encryption algorithms to AES-GCM variants
    AlgorithmConstraints encConstraints = new AlgorithmConstraints(
        AlgorithmConstraints.ConstraintType.PERMIT, new String[]{"A256GCM", "A192GCM", "A128GCM"});
    receiverJwe.setContentEncryptionAlgorithmConstraints(encConstraints);

    // Set the decryption key and the ciphertext
    receiverJwe.setKey(jsonWebKey.getKey());
    receiverJwe.setCompactSerialization(cipherData);

    // Return the decrypted event data as a UTF-8 string
    return new String(receiverJwe.getPlaintextBytes(), StandardCharsets.UTF_8);
}

Próximos passos

  • Revise o esquema de payload do evento para entender os campos do evento de sincronização de contas.

  • Visão geral: entenda como o IDaaS envia eventos e a arquitetura geral de provisionamento.