Skip to content

Commit eecee44

Browse files
authored
Include authentication type for the authenticate response (#61247)
Add a new "authentication_type" field to the response of "GET _security/_authenticate".
1 parent 051e79d commit eecee44

File tree

14 files changed

+57
-21
lines changed

14 files changed

+57
-21
lines changed

client/rest-high-level/src/main/java/org/elasticsearch/client/security/AuthenticateResponse.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,12 +50,13 @@ public final class AuthenticateResponse {
5050
static final ParseField LOOKUP_REALM = new ParseField("lookup_realm");
5151
static final ParseField REALM_NAME = new ParseField("name");
5252
static final ParseField REALM_TYPE = new ParseField("type");
53+
static final ParseField AUTHENTICATION_TYPE = new ParseField("authentication_type");
5354

5455
@SuppressWarnings("unchecked")
5556
private static final ConstructingObjectParser<AuthenticateResponse, Void> PARSER = new ConstructingObjectParser<>(
5657
"client_security_authenticate_response", true,
5758
a -> new AuthenticateResponse(new User((String) a[0], ((List<String>) a[1]), (Map<String, Object>) a[2],
58-
(String) a[3], (String) a[4]), (Boolean) a[5], (RealmInfo) a[6], (RealmInfo) a[7]));
59+
(String) a[3], (String) a[4]), (Boolean) a[5], (RealmInfo) a[6], (RealmInfo) a[7], (String) a[8]));
5960
static {
6061
final ConstructingObjectParser<RealmInfo, Void> realmInfoParser = new ConstructingObjectParser<>("realm_info", true,
6162
a -> new RealmInfo((String) a[0], (String) a[1]));
@@ -69,20 +70,23 @@ public final class AuthenticateResponse {
6970
PARSER.declareBoolean(constructorArg(), ENABLED);
7071
PARSER.declareObject(constructorArg(), realmInfoParser, AUTHENTICATION_REALM);
7172
PARSER.declareObject(constructorArg(), realmInfoParser, LOOKUP_REALM);
73+
PARSER.declareString(constructorArg(), AUTHENTICATION_TYPE);
7274
}
7375

7476
private final User user;
7577
private final boolean enabled;
7678
private final RealmInfo authenticationRealm;
7779
private final RealmInfo lookupRealm;
80+
private final String authenticationType;
7881

7982

8083
public AuthenticateResponse(User user, boolean enabled, RealmInfo authenticationRealm,
81-
RealmInfo lookupRealm) {
84+
RealmInfo lookupRealm, String authenticationType) {
8285
this.user = user;
8386
this.enabled = enabled;
8487
this.authenticationRealm = authenticationRealm;
8588
this.lookupRealm = lookupRealm;
89+
this.authenticationType = authenticationType;
8690
}
8791

8892
/**
@@ -115,6 +119,10 @@ public RealmInfo getLookupRealm() {
115119
return lookupRealm;
116120
}
117121

122+
public String getAuthenticationType() {
123+
return authenticationType;
124+
}
125+
118126
@Override
119127
public boolean equals(Object o) {
120128
if (this == o) return true;
@@ -123,12 +131,13 @@ public boolean equals(Object o) {
123131
return enabled == that.enabled &&
124132
Objects.equals(user, that.user) &&
125133
Objects.equals(authenticationRealm, that.authenticationRealm) &&
126-
Objects.equals(lookupRealm, that.lookupRealm);
134+
Objects.equals(lookupRealm, that.lookupRealm) &&
135+
Objects.equals(authenticationType, that.authenticationType);
127136
}
128137

129138
@Override
130139
public int hashCode() {
131-
return Objects.hash(user, enabled, authenticationRealm, lookupRealm);
140+
return Objects.hash(user, enabled, authenticationRealm, lookupRealm, authenticationType);
132141
}
133142

134143
public static AuthenticateResponse fromXContent(XContentParser parser) throws IOException {

client/rest-high-level/src/test/java/org/elasticsearch/client/SecurityIT.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ public void testAuthenticate() throws Exception {
108108

109109
assertThat(authenticateResponse.getUser(), is(putUserRequest.getUser()));
110110
assertThat(authenticateResponse.enabled(), is(true));
111+
assertThat(authenticateResponse.getAuthenticationType(), is("realm"));
111112

112113
// get user
113114
final GetUsersRequest getUsersRequest =

client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/SecurityDocumentationIT.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,7 @@ public void testAuthenticate() throws Exception {
750750
final String authenticationRealmType = response.getAuthenticationRealm().getType(); // <4>
751751
final String lookupRealmName = response.getLookupRealm().getName(); // <5>
752752
final String lookupRealmType = response.getLookupRealm().getType(); // <6>
753+
final String authenticationType = response.getAuthenticationType(); // <7>
753754
//end::authenticate-response
754755

755756
assertThat(user.getUsername(), is("test_user"));
@@ -762,6 +763,7 @@ public void testAuthenticate() throws Exception {
762763
assertThat(authenticationRealmType, is("file"));
763764
assertThat(lookupRealmName, is("default_file"));
764765
assertThat(lookupRealmType, is("file"));
766+
assertThat(authenticationType, is("realm"));
765767
}
766768

767769
{
@@ -2341,6 +2343,7 @@ public void testDelegatePkiAuthentication() throws Exception {
23412343
assertThat(authnRealm, is(notNullValue()));
23422344
assertThat(authnRealm.getName(), is("pki1"));
23432345
assertThat(authnRealm.getType(), is("pki"));
2346+
assertThat(resp.getAuthenticationType(), is("token"));
23442347
}
23452348

23462349
{
@@ -2384,6 +2387,7 @@ public void onFailure(Exception e) {
23842387
assertThat(authnRealm, is(notNullValue()));
23852388
assertThat(authnRealm.getName(), is("pki1"));
23862389
assertThat(authnRealm.getType(), is("pki"));
2390+
assertThat(resp.getAuthenticationType(), is("token"));
23872391
}
23882392
}
23892393

client/rest-high-level/src/test/java/org/elasticsearch/client/security/AuthenticateResponseTests.java

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,11 @@ protected AuthenticateResponse createTestInstance() {
7575
final String authenticationRealmType = randomFrom("file", "native", "ldap", "active_directory", "saml", "kerberos");
7676
final String lookupRealmName = randomAlphaOfLength(5);
7777
final String lookupRealmType = randomFrom("file", "native", "ldap", "active_directory", "saml", "kerberos");
78+
final String authenticationType = randomFrom("realm", "api_key", "token", "anonymous", "internal");
7879
return new AuthenticateResponse(
7980
new User(username, roles, metadata, fullName, email), enabled,
8081
new AuthenticateResponse.RealmInfo(authenticationRealmName, authenticationRealmType),
81-
new AuthenticateResponse.RealmInfo(lookupRealmName, lookupRealmType));
82+
new AuthenticateResponse.RealmInfo(lookupRealmName, lookupRealmType), authenticationType);
8283
}
8384

8485
private void toXContent(AuthenticateResponse response, XContentBuilder builder) throws IOException {
@@ -103,6 +104,7 @@ private void toXContent(AuthenticateResponse response, XContentBuilder builder)
103104
builder.field(AuthenticateResponse.REALM_NAME.getPreferredName(), response.getLookupRealm().getName());
104105
builder.field(AuthenticateResponse.REALM_TYPE.getPreferredName(), response.getLookupRealm().getType());
105106
builder.endObject();
107+
builder.field(AuthenticateResponse.AUTHENTICATION_TYPE.getPreferredName(), response.getAuthenticationType());
106108
builder.endObject();
107109
}
108110

@@ -111,48 +113,56 @@ private AuthenticateResponse copy(AuthenticateResponse response) {
111113
final User copyUser = new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
112114
originalUser.getFullName(), originalUser.getEmail());
113115
return new AuthenticateResponse(copyUser, response.enabled(), response.getAuthenticationRealm(),
114-
response.getLookupRealm());
116+
response.getLookupRealm(), response.getAuthenticationType());
115117
}
116118

117119
private AuthenticateResponse mutate(AuthenticateResponse response) {
118120
final User originalUser = response.getUser();
119-
switch (randomIntBetween(1, 8)) {
121+
switch (randomIntBetween(1, 9)) {
120122
case 1:
121123
return new AuthenticateResponse(new User(originalUser.getUsername() + "wrong", originalUser.getRoles(),
122124
originalUser.getMetadata(), originalUser.getFullName(), originalUser.getEmail()), response.enabled(),
123-
response.getAuthenticationRealm(), response.getLookupRealm());
125+
response.getAuthenticationRealm(), response.getLookupRealm(), response.getAuthenticationType());
124126
case 2:
125127
final List<String> wrongRoles = new ArrayList<>(originalUser.getRoles());
126128
wrongRoles.add(randomAlphaOfLengthBetween(1, 4));
127129
return new AuthenticateResponse(new User(originalUser.getUsername(), wrongRoles, originalUser.getMetadata(),
128130
originalUser.getFullName(), originalUser.getEmail()), response.enabled(), response.getAuthenticationRealm(),
129-
response.getLookupRealm());
131+
response.getLookupRealm(), response.getAuthenticationType());
130132
case 3:
131133
final Map<String, Object> wrongMetadata = new HashMap<>(originalUser.getMetadata());
132134
wrongMetadata.put("wrong_string", randomAlphaOfLengthBetween(0, 4));
133135
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), wrongMetadata,
134136
originalUser.getFullName(), originalUser.getEmail()), response.enabled(), response.getAuthenticationRealm(),
135-
response.getLookupRealm());
137+
response.getLookupRealm(), response.getAuthenticationType());
136138
case 4:
137139
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
138140
originalUser.getFullName() + "wrong", originalUser.getEmail()), response.enabled(),
139-
response.getAuthenticationRealm(), response.getLookupRealm());
141+
response.getAuthenticationRealm(), response.getLookupRealm(), response.getAuthenticationType());
140142
case 5:
141143
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
142144
originalUser.getFullName(), originalUser.getEmail() + "wrong"), response.enabled(),
143-
response.getAuthenticationRealm(), response.getLookupRealm());
145+
response.getAuthenticationRealm(), response.getLookupRealm(), response.getAuthenticationType());
144146
case 6:
145147
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
146148
originalUser.getFullName(), originalUser.getEmail()), !response.enabled(), response.getAuthenticationRealm(),
147-
response.getLookupRealm());
149+
response.getLookupRealm(), response.getAuthenticationType());
148150
case 7:
149151
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
150152
originalUser.getFullName(), originalUser.getEmail()), response.enabled(), response.getAuthenticationRealm(),
151-
new AuthenticateResponse.RealmInfo(randomAlphaOfLength(5), randomAlphaOfLength(5)));
153+
new AuthenticateResponse.RealmInfo(randomAlphaOfLength(5), randomAlphaOfLength(5)),
154+
response.getAuthenticationType());
152155
case 8:
153156
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
154157
originalUser.getFullName(), originalUser.getEmail()), response.enabled(),
155-
new AuthenticateResponse.RealmInfo(randomAlphaOfLength(5), randomAlphaOfLength(5)), response.getLookupRealm());
158+
new AuthenticateResponse.RealmInfo(randomAlphaOfLength(5), randomAlphaOfLength(5)), response.getLookupRealm(),
159+
response.getAuthenticationType());
160+
case 9:
161+
return new AuthenticateResponse(new User(originalUser.getUsername(), originalUser.getRoles(), originalUser.getMetadata(),
162+
originalUser.getFullName(), originalUser.getEmail()), response.enabled(), response.getAuthenticationRealm(),
163+
response.getLookupRealm(),
164+
randomValueOtherThan(response.getAuthenticationType(),
165+
() -> randomFrom("realm", "api_key", "token", "anonymous", "internal")));
156166
}
157167
throw new IllegalStateException("Bad random number");
158168
}

docs/java-rest/high-level/security/authenticate.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ see {javadoc-client}/security/user/User.html.
4444
<4> `getAuthenticationRealm().getType()` retrieves the type of the realm that authenticated the user.
4545
<5> `getLookupRealm().getName()` retrieves the name of the realm from where the user information is looked up.
4646
<6> `getLookupRealm().getType()` retrieves the type of the realm from where the user information is looked up.
47+
<7> `getAuthenticationType()` retrieves the authentication type of the authenticated user.
4748

4849
[id="{upid}-{api}-async"]
4950
==== Asynchronous Execution

x-pack/docs/en/rest-api/security/authenticate.asciidoc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ The following example output provides information about the "rdeniro" user:
4242
--------------------------------------------------
4343
{
4444
"username": "rdeniro",
45-
"roles": [
45+
"roles": [
4646
"admin"
4747
],
4848
"full_name": null,
@@ -56,8 +56,9 @@ The following example output provides information about the "rdeniro" user:
5656
"lookup_realm": {
5757
"name" : "file",
5858
"type" : "file"
59-
}
59+
},
60+
"authentication_type": "realm"
6061
}
6162
--------------------------------------------------
6263
// TESTRESPONSE[s/"rdeniro"/"$body.username"/]
63-
// TESTRESPONSE[s/"admin"/"superuser"/]
64+
// TESTRESPONSE[s/"admin"/"superuser"/]

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/user/AuthenticateResponse.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,4 @@ public void writeTo(StreamOutput out) throws IOException {
3434
authentication.writeTo(out);
3535
}
3636

37-
}
37+
}

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/authc/Authentication.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.io.IOException;
2121
import java.util.Base64;
2222
import java.util.Collections;
23+
import java.util.Locale;
2324
import java.util.Map;
2425
import java.util.Objects;
2526

@@ -176,6 +177,7 @@ public void toXContentFragment(XContentBuilder builder) throws IOException {
176177
builder.field(User.Fields.REALM_TYPE.getPreferredName(), getAuthenticatedBy().getType());
177178
}
178179
builder.endObject();
180+
builder.field(User.Fields.AUTHENTICATION_TYPE.getPreferredName(), getAuthenticationType().name().toLowerCase(Locale.ROOT));
179181
}
180182

181183
@Override
@@ -261,4 +263,3 @@ public enum AuthenticationType {
261263
INTERNAL
262264
}
263265
}
264-

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/user/User.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ public interface Fields {
238238
ParseField LOOKUP_REALM = new ParseField("lookup_realm");
239239
ParseField REALM_TYPE = new ParseField("type");
240240
ParseField REALM_NAME = new ParseField("name");
241+
ParseField AUTHENTICATION_TYPE = new ParseField("authentication_type");
241242
}
242243
}
243244

x-pack/plugin/security/src/test/java/org/elasticsearch/xpack/security/authc/ApiKeyIntegTests.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ public void testCreateApiKey() throws Exception{
190190
AuthenticateResponse authResponse = restClient.security().authenticate(RequestOptions.DEFAULT.toBuilder().addHeader("Authorization",
191191
"ApiKey " + base64ApiKeyKeyValue).build());
192192
assertThat(authResponse.getUser().getUsername(), equalTo(SecuritySettingsSource.TEST_SUPERUSER));
193+
assertThat(authResponse.getAuthenticationType(), equalTo("api_key"));
193194

194195
// use the first ApiKey for an unauthorized action
195196
ElasticsearchSecurityException e = expectThrows(ElasticsearchSecurityException.class, () ->

0 commit comments

Comments
 (0)