/** * Copyright (c) 2012 - 2018 Data In Motion and others. * All rights reserved. * * This program and the accompanying materials are made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Data In Motion - initial API and implementation */ package org.gecko.util.pac4j.clients; import java.text.ParseException; import org.gecko.util.pac4j.clients.config.BearerTokenClientConfig; import org.osgi.service.cm.ConfigurationException; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.ConfigurationPolicy; import org.osgi.service.component.annotations.Reference; import org.osgi.service.log.Logger; import org.osgi.service.log.LoggerFactory; import org.osgi.service.metatype.annotations.Designate; import org.pac4j.core.client.Client; import org.pac4j.core.client.DirectClient; import org.pac4j.core.context.WebContext; import org.pac4j.core.credentials.extractor.CredentialsExtractor; import org.pac4j.oidc.config.KeycloakOidcConfiguration; import org.pac4j.oidc.credentials.OidcCredentials; import org.pac4j.oidc.profile.OidcProfile; import org.pac4j.oidc.profile.creator.OidcProfileCreator; import com.nimbusds.jose.JWSAlgorithm; import com.nimbusds.jwt.JWTParser; /** * The {@link BearerTokenClient} is an OID Client, that extracts the Bearer Token from the Authorization header. it expects an JWT ID Token here. * The Token itself will be validated internally without asking the OID Authority again. * @author Juergen Albert * @since 10 Sep 2018 */ @Component(service = Client.class, name = "BearerTokenClient", configurationPolicy = ConfigurationPolicy.REQUIRE) @Designate(ocd = BearerTokenClientConfig.class) public class BearerTokenClient extends DirectClient{ @Reference(service = LoggerFactory.class) private Logger logger; @Activate public void activate(BearerTokenClientConfig config) throws ConfigurationException { KeycloakOidcConfiguration bearerconfig = new KeycloakOidcConfiguration(); bearerconfig.setBaseUri(config.oid_baseUri()); bearerconfig.setRealm(config.oid_realm()); bearerconfig.setClientId(config.oid_clientId()); bearerconfig.setSecret(config.oid_secret()); setName(config.oid_clientId()); JWSAlgorithm jwsAlgorithm = JWSAlgorithm.parse(config.oid_jws_algorithm().toString()); bearerconfig.setPreferredJwsAlgorithm(jwsAlgorithm); //set the mandatory stuff setProfileCreator(new OidcProfileCreator(bearerconfig)); setAuthenticator(new OidcBearerAuthenticator(bearerconfig)); setCredentialsExtractor(new CredentialsExtractor() { @Override public OidcCredentials extract(WebContext context) { String authorization = context.getRequestHeader("Authorization"); OidcCredentials oidcCredentials = new OidcCredentials(); if(authorization != null) { authorization = authorization.substring("Bearer ".length()); try { oidcCredentials.setIdToken(JWTParser.parse(authorization)); } catch (ParseException e) { logger.error("Could not parse JWT Token", e); context.setResponseStatus(500); context.setResponseContentType("text/plain"); context.setResponseHeader("Athorization-Error", "Authorization failed. Could not parse JWT Token: " + e.getMessage()); return null; } } else { context.setResponseStatus(401); context.setResponseContentType("text/plain"); context.setResponseHeader("Athorization-Error", "Authorization Header is missing"); return null; } return oidcCredentials; } }); } /* * (non-Javadoc) * @see org.pac4j.core.client.DirectClient#clientInit() */ @Override protected void clientInit() { } }