Skip to content

Commit 01e58ea

Browse files
committed
feat: add user / default scopes
1 parent 78cd310 commit 01e58ea

6 files changed

Lines changed: 68 additions & 14 deletions

File tree

src/it/java/io/weaviate/integration/OIDCSupportITest.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,13 @@
1616
/**
1717
* Test that the client can use one of the supported authorization flows to
1818
* obtain a token from the OIDC provider and use it in a request to Weaviate.
19+
*
20+
* Running this test suite successfully requires talking to external services,
21+
* so tests will be skipped if the don't have internet. See
22+
* {@link #hasInternetConnection}.
1923
*/
2024
public class OIDCSupportITest extends ConcurrentTest {
21-
private static final String WCS_DUMMY_CI_USER = "oidc-test-user@weaviate.io";
25+
private static final String WCS_DUMMY_CI_USERNAME = "oidc-test-user@weaviate.io";
2226
private static final String WCS_DUMMY_CI_PW = System.getenv("WCS_DUMMY_CI_PW");
2327

2428
/**
@@ -51,7 +55,7 @@ public void test_resourceOwnerPassword() throws IOException {
5155
Assume.assumeTrue("WCS_DUMMY_CI_PW is not set", WCS_DUMMY_CI_PW != null);
5256
Assume.assumeTrue("no internet connection", hasInternetConnection());
5357

54-
var authz = Authorization.resourceOwnerPassword(WCS_DUMMY_CI_USER, WCS_DUMMY_CI_PW, List.of("test_scope"));
58+
var authz = Authorization.resourceOwnerPassword(WCS_DUMMY_CI_USERNAME, WCS_DUMMY_CI_PW, List.of());
5559
pingWeaviate(wcsContainer, authz);
5660
}
5761

@@ -60,7 +64,7 @@ public void test_clientCredentials() throws IOException {
6064
Assume.assumeTrue("OKTA_CLIENT_SECRET is not set", OKTA_CLIENT_SECRET != null);
6165
Assume.assumeTrue("no internet connection", hasInternetConnection());
6266

63-
var authz = Authorization.clientCredentials(OKTA_CLIENT_ID, OKTA_CLIENT_SECRET, List.of("test_scope"));
67+
var authz = Authorization.clientCredentials(OKTA_CLIENT_ID, OKTA_CLIENT_SECRET, List.of());
6468
pingWeaviate(oktaContainer, authz);
6569
}
6670

src/main/java/io/weaviate/client6/v1/api/Authorization.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public static Authorization bearerToken(String accessToken, String refreshToken,
5151
*/
5252
public static Authorization resourceOwnerPassword(String username, String password, List<String> scopes) {
5353
return transport -> {
54-
OidcConfig oidc = OidcUtils.getConfig(transport);
54+
OidcConfig oidc = OidcUtils.getConfig(transport).withScopes(scopes).withScopes("offline_access");
5555
return TokenProvider.resourceOwnerPassword(oidc, username, password);
5656
};
5757
}
@@ -69,7 +69,10 @@ public static Authorization resourceOwnerPassword(String username, String passwo
6969
*/
7070
public static Authorization clientCredentials(String clientId, String clientSecret, List<String> scopes) {
7171
return transport -> {
72-
OidcConfig oidc = OidcUtils.getConfig(transport);
72+
OidcConfig oidc = OidcUtils.getConfig(transport).withScopes(scopes);
73+
if (oidc.scopes().isEmpty() && TokenProvider.isMicrosoft(oidc)) {
74+
oidc = oidc.withScopes(clientId + "/.default");
75+
}
7376
return TokenProvider.clientCredentials(oidc, clientId, clientSecret);
7477
};
7578
}

src/main/java/io/weaviate/client6/v1/internal/TokenProvider.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.weaviate.client6.v1.internal;
22

3+
import java.net.URI;
34
import java.time.Instant;
45

56
import io.weaviate.client6.v1.api.WeaviateOAuthException;
@@ -131,4 +132,21 @@ static TokenProvider exchange(OidcConfig oidc, TokenProvider tp) {
131132
static TokenProvider reuse(Token t, TokenProvider tp) {
132133
return ReuseTokenProvider.wrap(t, tp);
133134
}
135+
136+
public record ProviderMetadata(URI tokenEndpoint) {
137+
}
138+
139+
/**
140+
* Returns true if this OIDC provider's token endpoint is hosted at
141+
* {@code login.microsoftonline.com}.
142+
*
143+
* @param oidc OIDC config.
144+
*
145+
* @throws WeaviateOAuthException if metadata could not be parsed.
146+
*/
147+
public static boolean isMicrosoft(OidcConfig oidc) {
148+
var metadata = NimbusTokenProvider.parseProviderMetadata(oidc.providerMetadata());
149+
return metadata.tokenEndpoint().getHost().contains("login.microsoftonline.com");
150+
}
151+
134152
}
Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,36 @@
11
package io.weaviate.client6.v1.internal.oidc;
22

3+
import java.util.Arrays;
34
import java.util.Collections;
5+
import java.util.HashSet;
46
import java.util.List;
7+
import java.util.Set;
8+
import java.util.stream.Collectors;
9+
import java.util.stream.Stream;
510

611
public record OidcConfig(
712
String clientId,
813
String providerMetadata,
9-
List<String> scopes) {
14+
Set<String> scopes) {
1015

11-
public OidcConfig(String clientId, String providerMetadata, List<String> scopes) {
16+
public OidcConfig(String clientId, String providerMetadata, Set<String> scopes) {
1217
this.clientId = clientId;
1318
this.providerMetadata = providerMetadata;
14-
this.scopes = scopes != null ? scopes : Collections.emptyList();
19+
this.scopes = scopes != null ? Set.copyOf(scopes) : Collections.emptySet();
20+
}
21+
22+
public OidcConfig(String clientId, String providerMetadata, List<String> scopes) {
23+
this(clientId, providerMetadata, scopes == null ? null : new HashSet<>(scopes));
24+
}
25+
26+
/** Create a new OIDC config with extended scopes. */
27+
public OidcConfig withScopes(String... scopes) {
28+
return withScopes(Arrays.asList(scopes));
29+
}
30+
31+
/** Create a new OIDC config with extended scopes. */
32+
public OidcConfig withScopes(List<String> scopes) {
33+
var newScopes = Stream.concat(this.scopes.stream(), scopes.stream()).collect(Collectors.toSet());
34+
return new OidcConfig(clientId, providerMetadata, newScopes);
1535
}
1636
}

src/main/java/io/weaviate/client6/v1/internal/oidc/OidcUtils.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public static final OidcConfig getConfig(RestTransport transport) {
5353
} catch (IOException e) {
5454
throw new WeaviateOAuthException("fetch provider metadata", e);
5555
}
56+
5657
return new OidcConfig(openid.clientId(), providerMetadata, openid.scopes());
5758
}
5859
}

src/main/java/io/weaviate/client6/v1/internal/oidc/nimbus/NimbusTokenProvider.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,7 @@ public static NimbusTokenProvider clientCredentials(OidcConfig oidc, String clie
7070
}
7171

7272
private NimbusTokenProvider(OidcConfig oidc, Flow flow) {
73-
try {
74-
this.metadata = OIDCProviderMetadata.parse(oidc.providerMetadata());
75-
} catch (ParseException ex) {
76-
throw new WeaviateOAuthException("parse provider metadata: ", ex);
77-
}
78-
73+
this.metadata = _parseProviderMetadata(oidc.providerMetadata());
7974
this.clientId = new ClientID(oidc.clientId());
8075
this.scope = new Scope(oidc.scopes().toArray(String[]::new));
8176
this.flow = flow;
@@ -114,6 +109,19 @@ public Token getToken() {
114109
return newToken;
115110
}
116111

112+
public static ProviderMetadata parseProviderMetadata(String providerMetadata) {
113+
var metadata = _parseProviderMetadata(providerMetadata);
114+
return new ProviderMetadata(metadata.getTokenEndpointURI());
115+
}
116+
117+
private static OIDCProviderMetadata _parseProviderMetadata(String providerMetadata) {
118+
try {
119+
return OIDCProviderMetadata.parse(providerMetadata);
120+
} catch (ParseException ex) {
121+
throw new WeaviateOAuthException("parse provider metadata: ", ex);
122+
}
123+
}
124+
117125
@NotThreadSafe
118126
final class BearerTokenFlow implements Flow {
119127
private Token t;

0 commit comments

Comments
 (0)