UserinfoService.java

package de.dlr.shepard.auth.security;

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 org.eclipse.microprofile.config.ConfigProvider;

@RequestScoped
public final 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;
  }
}