1 package de.dlr.shepard.auth.security;
2
3 import de.dlr.shepard.common.exceptions.ShepardProcessingException;
4 import io.quarkus.logging.Log;
5 import jakarta.enterprise.context.RequestScoped;
6 import jakarta.ws.rs.ProcessingException;
7 import jakarta.ws.rs.WebApplicationException;
8 import jakarta.ws.rs.client.Client;
9 import jakarta.ws.rs.client.ClientBuilder;
10 import jakarta.ws.rs.core.HttpHeaders;
11 import jakarta.ws.rs.core.MediaType;
12 import java.net.URI;
13 import java.net.URISyntaxException;
14 import org.eclipse.microprofile.config.ConfigProvider;
15
16 @RequestScoped
17 public final class UserinfoService {
18
19 private static final String WELL_KNOWN_PATH = ".well-known/openid-configuration";
20
21 private final URI oidcConfigurationURI;
22 private String userinfoEndpoint;
23
24 private final Client client = ClientBuilder.newClient();
25
26 public UserinfoService() {
27 String oidcAuthority = ConfigProvider.getConfig().getValue("oidc.authority", String.class);
28 try {
29 URI base = new URI(oidcAuthority + "/").normalize();
30 oidcConfigurationURI = base.resolve(WELL_KNOWN_PATH);
31 } catch (URISyntaxException e) {
32 throw new ShepardProcessingException(e.getMessage());
33 }
34 }
35
36 protected void init() {
37 var openIdConfiguration = getOpenIdConfiguration();
38 if (openIdConfiguration == null) {
39 throw new ShepardProcessingException("Could not fetch openid configuration");
40 }
41 userinfoEndpoint = openIdConfiguration.getUserinfoEndpoint();
42 }
43
44 public Userinfo fetchUserinfo(String accessToken) {
45 if (userinfoEndpoint == null) {
46 init();
47 }
48
49 var userinfo = getUserinfo(userinfoEndpoint, accessToken);
50 if (userinfo == null) {
51 throw new ShepardProcessingException("Could not fetch userinfo");
52 }
53 return userinfo;
54 }
55
56 private OpenIdConfiguration getOpenIdConfiguration() {
57 var request = client.target(oidcConfigurationURI).request(MediaType.APPLICATION_JSON).buildGet();
58
59 OpenIdConfiguration response;
60 try {
61 response = request.invoke(OpenIdConfiguration.class);
62 } catch (ProcessingException | WebApplicationException e) {
63 Log.errorf("Request was unsuccessful: URI: %s, Error: %s", oidcConfigurationURI.toString(), e.getMessage());
64 return null;
65 }
66 return response;
67 }
68
69 private Userinfo getUserinfo(String uri, String bearer) {
70 var request = client
71 .target(uri)
72 .request(MediaType.APPLICATION_JSON)
73 .header(HttpHeaders.AUTHORIZATION, bearer)
74 .buildGet();
75
76 Userinfo response;
77 try {
78 response = request.invoke(Userinfo.class);
79 } catch (ProcessingException | WebApplicationException e) {
80 Log.errorf("Request was unsuccessful: URI: %s, Error: %s", uri, e.getMessage());
81 return null;
82 }
83 return response;
84 }
85 }