All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.cybersource.flex.sdk.CaptureContextImpl Maven / Gradle / Ivy

package com.cybersource.flex.sdk;

import com.cybersource.flex.sdk.impl.HttpResponse;
import com.cybersource.flex.sdk.repackaged.JSONObject;
import com.cybersource.shared.jwt.JWE;
import com.cybersource.shared.jwt.JWT;

import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.RSAPublicKeySpec;
import java.util.Base64;
import java.util.Map;

public final class CaptureContextImpl extends JwtJwtClaimsImpl implements CaptureContext {

    CaptureContextImpl(final PublicKey publicKey, final String jwt, final String correlationId, long startTime) {
        super(publicKey, jwt, correlationId, startTime);
    }

    static CaptureContextImpl fromString(final FlexService flexService, final String jwt, final String correlationId, final long startTime) {
        final PublicKey publicKey = pubKey(flexService, jwt, correlationId, startTime);
        return new CaptureContextImpl(publicKey, jwt, correlationId, startTime);
    }

    // typical internal use when SDKs makes remote call to Flex API
    static CaptureContext fromHttpResponse(final FlexService flexService, HttpResponse response, long startTime) {
        final JSONObject jsonObject = new JSONObject(response.getBody());
        final String jwt = jsonObject.getString("keyId"); // till v2, we need to get it from keyId.
        final String corrId = response.getHeaderFirstValue("v-c-correlation-id");
        try {
            return fromString(flexService, jwt, corrId, startTime);
        } catch (IllegalArgumentException iae) { // i.e. not JWT / JSON
            throw new FlexException.FlexIOException("Unable to parse response", iae, corrId, startTime);
        }
    }

    private static PublicKey pubKey(final FlexService flexService, final String jwt, final String correlationId, long startTime) {
        final Map header = JWT.parseHeader(jwt);
        final String kid = header.get("kid").toString();
        final PublicKey publicKey = flexService.flexPublicKey(kid);
        if (publicKey == null) {
            throw new FlexException.FlexSecurityException(String.format("Unable to find Public Key with %s kid.", kid), correlationId, startTime);
        }
        return publicKey;
    }

    @Override
    public String getFlexOrigin() {
        final Map flx = jwt.payload("flx");
        return flx.get("origin").toString();
    }

    @Override
    public String getTokensPath() {
        final Map flx = jwt.payload("flx");
        return flx.get("path").toString();
    }


    @Override
    public PublicKey getPublicKey() {
        try {
            final Map flexPublicKey = getJsonWebKey();
            final RSAPublicKeySpec publicKeySpec = new RSAPublicKeySpec(
                    new BigInteger(1, Base64.getUrlDecoder().decode(flexPublicKey.get("n"))),
                    new BigInteger(1, Base64.getUrlDecoder().decode(flexPublicKey.get("e")))
            );
            final KeyFactory factory = KeyFactory.getInstance("RSA");
            return factory.generatePublic(publicKeySpec);
        } catch (GeneralSecurityException e) {
            throw new IllegalStateException("Unable to decode public RSA key", e);
        }
    }

    @Override
    public Map getJsonWebKey() {
        final Map flx = jwt.payload("flx");
        return (Map) flx.get("jwk");
    }

    @Override
    public String jwe(Map data) {
        if (data == null || data.isEmpty()) {
            throw new IllegalArgumentException("at least one key/value pair must be provided.");
        }

        final JWE jwe = new JWE();
        jwe.payload("context", toString());
        jwe.payload("data", data);
        jwe.payload("index", 0L);
        return jwe.compact(getJsonWebKey().get("kid"), getPublicKey());
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy