Java tutorial
/** * Copyright (C) 2016 Red Hat, Inc. * <p> * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * <p> * http://www.apache.org/licenses/LICENSE-2.0 * <p> * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.syndesis.core; import java.io.IOException; import java.util.Locale; import java.util.function.UnaryOperator; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.ClientRequestFilter; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; import com.fasterxml.jackson.databind.ObjectMapper; import org.keycloak.KeycloakSecurityContext; import org.keycloak.TokenVerifier; import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken; import org.keycloak.common.VerificationException; import org.keycloak.representations.AccessTokenResponse; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.util.MultiValueMap; import org.springframework.web.util.UriComponentsBuilder; public final class Tokens { public enum TokenProvider implements UnaryOperator<String> { OPENSHIFT { @Override public String apply(String s) { ObjectMapper om = new ObjectMapper(); try { AccessTokenResponse accessToken = om.readValue(s, AccessTokenResponse.class); return accessToken.getToken(); } catch (IOException e) { throw SyndesisServerException.launderThrowable(e); } } }, GITHUB { @Override public String apply(String s) { MultiValueMap<String, String> params = UriComponentsBuilder.fromUriString("").query(s).build() .getQueryParams(); return params.getFirst("access_token"); } } } private static final ThreadLocal<String> OAUTH_TOKEN = new InheritableThreadLocal<>(); private Tokens() { // utility class } public static String getAuthenticationToken() { String stringToken = OAUTH_TOKEN.get(); if (stringToken != null) { return stringToken; } return getKeycloakSecurityContext().getTokenString(); } public static String getUsername() { return getKeycloakSecurityContext().getToken().getPreferredUsername(); } public static KeycloakSecurityContext getKeycloakSecurityContext() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (authentication == null) { throw new IllegalStateException( "Cannot set authorization header because there is no authenticated principal"); } if (!KeycloakAuthenticationToken.class.isAssignableFrom(authentication.getClass())) { throw new IllegalStateException(String.format( "Cannot set authorization header because Authentication is of type %s but %s is required", authentication.getClass(), KeycloakAuthenticationToken.class)); } KeycloakAuthenticationToken token = (KeycloakAuthenticationToken) authentication; return token.getAccount().getKeycloakSecurityContext(); } public static boolean isTokenExpired(String token) { TokenVerifier verifier = TokenVerifier.create(token); try { return verifier.getToken().isExpired(); } catch (VerificationException e) { return true; } } private static String getIssuer(String token) { TokenVerifier verifier = TokenVerifier.create(token); try { return verifier.getToken().getIssuer(); } catch (VerificationException e) { throw SyndesisServerException.launderThrowable(e); } } public static String fetchProviderTokenFromKeycloak(TokenProvider provider) { String keycloakTokenAsString = getAuthenticationToken(); return fetchProviderTokenFromKeycloak(provider, keycloakTokenAsString); } public static String fetchProviderTokenFromKeycloak(TokenProvider provider, String keycloakTokenAsString) { String providerId = provider.toString().toLowerCase(Locale.ENGLISH); String issuer = getIssuer(keycloakTokenAsString); String tokenEndpointUrl = issuer + "/broker/" + providerId + "/token"; final String authHeader = "Bearer " + keycloakTokenAsString; ClientRequestFilter authFilter = (requestContext) -> requestContext.getHeaders() .add(HttpHeaders.AUTHORIZATION, authHeader); Client client = ClientBuilder.newBuilder().register(authFilter).build(); UriBuilder authBase = UriBuilder.fromUri(tokenEndpointUrl); WebTarget tokenEndpoint = client.target(authBase); Response response = tokenEndpoint.request().get(); String responseBody = response.readEntity(String.class); int status = response.getStatus(); if (status != 200) { throw new IllegalStateException(String.format( "Unable to retrieve token for provider %s from URL %s, status code %d, received body: %s", providerId, tokenEndpointUrl, status, responseBody)); } return provider.apply(responseBody); } }