use of org.dcache.gplazma.oidc.IdentityProvider in project dcache by dCache.
the class QueryUserInfoEndpoint method identityProviders.
private Collection<IdentityProvider> identityProviders(String token) throws AuthenticationException {
if (JsonWebToken.isCompatibleFormat(token)) {
try {
JsonWebToken jwt = new JsonWebToken(token);
Optional<String> iss = jwt.getPayloadString("iss");
if (iss.isPresent()) {
try {
URI issuer = new URI(iss.get());
IdentityProvider ip = providersByIssuer.get(issuer);
checkAuthentication(ip != null, "JWT with unknown \"iss\" claim");
LOG.debug("Discovered token is JWT issued by {}", ip.getName());
return Collections.singleton(ip);
} catch (URISyntaxException e) {
LOG.debug("Bad \"iss\" claim \"{}\": {}", iss.get(), e.toString());
throw new AuthenticationException("Bad \"iss\" claim in JWT");
}
}
} catch (IOException e) {
LOG.debug("Failed to parse JWT: {}", e.toString());
throw new AuthenticationException("Bad JWT");
}
}
return providersByIssuer.values();
}
use of org.dcache.gplazma.oidc.IdentityProvider in project dcache by dCache.
the class QueryUserInfoEndpoint method extract.
@Override
public ExtractResult extract(String token) throws AuthenticationException {
Stopwatch userinfoLookupTiming = Stopwatch.createStarted();
List<LookupResult> allResults;
try {
allResults = userInfoCache.get(token);
} catch (ExecutionException e) {
Throwable cause = e.getCause();
Throwables.throwIfInstanceOf(cause, AuthenticationException.class);
Throwables.throwIfUnchecked(cause);
if (cause instanceof InterruptedException) {
throw new AuthenticationException("Shutting down");
}
throw new RuntimeException("Unexpected exception", e);
}
if (LOG.isDebugEnabled()) {
LOG.debug("Doing user-info lookup against {} OPs took {}", allResults.size(), TimeUtils.describe(userinfoLookupTiming.elapsed()).orElse("no time"));
}
List<LookupResult> successfulResults = allResults.stream().filter(LookupResult::isSuccess).collect(Collectors.toList());
if (successfulResults.isEmpty()) {
if (allResults.size() == 1) {
LookupResult result = allResults.get(0);
throw new AuthenticationException("OpenId Validation failed for " + result.getIdentityProvider().getName() + ": " + result.getError());
} else {
String randomId = randomId();
String errors = allResults.stream().map(r -> "[" + r.getIdentityProvider().getName() + ": " + r.getError() + "]").collect(Collectors.joining(", "));
LOG.warn("OpenId Validation Failure ({}): {}", randomId, errors);
throw new AuthenticationException("OpenId Validation Failed check [log entry #" + randomId + "]");
}
}
if (successfulResults.size() > 1) {
String names = successfulResults.stream().map(LookupResult::getIdentityProvider).map(IdentityProvider::getName).collect(Collectors.joining(", "));
LOG.warn("Multiple OpenID-Connect endpoints accepted access token: {}", names);
throw new AuthenticationException("Multiple OPs accepted token.");
}
var result = successfulResults.get(0);
return new ExtractResult(result.getIdentityProvider(), result.getClaims());
}
use of org.dcache.gplazma.oidc.IdentityProvider in project dcache by dCache.
the class IssuerTest method shouldReturnIdentityProvider.
@Test
public void shouldReturnIdentityProvider() throws Exception {
given(aClient());
given(anIp("EXAMPLE").withEndpoint("https://oidc.example.org/"));
given(anIssuer().withoutHistory());
IdentityProvider ip = issuer.getIdentityProvider();
assertThat(ip, is(sameInstance(identityProvider)));
}
use of org.dcache.gplazma.oidc.IdentityProvider in project dcache by dCache.
the class QueryUserInfoEndpointTest method shouldTargetSingleIpForJwt.
@Test
public void shouldTargetSingleIpForJwt() throws Exception {
given(aClient().onGet("https://oidc.example.org/.well-known/openid-configuration").responds().withEntity("{\"userinfo_endpoint\": \"https://oidc.example.org/oauth\"}").onGet("https://oidc.example.org/oauth").responds().withEntity("{\"sub\": \"ae7fb9688e0683999d864ab5618b92b9\"," + "\"another_claim\": \"another value\"," + "\"null_claim\": null," + "\"number_claim\": 42," + "\"array_claim\": [ \"first\", \"second\"]}").onGet("https://other-oidc.example.com/.well-known/openid-configuration").responds().withEntity("{\"userinfo_endpoint\": \"https://other-oidc.example.com/userinfo\"}").onGet("https://other-oidc.example.com/userinfo").responds().withStatusCode(404).withoutEntity());
given(aQueryUserInfoEndpoint().withIdentityProvider(new IdentityProvider("EXAMPLE-1", URI.create("https://oidc.example.org/"), IGNORE_ALL, client, CACHE_DURATION)).withIdentityProvider(new IdentityProvider("EXAMPLE-2", URI.create("https://other-oidc.example.com/"), IGNORE_ALL, client, CACHE_DURATION)));
given(aJwt().withPayloadClaim("iss", "https://oidc.example.org/"));
var result = processor.extract(jwt);
assertThat(result.claims(), hasEntry("sub", jsonString("ae7fb9688e0683999d864ab5618b92b9")));
assertThat(result.claims(), hasEntry("another_claim", jsonString("another value")));
assertThat(result.claims(), hasEntry("null_claim", jsonNull()));
assertThat(result.claims(), hasEntry("number_claim", jsonNumber(42)));
assertThat(result.claims(), hasEntry("array_claim", jsonStringArray("first", "second")));
}
use of org.dcache.gplazma.oidc.IdentityProvider in project dcache by dCache.
the class QueryUserInfoEndpointTest method shouldRejectTokenIfMultipleIpsReturnInformation.
@Test(expected = AuthenticationException.class)
public void shouldRejectTokenIfMultipleIpsReturnInformation() throws Exception {
given(aClient().onGet("https://oidc.example.org/.well-known/openid-configuration").responds().withEntity("{\"userinfo_endpoint\": \"https://oidc.example.org/oauth\"}").onGet("https://oidc.example.org/oauth").responds().withEntity("{\"sub\": \"ae7fb9688e0683999d864ab5618b92b9\"}").onGet("https://other-oidc.example.com/.well-known/openid-configuration").responds().withEntity("{\"userinfo_endpoint\": \"https://other-oidc.example.com/userinfo\"}").onGet("https://other-oidc.example.com/userinfo").responds().withEntity("{\"sub\": \"another-identity\"}"));
given(aQueryUserInfoEndpoint().withIdentityProvider(new IdentityProvider("EXAMPLE-1", URI.create("https://oidc.example.org/"), IGNORE_ALL, client, CACHE_DURATION)).withIdentityProvider(new IdentityProvider("EXAMPLE-2", URI.create("https://other-oidc.example.com/"), IGNORE_ALL, client, CACHE_DURATION)));
processor.extract("an-access-token");
}
Aggregations