
com.sap.cloud.sdk.cloudplatform.security.RefreshJwtTokenCommand 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.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
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.entity.ContentType;
import org.apache.http.entity.StringEntity;
import com.auth0.jwt.JWT;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.json.JsonSanitizer;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixThreadPoolKey;
import com.netflix.hystrix.HystrixThreadPoolProperties;
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 com.sap.cloud.sdk.frameworks.hystrix.Command;
import com.sap.cloud.sdk.frameworks.hystrix.HystrixUtil;
import lombok.Data;
/**
* This command is used by the CloudFoundry security setup to refresh an expired JWT, given a refresh token. NOTE: This
* is accepted duplicate code to connectivity-scp-cf:TokenRequest.
*/
class RefreshJwtTokenCommand extends Command
{
@Data
private static class CommandSetterBuilder
{
private final Class extends Command>> commandClass;
HystrixCommand.Setter build()
{
final String groupKey = HystrixUtil.getGlobalKey(commandClass);
final String commandKey = "refreshTokenRetrievalCommand";
final HystrixCommandProperties.Setter commandProperties =
HystrixCommandProperties
.Setter()
.withExecutionTimeoutInMilliseconds(6000)
.withCircuitBreakerEnabled(true)
.withCircuitBreakerSleepWindowInMilliseconds(6000)
.withFallbackEnabled(false);
return HystrixCommand.Setter
.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
.andThreadPoolKey(HystrixThreadPoolKey.Factory.asKey(groupKey))
.andCommandKey(HystrixCommandKey.Factory.asKey(commandKey))
.andThreadPoolPropertiesDefaults(
HystrixThreadPoolProperties
.Setter()
.withCoreSize(10)
.withQueueSizeRejectionThreshold(100)
.withMaxQueueSize(100))
.andCommandPropertiesDefaults(commandProperties);
}
}
private final String encodedJwt;
private final String refreshToken;
RefreshJwtTokenCommand( @Nonnull final String encodedJwt, @Nonnull final String refreshToken )
{
super(new CommandSetterBuilder(RefreshTokenRetrievalCommand.class).build());
this.encodedJwt = encodedJwt;
this.refreshToken = refreshToken;
}
@Override
protected String run()
{
// Get the XSUAA credentials from the environment variables
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.");
}
final JsonObject xsuaaServiceCredentials =
((ScpCfCloudPlatform) cloudPlatform).getXsuaaServiceCredentials(JWT.decode(encodedJwt));
final String clientid = xsuaaServiceCredentials.get("clientid").getAsString();
final String xsuaaUrl = xsuaaServiceCredentials.get("url").getAsString();
final String clientSecret = xsuaaServiceCredentials.get("clientsecret").getAsString();
// Assemble the request
final URI uri;
try {
uri = new URI((xsuaaUrl.endsWith("/") ? xsuaaUrl : xsuaaUrl + "/") + "oauth/token");
}
catch( final URISyntaxException e ) {
throw new TokenRequestFailedException(e);
}
final HttpPost tokenRequest = new HttpPost(uri);
tokenRequest.setHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.toString());
tokenRequest.setHeader("Content-Type", ContentType.APPLICATION_FORM_URLENCODED.toString());
try {
tokenRequest.setEntity(
new StringEntity(
"client_id="
+ clientid
+ "&client_secret="
+ clientSecret
+ "&grant_type=refresh_token&token_format=jwt&refresh_token="
+ refreshToken));
}
catch( final UnsupportedEncodingException e ) {
throw new TokenRequestFailedException(e);
}
// Execute request
final HttpResponse response;
try {
response = HttpClientAccessor.getHttpClient().execute(tokenRequest);
}
catch( final IOException e ) {
throw new TokenRequestFailedException(e);
}
final int statusCode = response.getStatusLine().getStatusCode();
if( statusCode >= 400 && statusCode <= 599 ) {
throw new TokenRequestFailedException(
"Refresh JWT request failed with status code "
+ statusCode
+ ": "
+ response.getStatusLine().getReasonPhrase());
}
final String responseBody;
try {
responseBody = HttpEntityUtil.getResponseBody(response);
}
catch( final IOException e ) {
throw new TokenRequestFailedException(e);
}
final JsonObject responseBodyJson =
new JsonParser().parse(JsonSanitizer.sanitize(responseBody)).getAsJsonObject();
@Nullable
final String encodedJwt = responseBodyJson.get("access_token").getAsString();
return encodedJwt;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy