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

io.sphere.sdk.client.TokensSupplierImpl Maven / Gradle / Ivy

There is a newer version: 1.0.0-M26
Show newest version
package io.sphere.sdk.client;

import com.fasterxml.jackson.databind.JsonNode;
import io.sphere.sdk.http.*;
import io.sphere.sdk.json.JsonException;
import io.sphere.sdk.json.SphereJsonUtils;
import io.sphere.sdk.meta.BuildInfo;
import io.sphere.sdk.models.SphereException;
import io.sphere.sdk.utils.MapUtils;

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Optional;
import java.util.concurrent.CompletionStage;

import static io.sphere.sdk.client.SphereAuth.AUTH_LOGGER;
import static io.sphere.sdk.http.HttpMethod.POST;
import static java.lang.String.format;

/**
 * Component that can fetch SPHERE.IO access tokens.
 * Does not refresh them,
 */
final class TokensSupplierImpl extends AutoCloseableService implements TokensSupplier {

    private final SphereAuthConfig config;
    private final HttpClient httpClient;
    private final boolean closeHttpClient;
    private boolean isClosed = false;

    private TokensSupplierImpl(final SphereAuthConfig config, final HttpClient httpClient, final boolean closeHttpClient) {
        this.config = config;
        this.httpClient = httpClient;
        this.closeHttpClient = closeHttpClient;
    }

    static TokensSupplier of(final SphereAuthConfig config, final HttpClient httpClient, final boolean closeHttpClient) {
        return new TokensSupplierImpl(config, httpClient, closeHttpClient);
    }

    /**
     * Executes a http auth sphere request and fetches a new access token.
     * @return future of a token
     */
    @Override
    public CompletionStage get() {
        AUTH_LOGGER.debug(() -> "Fetching new token.");
        final HttpRequest httpRequest = newRequest();
        final CompletionStage httpResponseStage = httpClient.execute(httpRequest);
        final CompletionStage result = httpResponseStage.thenApply((response) -> parseResponse(response, httpRequest));
        result.whenCompleteAsync(this::logTokenResult);
        return result;
    }

    private void logTokenResult(final Tokens nullableTokens, final Throwable nullableThrowable) {
        if (nullableTokens != null) {
            AUTH_LOGGER.debug(() -> "Successfully fetched token that expires in " + Optional.ofNullable(nullableTokens.getExpiresIn()).map(x -> x.toString()).orElse("an unknown time") + ".");
        } else {
            AUTH_LOGGER.error(() -> "Failed to fetch token.", nullableThrowable);
        }
    }

    @Override
    protected synchronized void internalClose() {
        if (!isClosed) {
            if (closeHttpClient) {
                closeQuietly(httpClient);
            }
            isClosed = true;
        }
    }

    private HttpRequest newRequest() {
        final String usernamePassword = format("%s:%s", config.getClientId(), config.getClientSecret());
        final String encodedString = Base64.getEncoder().encodeToString(usernamePassword.getBytes(StandardCharsets.UTF_8));
        final HttpHeaders httpHeaders = HttpHeaders
                .of(HttpHeaders.AUTHORIZATION, "Basic " + encodedString)
                .plus(HttpHeaders.USER_AGENT, BuildInfo.userAgent())
                .plus(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
        final FormUrlEncodedHttpRequestBody body = FormUrlEncodedHttpRequestBody.of(MapUtils.mapOf("grant_type", "client_credentials", "scope", format("manage_project:%s", config.getProjectKey())));
        return HttpRequest.of(POST, config.getAuthUrl() + "/oauth/token", httpHeaders, body);
    }

    /** Parses Tokens from a response from the backend authorization service.
     * @param httpResponse Response from the authorization service.
     * @param httpRequest the request which belongs to the response
     */
    private Tokens parseResponse(final HttpResponse httpResponse, final HttpRequest httpRequest) {
        try {
            if (httpResponse.getStatusCode() == 401 && httpResponse.getResponseBody() != null) {
                ClientErrorException exception = new UnauthorizedException(httpResponse.toString());
                try {
                    final JsonNode jsonNode = SphereJsonUtils.parse(httpResponse.getResponseBody());
                    final String error = jsonNode.get("error").asText();
                    if (error.equals("invalid_client")) {
                        exception = new InvalidClientCredentialsException(config);
                    }
                } catch (final JsonException e) {
                    exception = new UnauthorizedException(httpResponse.toString(), e);
                }
                throw exception;
            }
            return SphereJsonUtils.readObject(httpResponse.getResponseBody(), Tokens.typeReference());
        } catch (final SphereException exception) {
            exception.setProjectKey(config.getProjectKey());
            exception.setUnderlyingHttpResponse(httpResponse);
            exception.setHttpRequest(httpRequest);
            throw exception;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy