Skip to content

Commit de137e3

Browse files
authored
JCL-442: Add a quarkus integration module (#776)
1 parent 6896671 commit de137e3

File tree

7 files changed

+305
-0
lines changed

7 files changed

+305
-0
lines changed

bom/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@
7878
<artifactId>inrupt-client-parser</artifactId>
7979
<version>${project.version}</version>
8080
</dependency>
81+
<dependency>
82+
<groupId>com.inrupt.client</groupId>
83+
<artifactId>inrupt-client-quarkus</artifactId>
84+
<version>${project.version}</version>
85+
</dependency>
8186
<dependency>
8287
<groupId>com.inrupt.client</groupId>
8388
<artifactId>inrupt-client-rdf4j</artifactId>

pom.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
<jose4j.version>0.9.3</jose4j.version>
3434
<json.bind.version>3.0.0</json.bind.version>
3535
<okhttp.version>4.12.0</okhttp.version>
36+
<quarkus.version>3.5.0</quarkus.version>
3637
<slf4j.version>2.0.9</slf4j.version>
3738
<spring.security.version>6.1.5</spring.security.version>
3839
<inrupt.commons.rdf4j.version>0.6.0</inrupt.commons.rdf4j.version>
@@ -105,6 +106,7 @@
105106
<module>okhttp</module>
106107
<module>openid</module>
107108
<module>parser</module>
109+
<module>quarkus</module>
108110
<module>rdf4j</module>
109111
<module>rdf-legacy</module>
110112
<module>solid</module>

quarkus/pom.xml

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
<?xml version="1.0"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
3+
<modelVersion>4.0.0</modelVersion>
4+
<parent>
5+
<groupId>com.inrupt.client</groupId>
6+
<artifactId>inrupt-client</artifactId>
7+
<version>1.1.0-SNAPSHOT</version>
8+
</parent>
9+
10+
<artifactId>inrupt-client-quarkus</artifactId>
11+
<name>Inrupt Java Client Libraries - Quarkus integration</name>
12+
<description>
13+
Integration utilities for Quarkus support.
14+
</description>
15+
16+
<properties>
17+
<maven.compiler.target>11</maven.compiler.target>
18+
<maven.compiler.source>11</maven.compiler.source>
19+
</properties>
20+
21+
<dependencyManagement>
22+
<dependencies>
23+
<dependency>
24+
<groupId>io.quarkus</groupId>
25+
<artifactId>quarkus-bom</artifactId>
26+
<version>${quarkus.version}</version>
27+
<type>pom</type>
28+
<scope>import</scope>
29+
</dependency>
30+
</dependencies>
31+
</dependencyManagement>
32+
33+
<dependencies>
34+
<dependency>
35+
<groupId>com.inrupt.client</groupId>
36+
<artifactId>inrupt-client-api</artifactId>
37+
<version>${project.version}</version>
38+
</dependency>
39+
<dependency>
40+
<groupId>com.inrupt.client</groupId>
41+
<artifactId>inrupt-client-openid</artifactId>
42+
<version>${project.version}</version>
43+
</dependency>
44+
<dependency>
45+
<groupId>org.eclipse.microprofile.jwt</groupId>
46+
<artifactId>microprofile-jwt-auth-api</artifactId>
47+
<scope>provided</scope>
48+
</dependency>
49+
50+
<!-- test dependencies -->
51+
<dependency>
52+
<groupId>com.inrupt.client</groupId>
53+
<artifactId>inrupt-client-core</artifactId>
54+
<version>${project.version}</version>
55+
<scope>test</scope>
56+
</dependency>
57+
<dependency>
58+
<groupId>org.junit.jupiter</groupId>
59+
<artifactId>junit-jupiter-engine</artifactId>
60+
<version>${junit.version}</version>
61+
<scope>test</scope>
62+
</dependency>
63+
<dependency>
64+
<groupId>org.junit.jupiter</groupId>
65+
<artifactId>junit-jupiter-api</artifactId>
66+
<version>${junit.version}</version>
67+
<scope>test</scope>
68+
</dependency>
69+
<dependency>
70+
<groupId>org.slf4j</groupId>
71+
<artifactId>slf4j-simple</artifactId>
72+
<version>${slf4j.version}</version>
73+
<scope>test</scope>
74+
</dependency>
75+
<dependency>
76+
<groupId>io.smallrye</groupId>
77+
<artifactId>smallrye-jwt-build</artifactId>
78+
<scope>test</scope>
79+
</dependency>
80+
<dependency>
81+
<groupId>io.smallrye</groupId>
82+
<artifactId>smallrye-jwt</artifactId>
83+
<scope>test</scope>
84+
</dependency>
85+
<dependency>
86+
<groupId>io.smallrye.config</groupId>
87+
<artifactId>smallrye-config</artifactId>
88+
<scope>test</scope>
89+
</dependency>
90+
<dependency>
91+
<groupId>org.glassfish</groupId>
92+
<artifactId>jakarta.json</artifactId>
93+
<version>${glassfish.json.version}</version>
94+
<scope>test</scope>
95+
</dependency>
96+
</dependencies>
97+
98+
<build>
99+
<plugins>
100+
<plugin>
101+
<groupId>org.apache.maven.plugins</groupId>
102+
<artifactId>maven-surefire-plugin</artifactId>
103+
<configuration>
104+
<systemPropertyVariables />
105+
</configuration>
106+
</plugin>
107+
<plugin>
108+
<groupId>org.apache.maven.plugins</groupId>
109+
<artifactId>maven-failsafe-plugin</artifactId>
110+
<configuration>
111+
<systemPropertyVariables />
112+
</configuration>
113+
</plugin>
114+
<plugin>
115+
<groupId>org.jacoco</groupId>
116+
<artifactId>jacoco-maven-plugin</artifactId>
117+
</plugin>
118+
</plugins>
119+
</build>
120+
</project>
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright Inrupt Inc.
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal in
6+
* the Software without restriction, including without limitation the rights to use,
7+
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
8+
* Software, and to permit persons to whom the Software is furnished to do so,
9+
* subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16+
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
18+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20+
*/
21+
package com.inrupt.client.quarkus;
22+
23+
import com.inrupt.client.auth.Session;
24+
import com.inrupt.client.openid.OpenIdSession;
25+
26+
import java.util.Optional;
27+
import java.util.function.Function;
28+
29+
import org.eclipse.microprofile.jwt.JsonWebToken;
30+
31+
public final class SessionUtils {
32+
33+
/**
34+
* Convert a Quarkus (Microprofile) {@link JsonWebToken} to a {@link Session} object.
35+
*
36+
* <p>This method uses the {@link OpenIdSession} library to create a Session
37+
*
38+
* @param jwt a JSON Web Token object
39+
* @return the session, if present and unexpired
40+
*/
41+
public static Optional<Session> asSession(final JsonWebToken jwt) {
42+
return asSession(jwt, OpenIdSession::ofIdToken);
43+
}
44+
45+
/**
46+
* Convert a Quarkus (Microprofile) {@link JsonWebToken} to a {@link Session} object.
47+
*
48+
* @param jwt a JSON Web Token object
49+
* @param mapping a mapping function for creating a Session from an ID token
50+
* @return the session, if present and unexpired
51+
*/
52+
public static Optional<Session> asSession(final JsonWebToken jwt, final Function<String, Session> mapping) {
53+
return Optional.ofNullable(mapping.apply(jwt.getRawToken()));
54+
}
55+
56+
private SessionUtils() {
57+
// Prevent instantiation
58+
}
59+
}
60+
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
/*
2+
* Copyright Inrupt Inc.
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal in
6+
* the Software without restriction, including without limitation the rights to use,
7+
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
8+
* Software, and to permit persons to whom the Software is furnished to do so,
9+
* subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
15+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16+
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
17+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
18+
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
19+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20+
*/
21+
package com.inrupt.client.quarkus;
22+
23+
import static org.junit.jupiter.api.Assertions.*;
24+
25+
import com.inrupt.client.auth.Session;
26+
import com.inrupt.client.openid.OpenIdSession;
27+
28+
import io.smallrye.jwt.algorithm.SignatureAlgorithm;
29+
import io.smallrye.jwt.auth.principal.DefaultJWTParser;
30+
import io.smallrye.jwt.auth.principal.JWTAuthContextInfo;
31+
import io.smallrye.jwt.auth.principal.ParseException;
32+
import io.smallrye.jwt.build.Jwt;
33+
import io.smallrye.jwt.util.ResourceUtils;
34+
35+
import java.io.IOException;
36+
import java.net.URI;
37+
import java.time.Instant;
38+
import java.util.Optional;
39+
40+
import org.eclipse.microprofile.jwt.JsonWebToken;
41+
import org.jose4j.jwk.PublicJsonWebKey;
42+
import org.jose4j.lang.JoseException;
43+
import org.jose4j.lang.UncheckedJoseException;
44+
import org.junit.jupiter.api.Test;
45+
46+
class SessionUtilsTest {
47+
48+
static final String WEBID = "https://example.com/user";
49+
static final String ISSUER = "https://issuer.example";
50+
51+
@Test
52+
void testSession() {
53+
final var token = generateIdToken("user", ISSUER, WEBID);
54+
final var session = SessionUtils.asSession(token, OpenIdSession::ofIdToken);
55+
assertTrue(session.isPresent());
56+
session.ifPresent(s ->
57+
assertEquals(Optional.of(URI.create(WEBID)), s.getPrincipal()));
58+
}
59+
60+
@Test
61+
void testAnonymousSession() {
62+
final var token = generateIdToken("user", ISSUER, WEBID);
63+
final var session = SessionUtils.asSession(token, t -> Session.anonymous());
64+
assertTrue(session.isPresent());
65+
session.ifPresent(s ->
66+
assertEquals(Optional.empty(), s.getPrincipal()));
67+
}
68+
69+
@Test
70+
void testSessionNoMapper() {
71+
final var token = generateIdToken("user", ISSUER, WEBID);
72+
final var session = SessionUtils.asSession(token);
73+
assertTrue(session.isPresent());
74+
session.ifPresent(s ->
75+
assertEquals(Optional.of(URI.create(WEBID)), s.getPrincipal()));
76+
}
77+
78+
static JsonWebToken generateIdToken(final String sub, final String issuer, final String webid) {
79+
try {
80+
final var jwk = PublicJsonWebKey.Factory
81+
.newPublicJwk(ResourceUtils.readResource("testKey.json"));
82+
83+
final var authContext = new JWTAuthContextInfo(jwk.getPublicKey(), issuer);
84+
authContext.setSignatureAlgorithm(SignatureAlgorithm.ES256);
85+
final var parser = new DefaultJWTParser(authContext);
86+
87+
final var token = Jwt.claims()
88+
.subject(sub)
89+
.issuer(issuer)
90+
.claim("webid", webid)
91+
.expiresAt(Instant.now().plusSeconds(100))
92+
.audience("solid").jws()
93+
.keyId("76GJ30ywXmKAxKdhJ1yPLA").sign(jwk.getPrivateKey());
94+
return parser.parse(token);
95+
} catch (final IOException | JoseException ex) {
96+
throw new UncheckedJoseException("Could not build token", ex);
97+
} catch (final ParseException ex) {
98+
throw new IllegalArgumentException("Could not parse JWT", ex);
99+
}
100+
}
101+
}
102+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"kty":"EC",
3+
"kid":"76GJ30ywXmKAxKdhJ1yPLA",
4+
"use":"sig",
5+
"alg":"ES256",
6+
"x":"X-VSZcAATvp9oLrBWZTdLkuyjU-PpKIt24hIhbG4z5M",
7+
"y":"SIORCeKh4thRYsRxllDLNYssQscPCGNQZn62Isgmx08",
8+
"crv":"P-256",
9+
"d":"oflFwpOqy7u3H28LQSaRdvFJH_obvYsBA4udeq3hemM"
10+
}
11+

reports/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@
7272
<artifactId>inrupt-client-httpclient</artifactId>
7373
<version>${project.version}</version>
7474
</dependency>
75+
<dependency>
76+
<groupId>com.inrupt.client</groupId>
77+
<artifactId>inrupt-client-quarkus</artifactId>
78+
<version>${project.version}</version>
79+
</dependency>
7580
<dependency>
7681
<groupId>com.inrupt.client</groupId>
7782
<artifactId>inrupt-client-rdf4j</artifactId>

0 commit comments

Comments
 (0)