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

Include authentication type for the authenticate response #61247

Merged
merged 4 commits into from
Aug 21, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,13 @@ public final class AuthenticateResponse {
static final ParseField LOOKUP_REALM = new ParseField("lookup_realm");
static final ParseField REALM_NAME = new ParseField("name");
static final ParseField REALM_TYPE = new ParseField("type");
static final ParseField AUTHENTICATION_TYPE = new ParseField("authentication_type");

@SuppressWarnings("unchecked")
private static final ConstructingObjectParser<AuthenticateResponse, Void> PARSER = new ConstructingObjectParser<>(
"client_security_authenticate_response", true,
a -> new AuthenticateResponse(new User((String) a[0], ((List<String>) a[1]), (Map<String, Object>) a[2],
(String) a[3], (String) a[4]), (Boolean) a[5], (RealmInfo) a[6], (RealmInfo) a[7]));
(String) a[3], (String) a[4]), (Boolean) a[5], (RealmInfo) a[6], (RealmInfo) a[7], (String) a[8]));
static {
final ConstructingObjectParser<RealmInfo, Void> realmInfoParser = new ConstructingObjectParser<>("realm_info", true,
a -> new RealmInfo((String) a[0], (String) a[1]));
Expand All @@ -69,20 +70,23 @@ public final class AuthenticateResponse {
PARSER.declareBoolean(constructorArg(), ENABLED);
PARSER.declareObject(constructorArg(), realmInfoParser, AUTHENTICATION_REALM);
PARSER.declareObject(constructorArg(), realmInfoParser, LOOKUP_REALM);
PARSER.declareString(constructorArg(), AUTHENTICATION_TYPE);
}

private final User user;
private final boolean enabled;
private final RealmInfo authenticationRealm;
private final RealmInfo lookupRealm;
private final String authenticationType;


public AuthenticateResponse(User user, boolean enabled, RealmInfo authenticationRealm,
RealmInfo lookupRealm) {
RealmInfo lookupRealm, String authenticationType) {
this.user = user;
this.enabled = enabled;
this.authenticationRealm = authenticationRealm;
this.lookupRealm = lookupRealm;
this.authenticationType = authenticationType;
}

/**
Expand Down Expand Up @@ -115,6 +119,10 @@ public RealmInfo getLookupRealm() {
return lookupRealm;
}

public String getAuthenticationType() {
return authenticationType;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
Expand All @@ -123,12 +131,13 @@ public boolean equals(Object o) {
return enabled == that.enabled &&
Objects.equals(user, that.user) &&
Objects.equals(authenticationRealm, that.authenticationRealm) &&
Objects.equals(lookupRealm, that.lookupRealm);
Objects.equals(lookupRealm, that.lookupRealm) &&
Objects.equals(authenticationType, that.authenticationType);
}

@Override
public int hashCode() {
return Objects.hash(user, enabled, authenticationRealm, lookupRealm);
return Objects.hash(user, enabled, authenticationRealm, lookupRealm, authenticationType);
}

public static AuthenticateResponse fromXContent(XContentParser parser) throws IOException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public void testAuthenticate() throws Exception {

assertThat(authenticateResponse.getUser(), is(putUserRequest.getUser()));
assertThat(authenticateResponse.enabled(), is(true));
assertThat(authenticateResponse.getAuthenticationType(), is("REALM"));

// get user
final GetUsersRequest getUsersRequest =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,7 @@ public void testAuthenticate() throws Exception {
final String authenticationRealmType = response.getAuthenticationRealm().getType(); // <4>
final String lookupRealmName = response.getLookupRealm().getName(); // <5>
final String lookupRealmType = response.getLookupRealm().getType(); // <6>
final String authenticationType = response.getAuthenticationType(); // <7>
//end::authenticate-response

assertThat(user.getUsername(), is("test_user"));
Expand All @@ -762,6 +763,7 @@ public void testAuthenticate() throws Exception {
assertThat(authenticationRealmType, is("file"));
assertThat(lookupRealmName, is("default_file"));
assertThat(lookupRealmType, is("file"));
assertThat(authenticationType, is("REALM"));
}

{
Expand Down Expand Up @@ -2341,6 +2343,7 @@ public void testDelegatePkiAuthentication() throws Exception {
assertThat(authnRealm, is(notNullValue()));
assertThat(authnRealm.getName(), is("pki1"));
assertThat(authnRealm.getType(), is("pki"));
assertThat(resp.getAuthenticationType(), is("TOKEN"));
}

{
Expand Down Expand Up @@ -2384,6 +2387,7 @@ public void onFailure(Exception e) {
assertThat(authnRealm, is(notNullValue()));
assertThat(authnRealm.getName(), is("pki1"));
assertThat(authnRealm.getType(), is("pki"));
assertThat(resp.getAuthenticationType(), is("TOKEN"));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,11 @@ protected AuthenticateResponse createTestInstance() {
final String authenticationRealmType = randomFrom("file", "native", "ldap", "active_directory", "saml", "kerberos");
final String lookupRealmName = randomAlphaOfLength(5);
final String lookupRealmType = randomFrom("file", "native", "ldap", "active_directory", "saml", "kerberos");
final String authenticationType = randomFrom("REALM", "API_KEY", "TOKEN", "ANONYMOUS", "INTERNAL");
return new AuthenticateResponse(
new User(username, roles, metadata, fullName, email), enabled,
new AuthenticateResponse.RealmInfo(authenticationRealmName, authenticationRealmType),
new AuthenticateResponse.RealmInfo(lookupRealmName, lookupRealmType));
new AuthenticateResponse.RealmInfo(lookupRealmName, lookupRealmType), authenticationType);
}

private void toXContent(AuthenticateResponse response, XContentBuilder builder) throws IOException {
Expand All @@ -103,6 +104,7 @@ private void toXContent(AuthenticateResponse response, XContentBuilder builder)
builder.field(AuthenticateResponse.REALM_NAME.getPreferredName(), response.getLookupRealm().getName());
builder.field(AuthenticateResponse.REALM_TYPE.getPreferredName(), response.getLookupRealm().getType());
builder.endObject();
builder.field(AuthenticateResponse.AUTHENTICATION_TYPE.getPreferredName(), response.getAuthenticationType());
builder.endObject();
}

Expand All @@ -111,48 +113,56 @@ private AuthenticateResponse copy(AuthenticateResponse response) {
final User copyUser = new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
originalUser.getFullName(), originalUser.getEmail());
return new AuthenticateResponse(copyUser, response.enabled(), response.getAuthenticationRealm(),
response.getLookupRealm());
response.getLookupRealm(), response.getAuthenticationType());
}

private AuthenticateResponse mutate(AuthenticateResponse response) {
final User originalUser = response.getUser();
switch (randomIntBetween(1, 8)) {
switch (randomIntBetween(1, 9)) {
case 1:
return new AuthenticateResponse(new User(originalUser.getUsername() + "wrong", originalUser.getRoles(),
originalUser.getMetadata(), originalUser.getFullName(), originalUser.getEmail()), response.enabled(),
response.getAuthenticationRealm(), response.getLookupRealm());
response.getAuthenticationRealm(), response.getLookupRealm(), response.getAuthenticationType());
case 2:
final List<String> wrongRoles = new ArrayList<>(originalUser.getRoles());
wrongRoles.add(randomAlphaOfLengthBetween(1, 4));
return new AuthenticateResponse(new User(originalUser.getUsername(), wrongRoles, originalUser.getMetadata(),
originalUser.getFullName(), originalUser.getEmail()), response.enabled(), response.getAuthenticationRealm(),
response.getLookupRealm());
response.getLookupRealm(), response.getAuthenticationType());
case 3:
final Map<String, Object> wrongMetadata = new HashMap<>(originalUser.getMetadata());
wrongMetadata.put("wrong_string", randomAlphaOfLengthBetween(0, 4));
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), wrongMetadata,
originalUser.getFullName(), originalUser.getEmail()), response.enabled(), response.getAuthenticationRealm(),
response.getLookupRealm());
response.getLookupRealm(), response.getAuthenticationType());
case 4:
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
originalUser.getFullName() + "wrong", originalUser.getEmail()), response.enabled(),
response.getAuthenticationRealm(), response.getLookupRealm());
response.getAuthenticationRealm(), response.getLookupRealm(), response.getAuthenticationType());
case 5:
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
originalUser.getFullName(), originalUser.getEmail() + "wrong"), response.enabled(),
response.getAuthenticationRealm(), response.getLookupRealm());
response.getAuthenticationRealm(), response.getLookupRealm(), response.getAuthenticationType());
case 6:
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
originalUser.getFullName(), originalUser.getEmail()), !response.enabled(), response.getAuthenticationRealm(),
response.getLookupRealm());
response.getLookupRealm(), response.getAuthenticationType());
case 7:
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
originalUser.getFullName(), originalUser.getEmail()), response.enabled(), response.getAuthenticationRealm(),
new AuthenticateResponse.RealmInfo(randomAlphaOfLength(5), randomAlphaOfLength(5)));
new AuthenticateResponse.RealmInfo(randomAlphaOfLength(5), randomAlphaOfLength(5)),
response.getAuthenticationType());
case 8:
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
originalUser.getFullName(), originalUser.getEmail()), response.enabled(),
new AuthenticateResponse.RealmInfo(randomAlphaOfLength(5), randomAlphaOfLength(5)), response.getLookupRealm());
new AuthenticateResponse.RealmInfo(randomAlphaOfLength(5), randomAlphaOfLength(5)), response.getLookupRealm(),
response.getAuthenticationType());
case 9:
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
originalUser.getFullName(), originalUser.getEmail()), response.enabled(), response.getAuthenticationRealm(),
response.getLookupRealm(),
randomValueOtherThan(response.getAuthenticationType(),
() -> randomFrom("REALM", "API_KEY", "TOKEN", "ANONYMOUS", "INTERNAL")));
}
throw new IllegalStateException("Bad random number");
}
Expand Down
1 change: 1 addition & 0 deletions docs/java-rest/high-level/security/authenticate.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ see {javadoc-client}/security/user/User.html.
<4> `getAuthenticationRealm().getType()` retrieves the type of the realm that authenticated the user.
<5> `getLookupRealm().getName()` retrieves the name of the realm from where the user information is looked up.
<6> `getLookupRealm().getType()` retrieves the type of the realm from where the user information is looked up.
<7> `getAuthenticationType()` retrieves the authentication type of the authenticated user.

[id="{upid}-{api}-async"]
==== Asynchronous Execution
Expand Down
7 changes: 4 additions & 3 deletions x-pack/docs/en/rest-api/security/authenticate.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ The following example output provides information about the "rdeniro" user:
--------------------------------------------------
{
"username": "rdeniro",
"roles": [
"roles": [
"admin"
],
"full_name": null,
Expand All @@ -56,8 +56,9 @@ The following example output provides information about the "rdeniro" user:
"lookup_realm": {
"name" : "file",
"type" : "file"
}
},
"authentication_type": "REALM"
}
--------------------------------------------------
// TESTRESPONSE[s/"rdeniro"/"$body.username"/]
// TESTRESPONSE[s/"admin"/"superuser"/]
// TESTRESPONSE[s/"admin"/"superuser"/]
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@ public void writeTo(StreamOutput out) throws IOException {
authentication.writeTo(out);
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ public void toXContentFragment(XContentBuilder builder) throws IOException {
builder.field(User.Fields.REALM_TYPE.getPreferredName(), getAuthenticatedBy().getType());
}
builder.endObject();
builder.field(User.Fields.AUTHENTICATION_TYPE.getPreferredName(), getAuthenticationType().name());
ywangd marked this conversation as resolved.
Show resolved Hide resolved
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ public interface Fields {
ParseField LOOKUP_REALM = new ParseField("lookup_realm");
ParseField REALM_TYPE = new ParseField("type");
ParseField REALM_NAME = new ParseField("name");
ParseField AUTHENTICATION_TYPE = new ParseField("authentication_type");
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ public void testCreateApiKey() throws Exception{
AuthenticateResponse authResponse = restClient.security().authenticate(RequestOptions.DEFAULT.toBuilder().addHeader("Authorization",
"ApiKey " + base64ApiKeyKeyValue).build());
assertThat(authResponse.getUser().getUsername(), equalTo(SecuritySettingsSource.TEST_SUPERUSER));
assertThat(authResponse.getAuthenticationType(), equalTo("API_KEY"));

// use the first ApiKey for an unauthorized action
ElasticsearchSecurityException e = expectThrows(ElasticsearchSecurityException.class, () ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -525,8 +525,9 @@ public void testCreateThenRefreshAsDifferentUser() throws IOException {
assertNotEquals(refreshResponse.getRefreshToken(), createTokenResponse.getRefreshToken());

AuthenticateResponse response = restClient.security().authenticate(superuserOptions);
;

assertEquals(SecuritySettingsSource.TEST_SUPERUSER, response.getUser().getUsername());
assertEquals("REALM", response.getAuthenticationType());

assertAuthenticateWithToken(createTokenResponse.getAccessToken(), SecuritySettingsSource.TEST_USER_NAME);
assertAuthenticateWithToken(refreshResponse.getAccessToken(), SecuritySettingsSource.TEST_USER_NAME);
Expand Down Expand Up @@ -604,6 +605,7 @@ private void assertAuthenticateWithToken(String accessToken, String expectedUser
AuthenticateResponse authResponse = restClient.security().authenticate(RequestOptions.DEFAULT.toBuilder().addHeader("Authorization",
"Bearer " + accessToken).build());
assertThat(authResponse.getUser().getUsername(), equalTo(expectedUser));
assertThat(authResponse.getAuthenticationType(), equalTo("TOKEN"));
}

private void assertUnauthorizedToken(String accessToken) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ public void testDelegateThenAuthenticate() throws Exception {
assertThat(authnRealm, is(notNullValue()));
assertThat(authnRealm.getName(), is("pki3"));
assertThat(authnRealm.getType(), is("pki"));
assertThat(resp.getAuthenticationType(), is("TOKEN"));
}
}
}
Expand Down Expand Up @@ -205,6 +206,7 @@ public void testTokenInvalidate() throws Exception {
assertThat(authnRealm, is(notNullValue()));
assertThat(authnRealm.getName(), is("pki3"));
assertThat(authnRealm.getType(), is("pki"));
assertThat(resp.getAuthenticationType(), is("TOKEN"));
// invalidate
InvalidateTokenRequest invalidateRequest = new InvalidateTokenRequest(token, null, null, null);
optionsBuilder = RequestOptions.DEFAULT.toBuilder();
Expand Down Expand Up @@ -291,6 +293,7 @@ public void testDelegatePkiWithRoleMapping() throws Exception {
assertThat(authnRealm, is(notNullValue()));
assertThat(authnRealm.getName(), is("pki3"));
assertThat(authnRealm.getType(), is("pki"));
assertThat(resp.getAuthenticationType(), is("TOKEN"));
// delete role mappings for delegated PKI
restClient.security().deleteRoleMapping(new DeleteRoleMappingRequest("role_by_delegated_user", RefreshPolicy.IMMEDIATE),
testUserOptions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public void testAuthenticateApi() throws Exception {
assertThat(objectPath.evaluate("authentication_realm.type").toString(), equalTo("file"));
assertThat(objectPath.evaluate("lookup_realm.name").toString(), equalTo("file"));
assertThat(objectPath.evaluate("lookup_realm.type").toString(), equalTo("file"));
assertThat(objectPath.evaluate("authentication_type").toString(), equalTo("REALM"));
List<String> roles = objectPath.evaluate("roles");
assertThat(roles.size(), is(1));
assertThat(roles, contains(SecuritySettingsSource.TEST_ROLE));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ teardown:
- match: { username: "authenticate_user" }
- match: { roles.0: "superuser" }
- match: { full_name: "Authenticate User" }
- match: { authentication_type: "REALM" }