Skip to content
This repository has been archived by the owner on Oct 22, 2024. It is now read-only.

Commit

Permalink
feat: add token reset and throw exception
Browse files Browse the repository at this point in the history
(cherry picked from commit 469b2b7)
  • Loading branch information
1nb0und committed Jan 5, 2024
1 parent b50ea33 commit afef742
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ public interface Authentication {
Authentication build();

Map.Entry<String, String> getTokenHeader(Product product);

void resetToken(Product product);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.camunda.common.auth;

import io.camunda.common.exception.SdkException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -14,12 +15,19 @@ public class DefaultNoopAuthentication implements Authentication {

private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

private final String errorMessage = "Unable to determine authentication. Please check your configuration";

@Override
public Authentication build() {
LOG.error("Unable to determine authentication. Please check your configuration");
LOG.error(errorMessage);
return this;
}

@Override
public void resetToken(Product product) {
throw new SdkException(errorMessage);
}

@Override
public Map.Entry<String, String> getTokenHeader(Product product) {
throw new UnsupportedOperationException("Unable to determine authentication");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ public Authentication build() {
return this;
}

@Override
public void resetToken(Product product) {
JwtCredential jwtCredential = jwtConfig.getProduct(product);
retrieveToken(product, jwtCredential);
}

private String retrieveToken(Product product, JwtCredential jwtCredential) {
try {
HttpPost httpPost = new HttpPost(jwtCredential.getAuthUrl());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package io.camunda.common.auth;

import io.camunda.common.exception.SdkException;
import io.camunda.common.json.JsonMapper;
import io.camunda.common.json.SdkObjectMapper;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.slf4j.Logger;
Expand All @@ -14,7 +16,6 @@
import java.lang.invoke.MethodHandles;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Map;
Expand Down Expand Up @@ -74,6 +75,12 @@ public Authentication build() {
return this;
}

@Override
public void resetToken(Product product) {
JwtCredential jwtCredential = jwtConfig.getProduct(product);
retrieveToken(product, jwtCredential);
}

private String retrieveToken(Product product, JwtCredential jwtCredential) {
try {
HttpPost httpPost = new HttpPost(authUrl);
Expand All @@ -98,11 +105,16 @@ private String retrieveToken(Product product, JwtCredential jwtCredential) {
httpPost.setEntity(new StringEntity(form));
CloseableHttpClient client = HttpClient.getInstance();
CloseableHttpResponse response = client.execute(httpPost);
TokenResponse tokenResponse = jsonMapper.fromJson(EntityUtils.toString(response.getEntity()), TokenResponse.class);
TokenResponse tokenResponse;
if (response.getCode() == HttpStatus.SC_OK) {
tokenResponse = jsonMapper.fromJson(EntityUtils.toString(response.getEntity()), TokenResponse.class);
} else {
throw new SdkException("Error "+response.getCode()+" obtaining access token: "+EntityUtils.toString(response.getEntity()));
}
tokens.put(product, tokenResponse.getAccessToken());
} catch (Exception e) {
LOG.error("Authenticating for " + product + " failed due to " + e);
throw new RuntimeException("Unable to authenticate", e);
throw new SdkException("Unable to authenticate", e);
}
return tokens.get(product);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ public SimpleAuthentication() {
@Override
public Authentication build() {
authUrl = simpleUrl+"/api/login";
//simpleConfig.getMap().forEach(this::retrieveToken);
return this;
}

Expand Down Expand Up @@ -89,4 +88,10 @@ public Map.Entry<String, String> getTokenHeader(Product product) {

return new AbstractMap.SimpleEntry<>("Cookie", token);
}

@Override
public void resetToken(Product product) {
SimpleCredential simpleCredential = simpleConfig.getProduct(product);
retrieveToken(product, simpleCredential);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.google.common.reflect.TypeToken;
import io.camunda.common.auth.Authentication;
import io.camunda.common.auth.Product;
import io.camunda.common.exception.SdkException;
import io.camunda.common.json.JsonMapper;
import io.camunda.common.json.SdkObjectMapper;
import org.apache.hc.client5.http.classic.methods.HttpDelete;
Expand All @@ -12,11 +13,13 @@
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.Header;
import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.io.entity.StringEntity;
import org.apache.hc.core5.http.message.BasicHeader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
Expand Down Expand Up @@ -73,13 +76,13 @@ public <T> T get(Class<T> responseType, String id) {
String url = host + basePath + retrievePath(responseType) + "/" + id;
HttpGet httpGet = new HttpGet(url);
httpGet.addHeader(retrieveToken(responseType));
T resp = null;
T resp;
try {
CloseableHttpResponse response = httpClient.execute(httpGet);
String tmp = new String(Java8Utils.readAllBytes(response.getEntity().getContent()), StandardCharsets.UTF_8);
resp = jsonMapper.fromJson(tmp, responseType);
resp = parseAndRetry(response, responseType);
} catch (Exception e) {
LOG.error("Failed GET with responseType {}, id {} due to {}", responseType, id, e.getMessage());
throw new SdkException(e);
}
return resp;
}
Expand All @@ -99,13 +102,13 @@ private <T, V, W> T get(Class<T> responseType, Class<V> parameterType, TypeToke
String url = host + basePath + resourcePath;
HttpGet httpGet = new HttpGet(url);
httpGet.addHeader(retrieveToken(selector.getClass()));
T resp = null;
T resp;
try {
CloseableHttpResponse response = httpClient.execute(httpGet);
String tmp = new String(Java8Utils.readAllBytes(response.getEntity().getContent()), StandardCharsets.UTF_8);
resp = jsonMapper.fromJson(tmp, responseType, parameterType);
resp = parseAndRetry(response, responseType, parameterType, selector);
} catch (Exception e) {
LOG.error("Failed GET with responseType {}, parameterType {}, selector {}, id {} due to {}", responseType, parameterType, selector, id, e.getMessage());
throw new SdkException(e);
}
return resp;
}
Expand All @@ -116,12 +119,13 @@ public <T> String getXml(Class<T> selector, Long key) {
String url = host + basePath + retrievePath(selector) + "/" + key + "/xml";
HttpGet httpGet = new HttpGet(url);
httpGet.addHeader(retrieveToken(selector));
String xml = null;
String xml;
try {
CloseableHttpResponse response = httpClient.execute(httpGet);
xml = new String(Java8Utils.readAllBytes(response.getEntity().getContent()), StandardCharsets.UTF_8);
xml = (String) parseAndRetry(response, selector);
} catch (Exception e) {
LOG.error("Failed GET with selector {}, key {} due to {}", selector, key, e.getMessage());
throw new SdkException(e);
}
return xml;
}
Expand All @@ -132,15 +136,15 @@ public <T, V, W, U> T post(Class<T> responseType, Class<V> parameterType, TypeTo
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader("Content-Type", "application/json");
httpPost.addHeader(retrieveToken(selector.getClass()));
T resp = null;
T resp;
try {
String data = jsonMapper.toJson(body);
httpPost.setEntity(new StringEntity(data));
CloseableHttpResponse response = httpClient.execute(httpPost);
String tmp = new String(Java8Utils.readAllBytes(response.getEntity().getContent()), StandardCharsets.UTF_8);
resp = jsonMapper.fromJson(tmp, responseType, parameterType);
resp = parseAndRetry(response, responseType, parameterType, selector);
} catch (Exception e) {
LOG.error("Failed POST with responseType {}, parameterType {}, selector {}, body {} due to {}", responseType, parameterType, selector, body, e.getMessage());
throw new SdkException(e);
}
return resp;
}
Expand All @@ -154,10 +158,10 @@ public <T, V> T delete(Class<T> responseType, Class<V> selector, Long key) {
T resp = null;
try {
CloseableHttpResponse response = httpClient.execute(httpDelete);
String tmp = new String(Java8Utils.readAllBytes(response.getEntity().getContent()), StandardCharsets.UTF_8);
resp = jsonMapper.fromJson(tmp, responseType);
resp = parseAndRetry(response, responseType, selector);
} catch (Exception e) {
LOG.error("Failed DELETE with responseType {}, selector {}, key {}, due to {}", responseType, selector, key, e.getMessage());
throw new SdkException(e);
}
return resp;
}
Expand All @@ -182,4 +186,59 @@ private <T> Header retrieveToken(Class<T> clazz) {
Map.Entry<String, String> header = authentication.getTokenHeader(currentProduct.get());
return new BasicHeader(header.getKey(), header.getValue());
}

private <T> Product getProduct(Class<T> clazz) {
AtomicReference<Product> currentProduct = new AtomicReference<>();
productMap.forEach((product, map) -> {
if (map.containsKey(clazz)) {
currentProduct.set(product);
}
});
return currentProduct.get();
}

// TODO: Refactor duplicate code parseAndRetry()

private <T> T parseAndRetry(CloseableHttpResponse response, Class<T> responseType) throws IOException {
T resp;
if (200 <= response.getCode() && response.getCode() <= 299) {
String tmp = new String(Java8Utils.readAllBytes(response.getEntity().getContent()), StandardCharsets.UTF_8);
resp = jsonMapper.fromJson(tmp, responseType);
} else {
if(response.getCode() == HttpStatus.SC_UNAUTHORIZED || response.getCode() == HttpStatus.SC_FORBIDDEN) {
authentication.resetToken(getProduct(responseType.getClass()));
// TODO: Add capability to auto retry the existing request
}
throw new SdkException("Response not successful: " + response.getCode());
}
return resp;
}

private <T, V> T parseAndRetry(CloseableHttpResponse response, Class<T> responseType, Class<V> selector) throws IOException {
T resp;
if (200 <= response.getCode() && response.getCode() <= 299) {
String tmp = new String(Java8Utils.readAllBytes(response.getEntity().getContent()), StandardCharsets.UTF_8);
resp = jsonMapper.fromJson(tmp, responseType);
} else {
if(response.getCode() == HttpStatus.SC_UNAUTHORIZED || response.getCode() == HttpStatus.SC_FORBIDDEN) {
authentication.resetToken(getProduct(selector.getClass()));
}
throw new SdkException("Response not successful: " + response.getCode());
}
return resp;
}

private <T, V, W> T parseAndRetry(CloseableHttpResponse response, Class<T> responseType, Class<V> parameterType, TypeToken<W> selector) throws IOException {
T resp;
if (200 <= response.getCode() && response.getCode() <= 299) {
String tmp = new String(Java8Utils.readAllBytes(response.getEntity().getContent()), StandardCharsets.UTF_8);
resp = jsonMapper.fromJson(tmp, responseType, parameterType);
} else {
if(response.getCode() == HttpStatus.SC_UNAUTHORIZED || response.getCode() == HttpStatus.SC_FORBIDDEN) {
authentication.resetToken(getProduct(selector.getClass()));
}
throw new SdkException("Response not successful: " + response.getCode());
}
return resp;
}
}

0 comments on commit afef742

Please sign in to comment.