Skip to content

Commit

Permalink
OIDC UserInfo Endpoint
Browse files Browse the repository at this point in the history
Signed-off-by: Stephen Crawford <[email protected]>
  • Loading branch information
stephen-crawford committed Aug 21, 2024
1 parent ef0d471 commit 67e2619
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;

import static com.amazon.dlic.auth.http.jwt.keybyoidc.OpenIdConstants.APPLICATION_JSON;
import static org.apache.hc.core5.http.ContentType.APPLICATION_JSON;
import static org.apache.hc.core5.http.HttpHeaders.AUTHORIZATION;
import static com.amazon.dlic.auth.http.jwt.keybyoidc.OpenIdConstants.APPLICATION_JWT;
import static com.amazon.dlic.auth.http.jwt.keybyoidc.OpenIdConstants.AUTHORIZATION_HEADER;
import static com.amazon.dlic.auth.http.jwt.keybyoidc.OpenIdConstants.CLIENT_ID;
import static com.amazon.dlic.auth.http.jwt.keybyoidc.OpenIdConstants.ISSUER_ID_URL;
import static com.amazon.dlic.auth.http.jwt.keybyoidc.OpenIdConstants.SUB_CLAIM;
Expand All @@ -60,14 +60,14 @@ public class HTTPOpenIdAuthenticator implements HTTPAuthenticator {
private final Path configPath;
private final int requestTimeoutMs = 10000;
private final SettingsBasedSSLConfigurator.SSLConfig sslConfig;
private final String userinfo_endpoint;
private final String userInfoEndpoint;
private volatile HTTPJwtKeyByOpenIdConnectAuthenticator openIdJwtAuthenticator;

public HTTPOpenIdAuthenticator(Settings settings, Path configPath) throws Exception {
this.settings = settings;
this.configPath = configPath;
this.sslConfig = getSSLConfig(settings, configPath);
userinfo_endpoint = settings.get("userinfo_endpoint");
userInfoEndpoint = settings.get("userinfo_endpoint");
openIdJwtAuthenticator = new HTTPJwtKeyByOpenIdConnectAuthenticator(settings, configPath);
}

Expand All @@ -83,7 +83,7 @@ public HTTPJwtKeyByOpenIdConnectAuthenticator getOpenIdJwtAuthenticator() {
}

public String getType() {
return null;
return "oidc";
}

private static SettingsBasedSSLConfigurator.SSLConfig getSSLConfig(Settings settings, Path configPath) throws Exception {
Expand All @@ -92,7 +92,7 @@ private static SettingsBasedSSLConfigurator.SSLConfig getSSLConfig(Settings sett

@Override
public AuthCredentials extractCredentials(SecurityRequest request, ThreadContext context) throws OpenSearchSecurityException {
if (this.userinfo_endpoint != null && !this.userinfo_endpoint.isBlank()) {
if (this.userInfoEndpoint != null && !this.userInfoEndpoint.isBlank()) {
return extractCredentials0(request, context);
}
return (this.openIdJwtAuthenticator.extractCredentials(request, context));
Expand Down Expand Up @@ -141,37 +141,35 @@ public AuthCredentials extractCredentials0(SecurityRequest request, ThreadContex

try (CloseableHttpClient httpClient = createHttpClient()) {

HttpGet httpGet = new HttpGet(this.userinfo_endpoint);
HttpGet httpGet = new HttpGet(this.userInfoEndpoint);

RequestConfig requestConfig = RequestConfig.custom()
.setConnectionRequestTimeout(requestTimeoutMs, TimeUnit.MILLISECONDS)
.setConnectTimeout(requestTimeoutMs, TimeUnit.MILLISECONDS)
.build();

httpGet.setConfig(requestConfig);
httpGet.addHeader(AUTHORIZATION_HEADER, request.getHeaders().get(AUTHORIZATION_HEADER));
httpGet.addHeader(AUTHORIZATION, request.getHeaders().get(AUTHORIZATION));

// HTTPGet should internally verify the appropriate TLS cert.
try (CloseableHttpResponse response = httpClient.execute(httpGet)) {

if (response.getCode() < 200 || response.getCode() >= 300) {
throw new AuthenticatorUnavailableException(
"Error while getting " + this.userinfo_endpoint + ": " + response.getReasonPhrase()
"Error while getting " + this.userInfoEndpoint + ": " + response.getReasonPhrase()
);
}

HttpEntity httpEntity = response.getEntity();

if (httpEntity == null) {
throw new AuthenticatorUnavailableException(
"Error while getting " + this.userinfo_endpoint + ": Empty response entity"
);
throw new AuthenticatorUnavailableException("Error while getting " + this.userInfoEndpoint + ": Empty response entity");
}

String contentType = httpEntity.getContentType();
if (!contentType.contains(APPLICATION_JSON) && !contentType.contains(APPLICATION_JWT)) {
if (!contentType.contains(APPLICATION_JSON.getMimeType()) && !contentType.contains(APPLICATION_JWT)) {
throw new AuthenticatorUnavailableException(
"Error while getting " + this.userinfo_endpoint + ": Invalid content type in response"
"Error while getting " + this.userInfoEndpoint + ": Invalid content type in response"
);
}

Expand All @@ -191,7 +189,7 @@ public AuthCredentials extractCredentials0(SecurityRequest request, ThreadContex
userinfoContent = content.toString();
} catch (IOException e) {
throw new AuthenticatorUnavailableException(
"Error while getting " + this.userinfo_endpoint + ": Unable to read response content"
"Error while getting " + this.userInfoEndpoint + ": Unable to read response content"
);
}

Expand All @@ -208,7 +206,7 @@ public AuthCredentials extractCredentials0(SecurityRequest request, ThreadContex
String missing = validateResponseClaims(claims, id, isSigned);
if (!missing.isBlank()) {
throw new AuthenticatorUnavailableException(
"Error while getting " + this.userinfo_endpoint + ": Missing or invalid required claims in response: " + missing
"Error while getting " + this.userInfoEndpoint + ": Missing or invalid required claims in response: " + missing
);
}

Expand All @@ -231,7 +229,7 @@ public AuthCredentials extractCredentials0(SecurityRequest request, ThreadContex
throw new RuntimeException(e);
}
} catch (IOException e) {
throw new AuthenticatorUnavailableException("Error while getting " + this.userinfo_endpoint + ": " + e, e);
throw new AuthenticatorUnavailableException("Error while getting " + this.userInfoEndpoint + ": " + e, e);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@

public class OpenIdConstants {

public static final String APPLICATION_JSON = "application/json";
public static final String APPLICATION_JWT = "application/jwt";
public static final String AUTHORIZATION_HEADER = "Authorization";
public static final String CLIENT_ID = "client_id";
public static final String ISSUER_ID_URL = "issuer_id_url";
public static final String SUB_CLAIM = "sub";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ public void userinfoEndpointReturnsJwtWithAllRequirementsTest() throws Exception

@Test
public void userinfoEndpointReturnsJwtWithRequiredAudIssFailsTest() throws Exception { // Setting a required issuer or audience
// alongside userinfoendpoint settings causes
// alongside userinfo endpoint settings causes
// failures in signed response cases
Settings settings = Settings.builder()
.put("openid_connect_url", mockIdpServer.getDiscoverUri())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jwt.JWTClaimsSet;

import static com.amazon.dlic.auth.http.jwt.keybyoidc.OpenIdConstants.APPLICATION_JSON;
import static org.apache.hc.core5.http.ContentType.APPLICATION_JSON;
import static com.amazon.dlic.auth.http.jwt.keybyoidc.OpenIdConstants.APPLICATION_JWT;
import static com.amazon.dlic.auth.http.jwt.keybyoidc.TestJwts.MCCOY_SUBJECT;
import static com.amazon.dlic.auth.http.jwt.keybyoidc.TestJwts.TEST_ROLES_STRING;
Expand Down

0 comments on commit 67e2619

Please sign in to comment.