001 002package io.vrap.rmf.base.client.oauth2; 003 004import static io.vrap.rmf.base.client.ApiHttpHeaders.headerEntry; 005 006import java.net.URI; 007import java.nio.charset.StandardCharsets; 008import java.util.Base64; 009import java.util.concurrent.CompletableFuture; 010import java.util.concurrent.CompletionException; 011 012import io.vrap.rmf.base.client.*; 013import io.vrap.rmf.base.client.utils.Utils; 014import io.vrap.rmf.base.client.utils.json.JsonUtils; 015 016public class RefreshFlowTokenSupplier extends BaseAuthTokenSupplier implements RefreshableTokenSupplier { 017 private final TokenStorage tokenStorage; 018 019 public RefreshFlowTokenSupplier(final String clientId, final String clientSecret, final String tokenEndpoint, 020 final TokenStorage tokenStorage, final VrapHttpClient vrapHttpClient) { 021 super(vrapHttpClient, constructApiHttpRequest(clientId, clientSecret, tokenEndpoint)); 022 this.tokenStorage = tokenStorage; 023 } 024 025 @Override 026 public CompletableFuture<AuthenticationToken> refreshToken() { 027 final AuthenticationToken token = tokenStorage.getToken(); 028 if (token.getRefreshToken() == null) { 029 throw new AuthException(400, "No refresh_token given", null); 030 } 031 final String body = String.format("grant_type=refresh_token&refresh_token=%s", 032 urlEncode(token.getRefreshToken())); 033 final ApiHttpRequest request = apiHttpRequest.withBody(body); 034 logger.debug(() -> request); 035 return vrapHttpClient.execute(request).whenComplete((response, throwable) -> { 036 logger.info(() -> String.format("%s %s %s", apiHttpRequest.getMethod().name(), apiHttpRequest.getUri(), 037 response.getStatusCode())); 038 if (throwable != null) { 039 logger.error(() -> response, throwable); 040 } 041 else { 042 logger.debug(() -> response); 043 } 044 }).thenApply(apiHttpResponse -> { 045 if (apiHttpResponse.getStatusCode() < 200 || apiHttpResponse.getStatusCode() > 299) { 046 throw new CompletionException(new Throwable(new String(apiHttpResponse.getBody()))); 047 } 048 return apiHttpResponse; 049 }) 050 .thenApply(Utils.wrapToCompletionException((ApiHttpResponse<byte[]> response) -> JsonUtils 051 .fromJsonByteArray(response.getBody(), AuthenticationToken.class))); 052 } 053 054 @Override 055 public CompletableFuture<AuthenticationToken> getToken() { 056 return refreshToken(); 057 } 058 059 private static ApiHttpRequest constructApiHttpRequest(final String clientId, final String clientSecret, 060 final String tokenEndpoint) { 061 String auth = Base64.getEncoder() 062 .encodeToString((clientId + ":" + clientSecret).getBytes(StandardCharsets.UTF_8)); 063 final ApiHttpHeaders apiHttpHeaders = new ApiHttpHeaders( 064 headerEntry(ApiHttpHeaders.AUTHORIZATION, String.format("Basic %s", auth)), 065 headerEntry(ApiHttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded")); 066 return new ApiHttpRequest(ApiHttpMethod.POST, URI.create(tokenEndpoint), apiHttpHeaders, null); 067 } 068}