Added parsing of the response if is JSON and added specific exception to handle also this response

This commit is contained in:
Mauro Mugnaini 2020-12-21 18:00:08 +01:00
parent 977dcf4bc6
commit 125f7d91df
3 changed files with 172 additions and 46 deletions

View File

@ -18,6 +18,9 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -25,6 +28,11 @@ public class OpenIdConnectRESTHelper {
protected static final Logger logger = LoggerFactory.getLogger(OpenIdConnectRESTHelper.class);
private static final String RESPONSE_ERROR_KEY = "error";
private static final String RESPONSE_ERROR_INVALID_GRANT = "invalid_grant";
private static final String RESPONSE_ERROR_DESCRIPTION_KEY = "error_description";
private static final String RESPONSE_ERROR_MESSAGE_TINA = "Token is not active";
public static String buildLoginRequestURL(URL loginURL, String clientId, String state, String redirectURI)
throws UnsupportedEncodingException {
@ -47,11 +55,21 @@ public class OpenIdConnectRESTHelper {
return q;
}
public static JWTToken queryClientToken(String clientId, String clientSecret, URL tokenURL) throws Exception {
public static JWTToken queryClientToken(String clientId, String clientSecret, URL tokenURL)
throws OpenIdConnectRESTHelperException {
Map<String, List<String>> params = new HashMap<>();
params.put("grant_type", Arrays.asList("client_credentials"));
params.put("client_id", Arrays.asList(URLEncoder.encode(clientId, "UTF-8")));
params.put("client_secret", Arrays.asList(URLEncoder.encode(clientSecret, "UTF-8")));
try {
params.put("client_id", Arrays.asList(URLEncoder.encode(clientId, "UTF-8")));
} catch (UnsupportedEncodingException e) {
logger.error("Cannot URL encode 'client_id'", e);
}
try {
params.put("client_secret", Arrays.asList(URLEncoder.encode(clientSecret, "UTF-8")));
} catch (UnsupportedEncodingException e) {
logger.error("Cannot URL encode 'client_secret'", e);
}
return performQueryTokenWithPOST(tokenURL, null, params);
}
@ -68,30 +86,45 @@ public class OpenIdConnectRESTHelper {
}
public static JWTToken performQueryTokenWithPOST(URL tokenURL, String authorization,
Map<String, List<String>> params)
throws Exception {
Map<String, List<String>> params) throws OpenIdConnectRESTHelperException {
logger.debug("Querying access token from OIDC server with URL: {}", tokenURL);
HttpURLConnection httpURLConnection = performURLEncodedPOSTSendData(tokenURL, params, authorization);
StringBuilder sb;
try {
HttpURLConnection httpURLConnection = performURLEncodedPOSTSendData(tokenURL, params, authorization);
StringBuilder sb = new StringBuilder();
int httpResultCode = httpURLConnection.getResponseCode();
logger.trace("HTTP Response code: {}", httpResultCode);
if (httpResultCode != HttpURLConnection.HTTP_OK) {
BufferedReader br = new BufferedReader(new InputStreamReader(httpURLConnection.getErrorStream(), "UTF-8"));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
sb = new StringBuilder();
int httpResultCode = httpURLConnection.getResponseCode();
logger.trace("HTTP Response code: {}", httpResultCode);
String responseContentType = httpURLConnection.getContentType();
if (responseContentType != null) {
logger.debug("Response content type is: {}", responseContentType);
} else {
responseContentType = "";
}
br.close();
throw new Exception("Unable to get token " + sb);
} else {
BufferedReader br = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream(), "UTF-8"));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
if (httpResultCode != HttpURLConnection.HTTP_OK) {
BufferedReader br = new BufferedReader(
new InputStreamReader(httpURLConnection.getErrorStream(), "UTF-8"));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
throw OpenIdConnectRESTHelperException.create("Unable to get token", httpResultCode,
responseContentType, sb.toString());
} else {
BufferedReader br = new BufferedReader(
new InputStreamReader(httpURLConnection.getInputStream(), "UTF-8"));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
}
br.close();
} catch (IOException e) {
throw new OpenIdConnectRESTHelperException("Unable to get the token", e);
}
return JWTToken.fromString(sb.toString());
}
@ -119,11 +152,15 @@ public class OpenIdConnectRESTHelper {
}
public static JWTToken queryUMAToken(URL tokenUrl, String authorizationToken, String audience,
List<String> permissions) throws Exception {
List<String> permissions) throws OpenIdConnectRESTHelperException {
Map<String, List<String>> params = new HashMap<>();
params.put("grant_type", Arrays.asList("urn:ietf:params:oauth:grant-type:uma-ticket"));
params.put("audience", Arrays.asList(URLEncoder.encode(audience, "UTF-8")));
try {
params.put("audience", Arrays.asList(URLEncoder.encode(audience, "UTF-8")));
} catch (UnsupportedEncodingException e) {
logger.error("Cannot URL encode 'audience'", e);
}
if (permissions != null && !permissions.isEmpty()) {
params.put(
"permission", permissions.stream().map(s -> {
@ -137,25 +174,34 @@ public class OpenIdConnectRESTHelper {
return performQueryTokenWithPOST(tokenUrl, authorizationToken, params);
}
public static JWTToken refreshToken(URL tokenURL, JWTToken token) throws Exception {
public static JWTToken refreshToken(URL tokenURL, JWTToken token) throws OpenIdConnectRESTHelperException {
return refreshToken(tokenURL, null, null, token);
}
public static JWTToken refreshToken(URL tokenURL, String clientId, JWTToken token) throws Exception {
public static JWTToken refreshToken(URL tokenURL, String clientId, JWTToken token)
throws OpenIdConnectRESTHelperException {
return refreshToken(tokenURL, clientId, null, token);
}
public static JWTToken refreshToken(URL tokenURL, String clientId, String clientSecret, JWTToken token)
throws Exception {
throws OpenIdConnectRESTHelperException {
Map<String, List<String>> params = new HashMap<>();
params.put("grant_type", Arrays.asList("refresh_token"));
if (clientId == null) {
clientId = getClientIdFromToken(token);
}
params.put("client_id", Arrays.asList(URLEncoder.encode(clientId, "UTF-8")));
try {
params.put("client_id", Arrays.asList(URLEncoder.encode(clientId, "UTF-8")));
} catch (UnsupportedEncodingException e) {
logger.error("Cannot URL encode 'client_id'", e);
}
if (clientSecret != null) {
params.put("client_secret", Arrays.asList(URLEncoder.encode(clientSecret, "UTF-8")));
try {
params.put("client_secret", Arrays.asList(URLEncoder.encode(clientSecret, "UTF-8")));
} catch (UnsupportedEncodingException e) {
logger.error("Cannot URL encode 'client_secret'", e);
}
}
params.put("refresh_token", Arrays.asList(token.getRefreshTokenString()));
return performQueryTokenWithPOST(tokenURL, null, params);
@ -226,9 +272,9 @@ public class OpenIdConnectRESTHelper {
conn.setRequestProperty("Authorization", authorization);
}
String contentType = conn.getContentType();
int contentLenght = conn.getContentLength();
int contentLength = conn.getContentLength();
logger.debug("Getting the stream to a %d bytes lenght resource with MIME: %s", contentLenght, contentType);
logger.debug("Getting the stream to a {} bytes lenght resource with MIME: {}", contentLength, contentType);
InputStream is = conn.getInputStream();
buffer = new ByteArrayOutputStream();
@ -247,4 +293,15 @@ public class OpenIdConnectRESTHelper {
}
return null;
}
public static boolean isTokenNotActiveError(String jsonString) {
try {
JSONObject json = (JSONObject) new JSONParser().parse(jsonString);
return RESPONSE_ERROR_INVALID_GRANT.equals(json.get(RESPONSE_ERROR_KEY))
&& RESPONSE_ERROR_MESSAGE_TINA.equals(json.get(RESPONSE_ERROR_DESCRIPTION_KEY));
} catch (ParseException e) {
// Is an unparseable JSON
}
return false;
}
}

View File

@ -0,0 +1,59 @@
package org.gcube.oidc.rest;
public class OpenIdConnectRESTHelperException extends Exception {
private static final long serialVersionUID = -1615745541003534684L;
private int status = -1;
private String contentType = null;
private String responseString = null;
public static OpenIdConnectRESTHelperException create(String message, int status, String contentType,
String textResponse) {
OpenIdConnectRESTHelperException e = new OpenIdConnectRESTHelperException(
"[" + status + "] " + message + " (" + contentType + ") :" + textResponse);
e.setStatus(status);
e.setContentType(contentType);
e.setResponseString(textResponse);
return e;
}
public OpenIdConnectRESTHelperException(String message) {
super(message);
}
public OpenIdConnectRESTHelperException(String message, Exception cause) {
super(message, cause);
}
public void setStatus(int status) {
this.status = status;
}
public int getStatus() {
return status;
}
public void setContentType(String contentType) {
this.contentType = contentType;
}
public String getContentType() {
return contentType;
}
public boolean hasJSONPayload() {
return getContentType().endsWith("json");
}
public void setResponseString(String responseString) {
this.responseString = responseString;
}
public String getResponseString() {
return responseString;
}
}

View File

@ -1,11 +1,8 @@
package org.gcube.oidc.rest;
import static org.junit.Assert.assertNotNull;
import java.net.MalformedURLException;
import java.net.URL;
import org.junit.Test;
public class RestHelperTest {
public RestHelperTest() {
@ -14,24 +11,37 @@ public class RestHelperTest {
/**
* To be re-enabled when the token is took programmatically
*/
// @Test
public void getAvatar() throws Exception {
public void getAvatar() throws MalformedURLException {
String accessTokenBearer = "Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJSSklZNEpoNF9qdDdvNmREY0NlUDFfS1l0akcxVExXVW9oMkQ2Tzk1bFNBIn0.eyJleHAiOjE1OTc0MTc4MzEsImlhdCI6MTU5NzQxNzUzMSwiYXV0aF90aW1lIjoxNTk3NDE3NTI5LCJqdGkiOiI5ZjAwMzM1Yy1jM2NlLTQ3ZTktYTRhZS05MmM4ZDc1NmUyOWMiLCJpc3MiOiJodHRwczovL2FjY291bnRzLmRldi5kNHNjaWVuY2Uub3JnL2F1dGgvcmVhbG1zL2Q0c2NpZW5jZSIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiIzZTcwMzBhNS00M2MzLTRiNjUtYWMwYS0xNTJkYmU3MDI0NTIiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJwcmVwcm9kMi5kNHNjaWVuY2Uub3JnIiwic2Vzc2lvbl9zdGF0ZSI6IjAxOWEzMTVjLTY3MTQtNDQyZi1hNDE2LWM4MjAxNWFhYzFmNSIsImFjciI6IjEiLCJyZWFsbV9hY2Nlc3MiOnsicm9sZXMiOlsib2ZmbGluZV9hY2Nlc3MiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7ImFjY291bnQiOnsicm9sZXMiOlsibWFuYWdlLWFjY291bnQiLCJtYW5hZ2UtYWNjb3VudC1saW5rcyIsInZpZXctcHJvZmlsZSJdfX0sInNjb3BlIjoib3BlbmlkIGVtYWlsIHByb2ZpbGUiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwibmFtZSI6Ik1hdXJvIE11Z25haW5pIiwicHJlZmVycmVkX3VzZXJuYW1lIjoidGhlbWF4eDc2IiwiZ2l2ZW5fbmFtZSI6Ik1hdXJvIiwiZmFtaWx5X25hbWUiOiJNdWduYWluaSIsInBpY3R1cmUiOiJodHRwczovL2xoMy5nb29nbGV1c2VyY29udGVudC5jb20vYS0vQU9oMTRHaUFxUzZRc00xaDNXV1BqMU15VUdlRFA2VnFaQlhtOTZ4cHhZLXNndyIsImVtYWlsIjoidGhlbWF4eDc2QGdtYWlsLmNvbSJ9.WMddlUQujlpmzW07Lrk50vOyWpiT1Tp_RsBWRbzyrQnu5EQQSCq1uGOuSf7Z3VZFv8fbnzWekMZRNzhngEddzOQHgAlsgRdqNI_-ucjmb_8SfR2I5PkYJLTG0jF-Urqi-GvfJtLr2B8dBDnMDO6FLFsg1e5qb-5HkV60eEtY2Wult1PGxlkD05w-K2w513IOMkVIl25ZxKbP61-Iu1qfV_q3QFvUHl_pdqL7uKC5bkl1lqTVeuCwrXrKubHnKc-UzpHtHp8XY0Iao7LdLtON7SODYhU8EkZ860ZlFTSCszmLUpSH4t_shSk9Fiqd8wBKAet5ngmyAPzKx9TT2FK65g";
URL avatarURL = new URL("https://accounts.dev.d4science.org/auth/realms/d4science/avatar-provider/");
byte[] avatarBytes = OpenIdConnectRESTHelper.getUserAvatar(avatarURL, accessTokenBearer);
assertNotNull(avatarBytes);
// assertNotNull(avatarBytes);
}
// @Test
public void getExp() throws Exception {
URL tokenURL = new URL("https://nubis2.int.d4science.net/auth/realms/d4science/protocol/openid-connect/token");
JWTToken token = OpenIdConnectRESTHelper.queryClientToken("lr62_portal", "28726d01-9f24-4ef4-a057-3d208d96aaa0",
tokenURL);
System.out.println(token.getExpAsDate());
System.out.println(token.getAzp());
Thread.sleep((token.getExp() * 1000 - System.currentTimeMillis() + 5000));
System.out.println(token.isExpired());
public void getExp() throws MalformedURLException, OpenIdConnectRESTHelperException, InterruptedException {
URL tokenURL = new URL("https://accounts.dev.d4science.org/auth/realms/d4science/protocol/openid-connect/token");
JWTToken token = OpenIdConnectRESTHelper.queryClientToken("lr62_portal", "28726d01-9f24-4ef4-a057-3d208d96aaa0",
tokenURL);
System.out.println(token.getExpAsDate());
System.out.println(token.getAzp());
Thread.sleep((token.getExp() * 1000 - System.currentTimeMillis() + 5000));
System.out.println(token.isExpired());
}
public static void main(String[] args) throws Exception {
RestHelperTest rht = new RestHelperTest();
// rht.getAvatar();
try {
rht.getExp();
} catch (OpenIdConnectRESTHelperException e) {
if (e.hasJSONPayload()) {
System.out.println("JSON response: " + e.getResponseString());
} else {
System.out.println("Plain text response: " + e.getResponseString());
}
}
}
}