oidc-library/src/main/java/org/gcube/oidc/rest/OpenIdConnectRESTHelper.java

154 lines
6.8 KiB
Java

package org.gcube.oidc.rest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class OpenIdConnectRESTHelper {
protected static final Logger logger = LoggerFactory.getLogger(OpenIdConnectRESTHelper.class);
public static String buildLoginRequestURL(URL loginURL, String clientId, String state, String redirectURI)
throws UnsupportedEncodingException {
Map<String, List<String>> params = new HashMap<String, List<String>>();
params.put("client_id", Arrays.asList(URLEncoder.encode(clientId, "UTF-8")));
params.put("response_type", Arrays.asList("code"));
params.put("scope", Arrays.asList("openid"));
params.put("state", Arrays.asList(URLEncoder.encode(state, "UTF-8")));
params.put("redirect_uri", Arrays.asList(URLEncoder.encode(redirectURI, "UTF-8")));
params.put("login", Arrays.asList("true"));
String q = mapToQueryString(params);
return loginURL + "?" + q;
}
public static String mapToQueryString(Map<String, List<String>> params) {
String q = params.entrySet().stream().flatMap(p -> p.getValue().stream().map(v -> p.getKey() + "=" + v))
.reduce((p1, p2) -> p1 + "&" + p2).orElse("");
if (logger.isDebugEnabled()) {
logger.debug("Query string is: " + q);
}
return q;
}
public static JWTToken queryClientToken(String clientId, String clientSecret, URL tokenURL) throws Exception {
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")));
return performQueryTokenWithPOST(tokenURL, null, params);
}
public static JWTToken queryToken(String clientId, URL tokenURL, String code, String scope,
String redirectURI) throws Exception {
Map<String, List<String>> params = new HashMap<>();
params.put("client_id", Arrays.asList(URLEncoder.encode(clientId, "UTF-8")));
params.put("grant_type", Arrays.asList("authorization_code"));
params.put("scope", Arrays.asList(URLEncoder.encode(scope, "UTF-8")));
params.put("code", Arrays.asList(URLEncoder.encode(code, "UTF-8")));
params.put("redirect_uri", Arrays.asList(URLEncoder.encode(redirectURI, "UTF-8")));
return performQueryTokenWithPOST(tokenURL, null, params);
}
public static JWTToken performQueryTokenWithPOST(URL tokenURL, String authorization,
Map<String, List<String>> params)
throws Exception {
if (logger.isDebugEnabled()) {
logger.debug("Querying access token from OIDC server with URL: " + tokenURL);
}
HttpURLConnection con = (HttpURLConnection) tokenURL.openConnection();
con.setDoOutput(true);
con.setDoInput(true);
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Method", "POST");
if (authorization != null) {
con.setRequestProperty("Authorization", authorization);
}
OutputStream os = con.getOutputStream();
os.write(mapToQueryString(params).getBytes("UTF-8"));
os.close();
StringBuilder sb = new StringBuilder();
int httpResultCode = con.getResponseCode();
if (logger.isTraceEnabled()) {
logger.trace("HTTP Response code: " + httpResultCode);
}
if (httpResultCode != HttpURLConnection.HTTP_OK) {
BufferedReader br = new BufferedReader(new InputStreamReader(con.getErrorStream(), "UTF-8"));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
throw new Exception("Unable to get token " + sb);
} else {
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + "\n");
}
br.close();
}
return JWTToken.fromString(sb.toString());
}
public static JWTToken queryUMAToken(URL tokenUrl, String authorizationToken, String audience,
List<String> permissions) throws Exception {
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")));
if (permissions != null && !permissions.isEmpty()) {
params.put(
"permission", permissions.stream().map(s -> {
try {
return URLEncoder.encode(s, "UTF-8");
} catch (UnsupportedEncodingException e) {
return "";
}
}).collect(Collectors.toList()));
}
return performQueryTokenWithPOST(tokenUrl, authorizationToken, params);
}
public static void logout(JWTToken token, URL logoutUrl, String clientId) throws IOException {
Map<String, List<String>> params = new HashMap<>();
params.put("client_id", Arrays.asList(URLEncoder.encode(clientId, "UTF-8")));
params.put("refresh_token", Arrays.asList(token.getRefreshTokenString()));
logger.info("Performing logut from OIDC server with URL: " + logoutUrl);
HttpURLConnection con = (HttpURLConnection) logoutUrl.openConnection();
con.setDoOutput(true);
con.setDoInput(true);
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("Method", "POST");
con.setRequestProperty("Authorization", token.getAsBearer());
OutputStream os = con.getOutputStream();
os.write(mapToQueryString(params).getBytes("UTF-8"));
os.close();
int responseCode = con.getResponseCode();
if (responseCode == 204) {
logger.info("Logout performed correctly");
} else {
logger.error("Cannot perfrom logout: [" + responseCode + "] " + con.getResponseMessage());
}
}
}