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

com.sap.cloud.sdk.cloudplatform.security.AuthTokenRequest Maven / Gradle / Ivy

/*
 * Copyright (c) 2019 SAP SE or an SAP affiliate company. All rights reserved.
 */

package com.sap.cloud.sdk.cloudplatform.security;

import java.io.IOException;
import java.net.URI;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import org.apache.http.HttpHeaders;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.ContentType;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.json.JsonSanitizer;
import com.sap.cloud.sdk.cloudplatform.CloudPlatform;
import com.sap.cloud.sdk.cloudplatform.CloudPlatformAccessor;
import com.sap.cloud.sdk.cloudplatform.ScpCfCloudPlatform;
import com.sap.cloud.sdk.cloudplatform.connectivity.HttpClientAccessor;
import com.sap.cloud.sdk.cloudplatform.connectivity.HttpEntityUtil;
import com.sap.cloud.sdk.cloudplatform.exception.ShouldNotHappenException;
import com.sap.cloud.sdk.cloudplatform.security.exception.TokenRequestFailedException;

import io.vavr.control.Try;

/**
 * Class encapsulating the request to receive a JWT from an XSUAA service.
 */
class AuthTokenRequest
{
    private final AuthTokenDecoder decoder;

    /**
     * Creates a request with the given decoder.
     *
     * @param decoder
     *            The decoder to decode the JWT from encoded String to decoded {@link AuthToken}. If null a new
     *            {@link AuthTokenDecoder} is used.
     */
    AuthTokenRequest( @Nullable final AuthTokenDecoder decoder )
    {
        this.decoder = decoder == null ? new AuthTokenDecoder() : decoder;
    }

    /**
     * Creates a request with a {@link AuthTokenDecoder} to validate the received JWT.
     */
    AuthTokenRequest()
    {
        this(null);
    }

    /**
     * Retrieves a validated authentication token from the bound XSUAA instance.
     *
     * @return An authentication token from the XSUAA instance.
     *
     * @throws TokenRequestFailedException
     *             If no XSUAA instance was bound or the communication with the service failed.
     */
    @Nonnull
    AuthToken getXsuaaServiceToken()
        throws TokenRequestFailedException
    {
        // get XSUAA credentials from environment variables
        final ScpCfCloudPlatform cloudPlatform = getCloudPlatform();
        final JsonObject xsuaaCredentials = cloudPlatform.getXsuaaServiceCredentials();

        return getXsuaaServiceToken(xsuaaCredentials);
    }

    private AuthToken getXsuaaServiceToken( final JsonObject xsuaaServiceCredentials )
        throws TokenRequestFailedException
    {
        final String accessToken = Try.of(() -> {

            final String clientId = xsuaaServiceCredentials.get("clientid").getAsString();
            final String clientSecret = xsuaaServiceCredentials.get("clientsecret").getAsString();
            final String xsuaaUrl = xsuaaServiceCredentials.get("url").getAsString();

            final BasicCredentials clientCredentials = new BasicCredentials(clientId, clientSecret);

            final URI requestUri = new URI(xsuaaUrl).resolve("/oauth/token?grant_type=client_credentials");

            final HttpUriRequest request = new HttpPost(requestUri);

            request.setHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.toString());
            request.setHeader(
                HttpHeaders.AUTHORIZATION,
                "Basic " + BasicAuthHeaderEncoder.encodeUserPasswordBase64(clientCredentials));

            final HttpResponse response = HttpClientAccessor.getHttpClient().execute(request);

            return extractAccessToken(response);

        }).getOrElseThrow(TokenRequestFailedException::new);

        return decoder.decode(accessToken, null);
    }

    @Nullable
    private String extractAccessToken( final HttpResponse response )
        throws IOException
    {
        final String responseBody = HttpEntityUtil.getResponseBody(response);

        final JsonObject responseBodyJson =
            new JsonParser().parse(JsonSanitizer.sanitize(responseBody)).getAsJsonObject();

        return responseBodyJson.get("access_token").getAsString();
    }

    private ScpCfCloudPlatform getCloudPlatform()
    {
        final CloudPlatform cloudPlatform = CloudPlatformAccessor.getCloudPlatform();

        if( !(cloudPlatform instanceof ScpCfCloudPlatform) ) {
            throw new ShouldNotHappenException(
                "The current Cloud platform is not an instance of "
                    + ScpCfCloudPlatform.class.getSimpleName()
                    + ". Please make sure to specify a dependency to com.sap.cloud.s4hana.cloudplatform:core-scp-cf.");
        }

        return (ScpCfCloudPlatform) cloudPlatform;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy