c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith/**
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * Copyright (c) 2016 ForgeRock AS. All Rights Reserved
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * The contents of this file are subject to the terms
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * of the Common Development and Distribution License
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * (the License). You may not use this file except in
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * compliance with the License.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * You can obtain a copy of the License at legal/CDDLv1.0.txt.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * See the License for the specific language governing
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * permission and limitations under the License.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * When distributing Covered Code, include this CDDL
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * Header Notice in each file and include the License file at legal/CDDLv1.0.txt.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * If applicable, add the following below the CDDL Header,
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * with the fields enclosed by brackets [] replaced by
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * your own identifying information:
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * "Portions Copyrighted [year] [name of copyright owner]"
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithpackage com.forgerock.openam.functionaltest.sts.frmwk.rest;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport com.fasterxml.jackson.core.JsonParser;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport com.fasterxml.jackson.databind.ObjectMapper;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.json.JsonValue;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.json.resource.ResourceException;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.shared.sts.SharedSTSConstants;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.AMSTSConstants;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.TokenCancellationException;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.TokenCreationException;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.TokenType;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.TokenTypeId;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.TokenValidationException;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.user.invocation.OpenAMTokenState;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.user.invocation.OpenIdConnectTokenCreationState;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.user.invocation.OpenIdConnectTokenState;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.user.invocation.ProofTokenState;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.user.invocation.RestSTSTokenCancellationInvocationState;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.user.invocation.RestSTSTokenTranslationInvocationState;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.user.invocation.RestSTSTokenValidationInvocationState;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.user.invocation.SAML2TokenCreationState;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.user.invocation.SAML2TokenState;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.user.invocation.UsernameTokenState;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.user.invocation.X509TokenState;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.sts.token.SAML2SubjectConfirmation;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.openam.utils.IOUtils;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport org.forgerock.util.encode.Base64;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport javax.inject.Inject;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.io.IOException;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.io.InputStream;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.io.OutputStreamWriter;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.net.HttpURLConnection;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.net.MalformedURLException;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.net.URL;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.security.cert.CertificateEncodingException;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.security.cert.X509Certificate;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.util.logging.Level;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithimport java.util.logging.Logger;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith/**
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * This class demonstrates consumption of rest-sts token transformations.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmithpublic class RestSTSConsumer {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private final URL restSTSInstanceTranslateUrl;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private final URL restSTSInstanceValidateUrl;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private final URL restSTSInstanceCancelUrl;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private final Logger logger;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith /**
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @param restSTSInstanceTranslateUrl The full url of the rest-sts instance, with the translate action specfied.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * For example, for a rest-sts instance with a deployment url of instanceId, published to the
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * root realm, the url would be: http://amhost.com:8080/openam/rest-sts/instanceId?_action=translate
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * A rest-sts instance published to realm fred with a deployment url of instanceId2, the
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * url would be: http://amhost.com:8080/openam/rest-sts/fred/instanceId2?_action=translate
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * A rest-sts instance published to realm bobo, a sub-realm of fred, with a deployment url of
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * instanceId3, the url would be: http://amhost.com:8080/openam/rest-sts/fred/bobo/instanceId3?_action=translate
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @param restSTSInstanceValidateUrl The full url of the rest-sts instance, with the translate action specfied.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * For example, for a rest-sts instance with a deployment url of instanceId, published to the
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * root realm, the url would be: http://amhost.com:8080/openam/rest-sts/instanceId?_action=validate
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * A rest-sts instance published to realm fred with a deployment url of instanceId2, the
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * url would be: http://amhost.com:8080/openam/rest-sts/fred/instanceId2?_action=validate
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * A rest-sts instance published to realm bobo, a sub-realm of fred, with a deployment url of
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * instanceId3, the url would be: http://amhost.com:8080/openam/rest-sts/fred/bobo/instanceId3?_action=validate
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @throws MalformedURLException In case the specified restSTSInstanceTranslateUrl is mal-formed.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith @Inject
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public RestSTSConsumer(String restSTSInstanceTranslateUrl, String restSTSInstanceValidateUrl,
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith String restSTSInstanceCancelUrl, Logger logger) throws MalformedURLException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith this.restSTSInstanceTranslateUrl = new URL(restSTSInstanceTranslateUrl);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith this.restSTSInstanceValidateUrl = new URL(restSTSInstanceValidateUrl);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith this.restSTSInstanceCancelUrl = new URL(restSTSInstanceCancelUrl);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith this.logger = logger;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith this.logger.log(Level.FINE, "RestSTSConsumer will consume the REST STS at url: " + this.restSTSInstanceTranslateUrl.toString());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith /**
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * Invokes a UsernameToken->SAML2 token transformation.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * Sample json posted at the rest-sts instance in this method:
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith { "input_token_state": { "token_type": "USERNAME", "username": "unt_user1767572069", "password": "password" }, "output_token_state": { "token_type": "SAML2", "subject_confirmation": "BEARER" } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith { "input_token_state": { "token_type": "USERNAME", "username": "unt_user1683257432", "password": "password" }, "output_token_state": { "token_type": "SAML2", "subject_confirmation": "HOLDER_OF_KEY", "proof_token_state": { "base64EncodedCertificate": "MIICQDCCAakCBEeNB0...wWigmrW0Y0Q==" } } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith { "input_token_state": { "token_type": "USERNAME", "username": "unt_user1683257432", "password": "password" }, "output_token_state": { "token_type": "SAML2", "subject_confirmation": "SENDER_VOUCHES" } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @param username the username in the UsernameToken
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @param password the password in the UsernameToken
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @param subjectConfirmation The SAML2 SubjectConfirmation. For HoK, the certificate in the file /cert.jks on the
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * classpath will be included.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @return The string representation of the SAML2 Assertion
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @throws Exception If transformation fails
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public String transformUntToSAML2(String username, String password,
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith SAML2SubjectConfirmation subjectConfirmation, X509Certificate hokProofCert)
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith UsernameTokenState untState = UsernameTokenState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .username(username.getBytes(AMSTSConstants.UTF_8_CHARSET_ID))
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .password(password.getBytes(AMSTSConstants.UTF_8_CHARSET_ID))
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith RestSTSTokenTranslationInvocationState invocationState = RestSTSTokenTranslationInvocationState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .inputTokenState(untState.toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .outputTokenState(buildSAML2TokenCreationState(subjectConfirmation, hokProofCert).toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return invokeTokenTranslation(invocationState.toJson().toString());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public String transformCustomTokenToOIDC(JsonValue customTokenInput) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith RestSTSTokenTranslationInvocationState invocationState = RestSTSTokenTranslationInvocationState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .inputTokenState(customTokenInput)
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .outputTokenState(buildOpenIdConnectTokenCreationState("faux_nonce").toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return invokeTokenTranslation(invocationState.toJson().toString());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public String transformCustomTokenToCustomToken(JsonValue customTokenInput, JsonValue customTokenOutput) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith RestSTSTokenTranslationInvocationState invocationState = RestSTSTokenTranslationInvocationState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .inputTokenState(customTokenInput)
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .outputTokenState(customTokenOutput)
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return invokeTokenTranslation(invocationState.toJson().toString());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public String transformUntToCustomToken(String username, String password, JsonValue customTokenOutput) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith UsernameTokenState untState = UsernameTokenState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .username(username.getBytes(AMSTSConstants.UTF_8_CHARSET_ID))
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .password(password.getBytes(AMSTSConstants.UTF_8_CHARSET_ID))
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith RestSTSTokenTranslationInvocationState invocationState = RestSTSTokenTranslationInvocationState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .inputTokenState(untState.toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .outputTokenState(customTokenOutput)
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return invokeTokenTranslation(invocationState.toJson().toString());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith /*
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith example invocation state:
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith { "input_token_state": { "token_type": "USERNAME", "username": "unt_user1767572069", "password": "password" }, "output_token_state": { "token_type": "OPENIDCONNECT", "nonce": "521828576", "allow_access": true } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public String transformUntToOIDC(String username, String password,
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith String nonce) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith UsernameTokenState untState = UsernameTokenState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .username(username.getBytes(AMSTSConstants.UTF_8_CHARSET_ID))
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .password(password.getBytes(AMSTSConstants.UTF_8_CHARSET_ID))
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith RestSTSTokenTranslationInvocationState invocationState = RestSTSTokenTranslationInvocationState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .inputTokenState(untState.toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .outputTokenState(buildOpenIdConnectTokenCreationState(nonce).toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return invokeTokenTranslation(invocationState.toJson().toString());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith /*
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith Transforming oidc->oidc does make sense - an oidc token issued by e.g. google can be transformed into an oidc token
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith intended for another audience. In this way, OpenAM can function as a 'meta' IdP - it can accept tokens from other
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith IdPs (google), authenticate them, and act as an idp creating a oidc token for another sp.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith { "input_token_state": { "token_type": "OPENIDCONNECT", "oidc_id_token": "eyAidHlwIjogIkpXVCIsICJhbGciOiAiSFMyNTYiIH0.eyAidG9rZW5OYW1AxNDQ4MDUzNjkz...pZW50IiBdIH0.YJFTbrlyAoZ3JP--zfcr8TwG_B0q6bPeUt0bBrx7bEw" }, "output_token_state": { "token_type": "OPENIDCONNECT", "nonce": "247885108", "allow_access": true } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public String transformOIDCToOIDC(String oidcTokenValue, String nonce) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith OpenIdConnectTokenState oidcTokenState = OpenIdConnectTokenState.builder().tokenValue(oidcTokenValue).build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith RestSTSTokenTranslationInvocationState invocationState = RestSTSTokenTranslationInvocationState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .inputTokenState(oidcTokenState.toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .outputTokenState(buildOpenIdConnectTokenCreationState(nonce).toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return invokeTokenTranslation(invocationState.toJson().toString());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith /**
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * Invokes a OpenAMToken->SAML2 token transformation.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * Sample json posted at the rest-sts instance in this method:
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * { "input_token_state": { "token_type": "OPENAM", "session_id": "AQIC5wM...1MjYyAAJTMQAA*" }, "output_token_state": { "token_type": "SAML2", "subject_confirmation": "BEARER" } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * { "input_token_state": { "token_type": "OPENAM", "session_id": "AQIC5...TQ1MjYyAAJTMQAA*" }, "output_token_state": { "token_type": "SAML2", "subject_confirmation": "HOLDER_OF_KEY", "proof_token_state": { "base64EncodedCertificate": "MIICQDCCAakCB...wWigmrW0Y0Q==" } } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * { "input_token_state": { "token_type": "OPENAM", "session_id": "AQIC5...TMQAA*" }, "output_token_state": { "token_type": "SAML2", "subject_confirmation": "SENDER_VOUCHES" } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @param sessionId the OpenAM session ID. Corresponds to the iPlanetDirectoryPro (or equivalent) cookie.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @param subjectConfirmation The SAML2 SubjectConfirmation. For HoK, the certificate in the file /cert.jks on the
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * classpath will be included.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @return The string representation of the SAML2 Assertion
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @throws Exception If transformation fails
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public String transformOpenAMToSAML2(String sessionId,
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith SAML2SubjectConfirmation subjectConfirmation, X509Certificate hokProofCert)
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith OpenAMTokenState sessionState = OpenAMTokenState.builder().sessionId(sessionId).build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith RestSTSTokenTranslationInvocationState invocationState = RestSTSTokenTranslationInvocationState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .inputTokenState(sessionState.toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .outputTokenState(buildSAML2TokenCreationState(subjectConfirmation, hokProofCert).toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return invokeTokenTranslation(invocationState.toJson().toString());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith /*
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith Example invocation state:
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith { "input_token_state": { "token_type": "OPENAM", "session_id": "AQIC5wM2...TMQAA*" }, "output_token_state": { "token_type": "OPENIDCONNECT", "nonce": "471564333", "allow_access": true } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public String transformOpenAMToOIDC(String sessionId,
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith String nonce) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith OpenAMTokenState sessionState = OpenAMTokenState.builder().sessionId(sessionId).build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith RestSTSTokenTranslationInvocationState invocationState = RestSTSTokenTranslationInvocationState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .inputTokenState(sessionState.toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .outputTokenState(buildOpenIdConnectTokenCreationState(nonce).toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return invokeTokenTranslation(invocationState.toJson().toString());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith /**
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * Invokes a OIDCToken->SAML2 token transformation
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * Sample json posted at the rest-sts instance in this method (HoK SubjectConfirmation, with token elements truncated):
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith { "input_token_state": { "token_type": "OPENIDCONNECT", "oidc_id_token": "eyAiYWxQ.euTNnNDExNTkyMjEyIH0.kuNlKwyvZJqaC8EYpDyPJMiEcII" },"output_token_state": { "token_type": "SAML2", "subject_confirmation": "HOLDER_OF_KEY", "proof_token_state": { "base64EncodedCertificate": "MIMbFAAOBjQAwgYkCgYEArSQ...c/U75GB2AtKhbGS5pimrW0Y0Q==" } } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith { "input_token_state": { "token_type": "OPENIDCONNECT", "oidc_id_token": "eyAidHlwIjogIkpXVCIsICJhbGciOiAiSFMyNTYiIH0.eyAidG9rZW5OYW1lIjogImlkX3...gMTQ0ODA1MzY52xpZW50IiBdIH0.yKVp4kInTR-6TZGL3cjvA-adhbIfLqjf8E7ZQWHCm9c" }, "output_token_state": { "token_type": "SAML2", "subject_confirmation": "BEARER" } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith { "input_token_state": { "token_type": "OPENIDCONNECT", "oidc_id_token": "eyAidHlwIjogIkpXVCIsICJhbGciOiAiSFMyNTYiIH0.eyAidG9rZW5O...Q2xpZW50IiBdIH0.yKVp4kInTR-6TZGL3cjvA-adhbIfLqjf8E7ZQWHCm9c" }, "output_token_state": { "token_type": "SAML2", "subject_confirmation": "SENDER_VOUCHES" } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith To set up oauth2, you have to:
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith 1. configure the OAuth2 provider using the common tasks
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith 2. then create a client using the agents tab - reflecting the client id and the redirect uri defined in my
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith integration test. Also add the openid scope
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith 2.5. Make sure you specify a hmac-based based signing in the OAuth2 client.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith 3. then create the oidc module - the issuer should be the url of the openam deployment, with oauth2 appended (e.g.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith http://macbook.dirk.internal.forgerock.com:8080/openam/oauth2), the type should be
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith client-secret, and the secret itself should be that configured for the oauth2 client - we are authN-ing a HMAC-signed jwt.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith 4. if the OpenAM provider is issuing the oidc token, then the azp and aud in the oidc module should be set to
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith the name of the oauth2 client
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @param oidcTokenValue the OpenIdConnect ID token. Note that the targeted rest-sts instance has to be deployed with
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * a AuthTargetMapping which references an instance of the OIDC module with configuration state
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * necessary to validate an OIDC token from a specific issuer.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @param subjectConfirmation The SAML2 SubjectConfirmation. For HoK, the certificate in the file /cert.jks on the
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * classpath will be included.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @param hokProofCert The X509Certificate used as the HolderOfKey proof cert. Null if non-HolderOfKey SubjectConfirmation
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * is specified.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @return The string representation of the SAML2 Assertion
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @throws IOException If transformation fails
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public String transformOpenIdConnectToSAML2(SAML2SubjectConfirmation subjectConfirmation, String oidcTokenValue,
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith X509Certificate hokProofCert)
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (oidcTokenValue == null) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throw new IOException("OIDC token is null!");
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith OpenIdConnectTokenState tokenState = OpenIdConnectTokenState.builder().tokenValue(oidcTokenValue).build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith RestSTSTokenTranslationInvocationState invocationState = RestSTSTokenTranslationInvocationState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .inputTokenState(tokenState.toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .outputTokenState(buildSAML2TokenCreationState(subjectConfirmation, hokProofCert).toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return invokeTokenTranslation(invocationState.toJson().toString());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith /**
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * Invokes a X509->SAML2 token transformation
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * Sample json posted at the rest-sts instance in this method:
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * { "input_token_state": { "token_type": "X509" }, "output_token_state": { "token_type": "SAML2", "subject_confirmation": "SENDER_VOUCHES" } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * { "input_token_state": { "token_type": "X509" }, "output_token_state": { "token_type": "SAML2", "subject_confirmation": "BEARER" } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith { "input_token_state": { "token_type": "X509" }, "output_token_state": { "token_type": "SAML2", "subject_confirmation": "HOLDER_OF_KEY", "proof_token_state": { "base64EncodedCertificate": "MIICQDCCAakCBEeNB0swDQYJKoZIhvcNAQEEB...Fax0JDC/FfwWigmrW0Y0Q==" } } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith *
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * Note that the caller's X509 token must be specified either 1. in a header specified in the publshed rest-sts instance and invoked
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * from one of the trusted hosts, again specified in the published rest-sts instance, or 2. via two-way TLS.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * Note that the targeted rest-sts module has to be deployed with an AuthTargetMapping which reference an instance
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * of the Certificate module configured to reference the client's certificate from the header specified in the
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * AuthTargetMapping, and configured to trust the local OpenAM instance. In addition, the
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * 'Certificate Field Used to Access User Profile' should be set to subject CN. The CN
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * used in the test cert deployed with OpenAM, and used in this integration test, is 'test', so a subject with a uid of
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * 'test' has to be created for account mapping to work.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * Likewise the published rest-sts instance
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * must also be configured to trust the host running this test, and must be configured to reference the client's certificate
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * in the header specified by stsClientCertHeaderName (unless the rest-sts is being consumed via two-way-tls, in which
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * case the stsClientCertHeaderName is irrelevant, as the rest-sts will reference the client's certificate via the
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * javax.servlet.request.X509Certificate ServletRequest attribute.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @param subjectConfirmation The SAML2 SubjectConfirmation. For HoK, the certificate in the file /cert.jks on the
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * classpath will be included.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @param stsClientCertHeaderName The header name specification of where the published sts expects to find the client
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * cert (must correspond to published sts state)
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @param clientCertificate the X509 Certificate that will be authenticated to establish the caller's identity
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @param hokProofCert For SAML2 assertions with HoK SubjectConfirmation, the holder's x509 certificate. Null for non-HoK
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * SubjectConfirmations
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @return The string representation of the SAML2 Assertion
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * @throws IOException If transformation fails
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public String transformX509ToSAML2(SAML2SubjectConfirmation subjectConfirmation, String stsClientCertHeaderName,
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith X509Certificate clientCertificate, X509Certificate hokProofCert)
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith X509TokenState tokenState = new X509TokenState();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith RestSTSTokenTranslationInvocationState invocationState = RestSTSTokenTranslationInvocationState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .inputTokenState(tokenState.toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .outputTokenState(buildSAML2TokenCreationState(subjectConfirmation, hokProofCert).toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return invokeTokenTranslation(invocationState.toJson().toString(), stsClientCertHeaderName, clientCertificate);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith /*
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith Example invocation state:
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * Note that the caller's X509 token must be specified either 1. in a header specified in the publshed rest-sts instance and invoked
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith * from one of the trusted hosts, again specified in the published rest-sts instance, or 2. via two-way TLS.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith { "input_token_state": { "token_type": "X509" }, "output_token_state": { "token_type": "OPENIDCONNECT", "nonce": "2003851386", "allow_access": true } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public String transformX509ToOIDC(String nonce, String stsClientCertHeaderName, X509Certificate clientCertificate)
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith X509TokenState tokenState = new X509TokenState();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith RestSTSTokenTranslationInvocationState invocationState = RestSTSTokenTranslationInvocationState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .inputTokenState(tokenState.toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .outputTokenState(buildOpenIdConnectTokenCreationState(nonce).toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return invokeTokenTranslation(invocationState.toJson().toString(), stsClientCertHeaderName, clientCertificate);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private SAML2TokenCreationState buildSAML2TokenCreationState(SAML2SubjectConfirmation subjectConfirmation,
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith X509Certificate hokProofCert) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (SAML2SubjectConfirmation.HOLDER_OF_KEY.equals(subjectConfirmation)) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith ProofTokenState proofTokenState = ProofTokenState.builder().x509Certificate(hokProofCert).build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return SAML2TokenCreationState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .saml2SubjectConfirmation(subjectConfirmation)
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .proofTokenState(proofTokenState)
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } else {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return SAML2TokenCreationState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .saml2SubjectConfirmation(subjectConfirmation)
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith /*
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith Example invocation state:
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith Note: full token, as returned by transform operation, must be included in the invocation. Token details shortened below.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith { "validated_token_state": { "token_type": "OPENIDCONNECT", "oidc_id_token": "eyAidHlwIjogIkpXVCIsICJhbGciOiAiSFMyNTYiIH0.eyAiYXV0...LWE0ZmUtNDQ2YmZhODIzNGEyIiB9.TjhBCB9K64dHoDiBh7I5RWkJ6_y_EEjInuCBiD3F3tc" } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith { "validated_token_state": { "token_type": "SAML2", "saml2_token": "<saml:Assertion xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" ...</saml:AuthnContext></saml:AuthnStatement></saml:Assertion>" } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public boolean isTokenValid(TokenTypeId tokenType, String validatedToken) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith RestSTSTokenValidationInvocationState invocationState;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (TokenType.SAML2.getId().equals(tokenType.getId())) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith invocationState = RestSTSTokenValidationInvocationState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .validatedTokenState(SAML2TokenState.builder().tokenValue(validatedToken).build().toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } else if (TokenType.OPENIDCONNECT.getId().equals(tokenType.getId())) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith invocationState = RestSTSTokenValidationInvocationState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .validatedTokenState(OpenIdConnectTokenState.builder().tokenValue(validatedToken).build().toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } else {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throw new TokenValidationException(ResourceException.BAD_REQUEST, "Invalid integration test invocation: " +
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith "cannot validate token of type: " + tokenType.getId());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith final String response = invokeTokenValidation(invocationState.toJson().toString());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return parseTokenValidationResponse(response);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith /*
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith Example invocation state:
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith Note: full token, as returned by transform operation, must be included in the invocation. Token details shortened below.
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith { "cancelled_token_state": { "token_type": "OPENIDCONNECT", "oidc_id_token": "eyAidHlwIjogIkpXVCIsICJhbGciOiAiSFMyNTYiIH0.eyAiYXV0...LWE0ZmUtNDQ2YmZhODIzNGEyIiB9.TjhBCB9K64dHoDiBh7I5RWkJ6_y_EEjInuCBiD3F3tc" } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith { "cancelled_token_state": { "token_type": "SAML2", "saml2_token": ""<saml:Assertion xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\" ...</saml:AuthnContext></saml:AuthnStatement></saml:Assertion>" } }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith */
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith public void cancelToken(TokenTypeId tokenType, String cancelledToken) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith RestSTSTokenCancellationInvocationState invocationState;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (TokenType.SAML2.getId().equals(tokenType.getId())) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith invocationState = RestSTSTokenCancellationInvocationState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .cancelledTokenState(SAML2TokenState.builder().tokenValue(cancelledToken).build().toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } else if (TokenType.OPENIDCONNECT.getId().equals(tokenType.getId())) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith invocationState = RestSTSTokenCancellationInvocationState.builder()
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .cancelledTokenState(OpenIdConnectTokenState.builder().tokenValue(cancelledToken).build().toJson())
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith .build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } else {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throw new TokenCancellationException(ResourceException.BAD_REQUEST, "Invalid integration test invocation: " +
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith "cannot validate token of type: " + tokenType.getId());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith invokeTokenCancellation(invocationState.toJson().toString());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private OpenIdConnectTokenCreationState buildOpenIdConnectTokenCreationState(String nonce) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return OpenIdConnectTokenCreationState.builder().nonce(nonce).allowAccess(true).build();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String invokeTokenTranslation(String invocationPayload)
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return invokeTokenTranslation(invocationPayload, null, null);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String invokeTokenTranslation(String invocationPayload, String stsClientCertHeaderName, X509Certificate userCertificate)
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith logger.log(Level.FINE, "Invoking token translation with the following payload: " + invocationPayload);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith HttpURLConnection connection = (HttpURLConnection) restSTSInstanceTranslateUrl.openConnection();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setDoOutput(true);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestMethod("POST");
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestProperty(SharedSTSConstants.CONTENT_TYPE, SharedSTSConstants.APPLICATION_JSON);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (stsClientCertHeaderName != null) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith try {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestProperty(stsClientCertHeaderName, Base64.encode(userCertificate.getEncoded()));
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } catch (CertificateEncodingException e) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throw new IOException("Exception encoding user certificate: " + e.getMessage(), e);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith writer.write(invocationPayload);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith writer.close();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith final int responseCode = connection.getResponseCode();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (responseCode == HttpURLConnection.HTTP_OK) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return parseTokenTranslationResponse(getSuccessMessage(connection));
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } else {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throw new TokenCreationException(responseCode, getErrorMessage(connection));
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String invokeTokenValidation(String invocationPayload)
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith logger.log(Level.FINE, "Invoking token validation on url " + restSTSInstanceValidateUrl + " with payload: " + invocationPayload);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith HttpURLConnection connection = (HttpURLConnection) restSTSInstanceValidateUrl.openConnection();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setDoOutput(true);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestMethod("POST");
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestProperty(SharedSTSConstants.CONTENT_TYPE, SharedSTSConstants.APPLICATION_JSON);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith writer.write(invocationPayload);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith writer.close();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith final int responseCode = connection.getResponseCode();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (responseCode == HttpURLConnection.HTTP_OK) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return getSuccessMessage(connection);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } else {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throw new TokenValidationException(responseCode, getErrorMessage(connection));
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String invokeTokenCancellation(String invocationPayload) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith logger.log(Level.FINE, "Invoking token cancellation on url " + restSTSInstanceCancelUrl + " with payload: " + invocationPayload);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith HttpURLConnection connection = (HttpURLConnection) restSTSInstanceCancelUrl.openConnection();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setDoOutput(true);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestMethod("POST");
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith connection.setRequestProperty(SharedSTSConstants.CONTENT_TYPE, SharedSTSConstants.APPLICATION_JSON);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith writer.write(invocationPayload);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith writer.close();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith final int responseCode = connection.getResponseCode();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (responseCode == HttpURLConnection.HTTP_OK) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return getSuccessMessage(connection);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } else {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throw new TokenCancellationException(responseCode, getErrorMessage(connection));
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String getSuccessMessage(HttpURLConnection connection) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return readInputStream(connection.getInputStream());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String getErrorMessage(HttpURLConnection connection) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (connection.getErrorStream() != null) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return readInputStream(connection.getErrorStream());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } else {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return readInputStream(connection.getInputStream());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String readInputStream(InputStream inputStream) throws IOException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (inputStream == null) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return "Empty error stream";
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } else {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return IOUtils.readStream(inputStream);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private String parseTokenTranslationResponse(String response) throws TokenCreationException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith Object responseContent;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith try {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith JsonParser parser =
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith new ObjectMapper().getFactory().createParser(response);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith responseContent = parser.readValueAs(Object.class);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } catch (IOException e) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throw new TokenCreationException(500, "Could not map the response from the rest sts instance at url " + restSTSInstanceTranslateUrl +
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith " to a json object. The response: " + response + "; The exception: " + e);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith JsonValue assertionJson = new JsonValue(responseContent).get(AMSTSConstants.ISSUED_TOKEN);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (assertionJson.isNull() || !assertionJson.isString()) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throw new TokenCreationException(500, "The json response returned from the rest-sts instance at url " + restSTSInstanceTranslateUrl +
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith " did not have a non-null string element for the " + AMSTSConstants.ISSUED_TOKEN + " key. The json: "
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith + responseContent.toString());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return assertionJson.asString();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith private boolean parseTokenValidationResponse(String response) throws TokenValidationException {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith Object responseContent;
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith try {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith JsonParser parser =
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith new ObjectMapper().getFactory().createParser(response);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith responseContent = parser.readValueAs(Object.class);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith } catch (IOException e) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throw new TokenValidationException(ResourceException.INTERNAL_ERROR,
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith "Could not map the response from the rest sts instance at url " + restSTSInstanceValidateUrl +
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith " to a json object. The response: " + response + "; The exception: " + e);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith JsonValue assertionJson = new JsonValue(responseContent).get(AMSTSConstants.TOKEN_VALID);
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith if (assertionJson.isNull() || !assertionJson.isBoolean()) {
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith throw new TokenValidationException(ResourceException.INTERNAL_ERROR,
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith "The json response returned from the rest-sts instance at url " + restSTSInstanceValidateUrl +
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith " did not have a non-null string element for the " + AMSTSConstants.TOKEN_VALID + " key. The json: "
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith + responseContent.toString());
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith return assertionJson.asBoolean();
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith }
c1bef59b02d89a84c23d29663cc4e6d46148ebd2David Goldsmith}