Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add OIDC authentication Integration Tests #40262

Merged
merged 17 commits into from
Mar 30, 2019
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion x-pack/plugin/security/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ dependencies {
compile "com.nimbusds:oauth2-oidc-sdk:6.5"
compile "com.nimbusds:nimbus-jose-jwt:4.41.2"
compile "com.nimbusds:lang-tag:1.4.4"
compile "com.sun.mail:javax.mail:1.6.2"
compile 'com.sun.mail:jakarta.mail:1.6.3'
compile "net.jcip:jcip-annotations:1.0"
compile "net.minidev:json-smart:2.3"
compile "net.minidev:accessors-smart:1.2"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
787e007e377223bba85a33599d3da416c135f99b
1 change: 0 additions & 1 deletion x-pack/plugin/security/licenses/javax.mail-1.6.2.jar.sha1

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ protected void doExecute(Task task, OpenIdConnectAuthenticateRequest request,
.get(OpenIdConnectRealm.CONTEXT_TOKEN_DATA);
tokenService.createUserToken(authentication, originatingAuthentication,
ActionListener.wrap(tuple -> {
final String tokenString = tokenService.getUserTokenString(tuple.v1());
final String tokenString = tokenService.getAccessTokenAsString(tuple.v1());
final TimeValue expiresIn = tokenService.getExpirationDelay();
listener.onResponse(new OpenIdConnectAuthenticateResponse(authentication.getUser().principal(), tokenString,
tuple.v2(), expiresIn));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ public OpenIdConnectAuthenticator(RealmConfig realmConfig, OpenIdConnectProvider
this.rpConfig = rpConfig;
this.sslService = sslService;
this.httpClient = createHttpClient();
this.idTokenValidator.set(createIdTokenValidator());
this.watcherService = watcherService;
this.idTokenValidator.set(createIdTokenValidator());
}

// For testing
Expand Down Expand Up @@ -285,12 +285,15 @@ private void validateAccessToken(AccessToken accessToken, JWT idToken) {
accessToken.getType());
}
String atHashValue = idToken.getJWTClaimsSet().getStringClaim("at_hash");
if (null == atHashValue && optional == false) {
throw new ElasticsearchSecurityException("Failed to verify access token. at_hash claim is missing from the ID Token");
if (Strings.hasText(atHashValue) == false) {
if (optional == false) {
throw new ElasticsearchSecurityException("Failed to verify access token.ID Token doesn't contain at_hash claim ");
}
} else {
AccessTokenHash atHash = new AccessTokenHash(atHashValue);
JWSAlgorithm jwsAlgorithm = JWSAlgorithm.parse(idToken.getHeader().getAlgorithm().getName());
AccessTokenValidator.validate(accessToken, jwsAlgorithm, atHash);
}
AccessTokenHash atHash = new AccessTokenHash(atHashValue);
JWSAlgorithm jwsAlgorithm = JWSAlgorithm.parse(idToken.getHeader().getAlgorithm().getName());
AccessTokenValidator.validate(accessToken, jwsAlgorithm, atHash);
} else if (rpConfig.getResponseType().equals(ResponseType.parse("id_token")) && accessToken != null) {
// This should NOT happen and indicates a misconfigured OP. Warn the user but do not fail
LOGGER.warn("Access Token incorrectly returned from the OpenId Connect Provider while using \"id_token\" response type.");
Expand Down Expand Up @@ -324,7 +327,6 @@ private void validateResponseType(AuthenticationSuccessResponse response) {
if (rpConfig.getResponseType().equals(response.impliedResponseType()) == false) {
throw new ElasticsearchSecurityException("Unexpected response type [{}], while [{}] is configured",
response.impliedResponseType(), rpConfig.getResponseType());

}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ public void testLogoutInvalidatesTokens() throws Exception {
tokenService.createUserToken(authentication, authentication, future, tokenMetadata, true);
final UserToken userToken = future.actionGet().v1();
mockGetTokenFromId(userToken, false, client);
final String tokenString = tokenService.getUserTokenString(userToken);
final String tokenString = tokenService.getAccessTokenAsString(userToken);

final OpenIdConnectLogoutRequest request = new OpenIdConnectLogoutRequest();
request.setToken(tokenString);
Expand Down
74 changes: 74 additions & 0 deletions x-pack/qa/oidc-op-tests/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
Project idpFixtureProject = xpackProject("test:idp-fixture")
evaluationDependsOn(idpFixtureProject.path)

apply plugin: 'elasticsearch.standalone-rest-test'
apply plugin: 'elasticsearch.rest-test'
apply plugin: 'elasticsearch.test.fixtures'

dependencies {
// "org.elasticsearch.plugin:x-pack-core:${version}" doesn't work with idea because the testArtifacts are also here
testCompile project(path: xpackModule('core'), configuration: 'default')
testCompile project(path: xpackModule('core'), configuration: 'testArtifacts')
testCompile project(path: xpackModule('security'), configuration: 'testArtifacts')
}
testFixtures.useFixture ":x-pack:test:idp-fixture"

integTestCluster {
setting 'xpack.license.self_generated.type', 'trial'
setting 'xpack.security.enabled', 'true'
setting 'xpack.security.http.ssl.enabled', 'false'
setting 'xpack.security.authc.token.enabled', 'true'
setting 'xpack.security.authc.realms.file.file.order', '0'
setting 'xpack.security.authc.realms.native.native.order', '1'
// OpenID Connect Realm 1 configured for authorization grant flow
setting 'xpack.security.authc.realms.oidc.c2id.order', '2'
setting 'xpack.security.authc.realms.oidc.c2id.op.name', 'c2id-op'
setting 'xpack.security.authc.realms.oidc.c2id.op.issuer', 'http://localhost:8080'
setting 'xpack.security.authc.realms.oidc.c2id.op.authorization_endpoint', 'http://127.0.0.1:8080/c2id-login'
setting 'xpack.security.authc.realms.oidc.c2id.op.token_endpoint', 'http://127.0.0.1:8080/c2id/token'
setting 'xpack.security.authc.realms.oidc.c2id.op.userinfo_endpoint', 'http://127.0.0.1:8080/c2id/userinfo'
setting 'xpack.security.authc.realms.oidc.c2id.op.jwkset_path', 'op-jwks.json'
setting 'xpack.security.authc.realms.oidc.c2id.rp.redirect_uri', 'https://my.fantastic.rp/cb'
setting 'xpack.security.authc.realms.oidc.c2id.rp.client_id', 'elasticsearch-rp'
keystoreSetting 'xpack.security.authc.realms.oidc.c2id.rp.client_secret', 'b07efb7a1cf6ec9462afe7b6d3ab55c6c7880262aa61ac28dded292aca47c9a2'
setting 'xpack.security.authc.realms.oidc.c2id.rp.response_type', 'code'
setting 'xpack.security.authc.realms.oidc.c2id.claims.principal', 'sub'
setting 'xpack.security.authc.realms.oidc.c2id.claims.name', 'name'
setting 'xpack.security.authc.realms.oidc.c2id.claims.mail', 'email'
// OpenID Connect Realm 2 configured for implicit flow
setting 'xpack.security.authc.realms.oidc.c2id-implicit.order', '3'
setting 'xpack.security.authc.realms.oidc.c2id-implicit.op.name', 'c2id-implicit'
setting 'xpack.security.authc.realms.oidc.c2id-implicit.op.issuer', 'http://localhost:8080'
setting 'xpack.security.authc.realms.oidc.c2id-implicit.op.authorization_endpoint', 'http://127.0.0.1:8080/c2id-login'
setting 'xpack.security.authc.realms.oidc.c2id-implicit.op.token_endpoint', 'http://127.0.0.1:8080/c2id/token'
setting 'xpack.security.authc.realms.oidc.c2id-implicit.op.userinfo_endpoint', 'http://127.0.0.1:8080/c2id/userinfo'
setting 'xpack.security.authc.realms.oidc.c2id-implicit.op.jwkset_path', 'op-jwks.json'
setting 'xpack.security.authc.realms.oidc.c2id-implicit.rp.redirect_uri', 'https://my.fantastic.rp/cb'
setting 'xpack.security.authc.realms.oidc.c2id-implicit.rp.client_id', 'elasticsearch-rp'
keystoreSetting 'xpack.security.authc.realms.oidc.c2id-implicit.rp.client_secret', 'b07efb7a1cf6ec9462afe7b6d3ab55c6c7880262aa61ac28dded292aca47c9a2'
setting 'xpack.security.authc.realms.oidc.c2id-implicit.rp.response_type', 'id_token token'
setting 'xpack.security.authc.realms.oidc.c2id-implicit.claims.principal', 'sub'
setting 'xpack.security.authc.realms.oidc.c2id-implicit.claims.name', 'name'
setting 'xpack.security.authc.realms.oidc.c2id-implicit.claims.mail', 'email'
// Allow for troubleshooting CI errors
setting 'logger.org.elasticsearch.xpack.security.authc', 'TRACE'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you expecting this to fail in CI? I'd much rather leave this out because who knows what this could hide; maybe it slows things down enough that we miss a concurrency bug

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you expecting this to fail in CI?

No :) , the idea was to have logs available for when it will - inevitably - fail . I see your point though, will remove this

setting 'xpack.ml.enabled', 'false'

extraConfigFile 'op-jwks.json', idpFixtureProject.file("oidc/op-jwks.json")

setupCommand 'setupTestAdmin',
'bin/elasticsearch-users', 'useradd', "test_admin", '-p', 'x-pack-test-password', '-r', "superuser"

waitCondition = { node, ant ->
File tmpFile = new File(node.cwd, 'wait.success')
ant.get(src: "http://${node.httpUri()}/_cluster/health?wait_for_nodes=>=${numNodes}&wait_for_status=yellow",
dest: tmpFile.toString(),
username: 'test_admin',
password: 'x-pack-test-password',
ignoreerrors: true,
retries: 10)
return tmpFile.exists()
}
}

thirdPartyAudit.enabled = false
Loading