UserinfoService.java
package de.dlr.shepard.auth.security;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import de.dlr.shepard.common.exceptions.ShepardProcessingException;
import io.quarkus.logging.Log;
import jakarta.enterprise.context.RequestScoped;
import jakarta.ws.rs.ProcessingException;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
import java.net.URI;
import java.net.URISyntaxException;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.eclipse.microprofile.config.ConfigProvider;
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
class OpenIdConfiguration {
private String issuer;
@JsonProperty("authorization_endpoint")
private String authorizationEndpoint;
@JsonProperty("userinfo_endpoint")
private String userinfoEndpoint;
@JsonProperty("jwks_uri")
private String jwksUri;
@JsonProperty("response_types_supported")
private String[] responseTypesSupported;
@JsonProperty("subject_types_supported")
private String[] subjectTypesSupported;
@JsonProperty("id_token_signing_alg_values_supported")
private String[] idTokenSigningAlgValuesSupported;
}
@RequestScoped
public class UserinfoService {
private static final String WELL_KNOWN_PATH = ".well-known/openid-configuration";
private final URI oidcConfigurationURI;
private String userinfoEndpoint;
private final Client client = ClientBuilder.newClient();
public UserinfoService() {
String oidcAuthority = ConfigProvider.getConfig().getValue("oidc.authority", String.class);
try {
URI base = new URI(oidcAuthority + "/").normalize();
oidcConfigurationURI = base.resolve(WELL_KNOWN_PATH);
} catch (URISyntaxException e) {
throw new ShepardProcessingException(e.getMessage());
}
}
protected void init() {
var openIdConfiguration = getOpenIdConfiguration();
if (openIdConfiguration == null) {
throw new ShepardProcessingException("Could not fetch openid configuration");
}
userinfoEndpoint = openIdConfiguration.getUserinfoEndpoint();
}
public Userinfo fetchUserinfo(String accessToken) {
if (userinfoEndpoint == null) {
init();
}
var userinfo = getUserinfo(userinfoEndpoint, accessToken);
if (userinfo == null) {
throw new ShepardProcessingException("Could not fetch userinfo");
}
return userinfo;
}
private OpenIdConfiguration getOpenIdConfiguration() {
var request = client.target(oidcConfigurationURI).request(MediaType.APPLICATION_JSON).buildGet();
OpenIdConfiguration response;
try {
response = request.invoke(OpenIdConfiguration.class);
} catch (ProcessingException | WebApplicationException e) {
Log.errorf("Request was unsuccessful: URI: %s, Error: %s", oidcConfigurationURI.toString(), e.getMessage());
return null;
}
return response;
}
private Userinfo getUserinfo(String uri, String bearer) {
var request = client
.target(uri)
.request(MediaType.APPLICATION_JSON)
.header(HttpHeaders.AUTHORIZATION, bearer)
.buildGet();
Userinfo response;
try {
response = request.invoke(Userinfo.class);
} catch (ProcessingException | WebApplicationException e) {
Log.errorf("Request was unsuccessful: URI: %s, Error: %s", uri, e.getMessage());
return null;
}
return response;
}
}