Skip to content

Commit 4e0788e

Browse files
committed
address feedback
1 parent afaf2e9 commit 4e0788e

File tree

4 files changed

+61
-20
lines changed

4 files changed

+61
-20
lines changed

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/security/action/oidc/OpenIdConnectPrepareAuthenticationRequest.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public class OpenIdConnectPrepareAuthenticationRequest extends ActionRequest {
3030
* issuer to the UA needs to be redirected for authentication
3131
*/
3232
private String issuer;
33+
private String loginHint;
3334
private String state;
3435
private String nonce;
3536

@@ -49,6 +50,11 @@ public String getIssuer() {
4950
return issuer;
5051
}
5152

53+
public String getLoginHint() {
54+
return loginHint;
55+
}
56+
57+
5258
public void setRealmName(String realmName) {
5359
this.realmName = realmName;
5460
}
@@ -65,13 +71,18 @@ public void setNonce(String nonce) {
6571
this.nonce = nonce;
6672
}
6773

74+
public void setLoginHint(String loginHint) {
75+
this.loginHint = loginHint;
76+
}
77+
6878
public OpenIdConnectPrepareAuthenticationRequest() {
6979
}
7080

7181
public OpenIdConnectPrepareAuthenticationRequest(StreamInput in) throws IOException {
7282
super.readFrom(in);
7383
realmName = in.readOptionalString();
7484
issuer = in.readOptionalString();
85+
loginHint = in.readOptionalString();
7586
state = in.readOptionalString();
7687
nonce = in.readOptionalString();
7788
}
@@ -93,6 +104,7 @@ public void writeTo(StreamOutput out) throws IOException {
93104
super.writeTo(out);
94105
out.writeOptionalString(realmName);
95106
out.writeOptionalString(issuer);
107+
out.writeOptionalString(loginHint);
96108
out.writeOptionalString(state);
97109
out.writeOptionalString(nonce);
98110
}
@@ -103,7 +115,8 @@ public void readFrom(StreamInput in) {
103115
}
104116

105117
public String toString() {
106-
return "{realmName=" + realmName + ", issuer=" + issuer +", state=" + state + ", nonce=" + nonce + "}";
118+
return "{realmName=" + realmName + ", issuer=" + issuer + ", login_hint=" +
119+
loginHint + ", state=" + state + ", nonce=" + nonce + "}";
107120
}
108121

109122
}

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/action/oidc/TransportOpenIdConnectPrepareAuthenticationAction.java

+5-3
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,19 @@ protected void doExecute(Task task, OpenIdConnectPrepareAuthenticationRequest re
6161
}
6262

6363
if (realm instanceof OpenIdConnectRealm) {
64-
prepareAuthenticationResponse((OpenIdConnectRealm) realm, request.getState(), request.getNonce(), listener);
64+
prepareAuthenticationResponse((OpenIdConnectRealm) realm, request.getState(), request.getNonce(), request.getLoginHint(),
65+
listener);
6566
} else {
6667
listener.onFailure(
6768
new ElasticsearchSecurityException("Cannot find OpenID Connect realm with name [{}]", request.getRealmName()));
6869
}
6970
}
7071

71-
private void prepareAuthenticationResponse(OpenIdConnectRealm realm, String state, String nonce,
72+
private void prepareAuthenticationResponse(OpenIdConnectRealm realm, String state, String nonce, String loginHint,
7273
ActionListener<OpenIdConnectPrepareAuthenticationResponse> listener) {
7374
try {
74-
final OpenIdConnectPrepareAuthenticationResponse authenticationResponse = realm.buildAuthenticationRequestUri(state, nonce);
75+
final OpenIdConnectPrepareAuthenticationResponse authenticationResponse =
76+
realm.buildAuthenticationRequestUri(state, nonce, loginHint);
7577
listener.onResponse(authenticationResponse);
7678
} catch (ElasticsearchException e) {
7779
listener.onFailure(e);

x-pack/plugin/security/src/main/java/org/elasticsearch/xpack/security/authc/oidc/OpenIdConnectRealm.java

+12-9
Original file line numberDiff line numberDiff line change
@@ -294,23 +294,26 @@ private static String require(RealmConfig config, Setting.AffixSetting<String> s
294294
*
295295
* @param existingState An existing state that can be reused or null if we need to generate one
296296
* @param existingNonce An existing nonce that can be reused or null if we need to generate one
297+
* @param loginHint A String with a login hint to add to the authentication request in case of a 3rd party initiated login
297298
*
298299
* @return an {@link OpenIdConnectPrepareAuthenticationResponse}
299300
*/
300301
public OpenIdConnectPrepareAuthenticationResponse buildAuthenticationRequestUri(@Nullable String existingState,
301-
@Nullable String existingNonce) {
302+
@Nullable String existingNonce,
303+
@Nullable String loginHint) {
302304
final State state = existingState != null ? new State(existingState) : new State();
303305
final Nonce nonce = existingNonce != null ? new Nonce(existingNonce) : new Nonce();
304-
final AuthenticationRequest authenticationRequest = new AuthenticationRequest(
305-
opConfiguration.getAuthorizationEndpoint(),
306-
rpConfiguration.getResponseType(),
306+
final AuthenticationRequest.Builder builder = new AuthenticationRequest.Builder(rpConfiguration.getResponseType(),
307307
rpConfiguration.getRequestedScope(),
308308
rpConfiguration.getClientId(),
309-
rpConfiguration.getRedirectUri(),
310-
state,
311-
nonce);
312-
313-
return new OpenIdConnectPrepareAuthenticationResponse(authenticationRequest.toURI().toString(),
309+
rpConfiguration.getRedirectUri())
310+
.endpointURI(opConfiguration.getAuthorizationEndpoint())
311+
.state(state)
312+
.nonce(nonce);
313+
if (Strings.hasText(loginHint)) {
314+
builder.loginHint(loginHint);
315+
}
316+
return new OpenIdConnectPrepareAuthenticationResponse(builder.build().toURI().toString(),
314317
state.getValue(), nonce.getValue());
315318
}
316319

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

+30-7
Original file line numberDiff line numberDiff line change
@@ -162,15 +162,15 @@ public void testBuildRelyingPartyConfigWithoutOpenIdScope() {
162162
Arrays.asList("scope1", "scope2"));
163163
final OpenIdConnectRealm realm = new OpenIdConnectRealm(buildConfig(settingsBuilder.build()), null,
164164
null);
165-
final OpenIdConnectPrepareAuthenticationResponse response = realm.buildAuthenticationRequestUri(null, null);
165+
final OpenIdConnectPrepareAuthenticationResponse response = realm.buildAuthenticationRequestUri(null, null, null);
166166
final String state = response.getState();
167167
final String nonce = response.getNonce();
168168
assertThat(response.getAuthenticationRequestUrl(),
169169
equalTo("https://op.example.com/login?scope=scope1+scope2+openid&response_type=code" +
170170
"&redirect_uri=https%3A%2F%2Frp.my.com%2Fcb&state=" + state + "&nonce=" + nonce + "&client_id=rp-my"));
171171
}
172172

173-
public void testBuilidingAuthenticationRequest() {
173+
public void testBuildingAuthenticationRequest() {
174174
final Settings.Builder settingsBuilder = Settings.builder()
175175
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_AUTHORIZATION_ENDPOINT), "https://op.example.com/login")
176176
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_TOKEN_ENDPOINT), "https://op.example.com/token")
@@ -185,7 +185,7 @@ public void testBuilidingAuthenticationRequest() {
185185
Arrays.asList("openid", "scope1", "scope2"));
186186
final OpenIdConnectRealm realm = new OpenIdConnectRealm(buildConfig(settingsBuilder.build()), null,
187187
null);
188-
final OpenIdConnectPrepareAuthenticationResponse response = realm.buildAuthenticationRequestUri(null, null);
188+
final OpenIdConnectPrepareAuthenticationResponse response = realm.buildAuthenticationRequestUri(null, null, null);
189189
final String state = response.getState();
190190
final String nonce = response.getNonce();
191191
assertThat(response.getAuthenticationRequestUrl(),
@@ -194,7 +194,7 @@ public void testBuilidingAuthenticationRequest() {
194194
}
195195

196196

197-
public void testBuilidingAuthenticationRequestWithDefaultScope() {
197+
public void testBuildingAuthenticationRequestWithDefaultScope() {
198198
final Settings.Builder settingsBuilder = Settings.builder()
199199
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_AUTHORIZATION_ENDPOINT), "https://op.example.com/login")
200200
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_TOKEN_ENDPOINT), "https://op.example.com/token")
@@ -207,14 +207,14 @@ public void testBuilidingAuthenticationRequestWithDefaultScope() {
207207
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_RESPONSE_TYPE), "code");
208208
final OpenIdConnectRealm realm = new OpenIdConnectRealm(buildConfig(settingsBuilder.build()), null,
209209
null);
210-
final OpenIdConnectPrepareAuthenticationResponse response = realm.buildAuthenticationRequestUri(null, null);
210+
final OpenIdConnectPrepareAuthenticationResponse response = realm.buildAuthenticationRequestUri(null, null, null);
211211
final String state = response.getState();
212212
final String nonce = response.getNonce();
213213
assertThat(response.getAuthenticationRequestUrl(), equalTo("https://op.example.com/login?scope=openid&response_type=code" +
214214
"&redirect_uri=https%3A%2F%2Frp.my.com%2Fcb&state=" + state + "&nonce=" + nonce + "&client_id=rp-my"));
215215
}
216216

217-
public void testBuilidingAuthenticationRequestWithExistingStateAndNonce() {
217+
public void testBuildingAuthenticationRequestWithExistingStateAndNonce() {
218218
final Settings.Builder settingsBuilder = Settings.builder()
219219
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_AUTHORIZATION_ENDPOINT), "https://op.example.com/login")
220220
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_TOKEN_ENDPOINT), "https://op.example.com/token")
@@ -229,12 +229,35 @@ public void testBuilidingAuthenticationRequestWithExistingStateAndNonce() {
229229
null);
230230
final String state = new State().getValue();
231231
final String nonce = new Nonce().getValue();
232-
final OpenIdConnectPrepareAuthenticationResponse response = realm.buildAuthenticationRequestUri(state, nonce);
232+
final OpenIdConnectPrepareAuthenticationResponse response = realm.buildAuthenticationRequestUri(state, nonce, null);
233233

234234
assertThat(response.getAuthenticationRequestUrl(), equalTo("https://op.example.com/login?scope=openid&response_type=code" +
235235
"&redirect_uri=https%3A%2F%2Frp.my.com%2Fcb&state=" + state + "&nonce=" + nonce + "&client_id=rp-my"));
236236
}
237237

238+
public void testBuildingAuthenticationRequestWithLoginHint() {
239+
final Settings.Builder settingsBuilder = Settings.builder()
240+
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_AUTHORIZATION_ENDPOINT), "https://op.example.com/login")
241+
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_TOKEN_ENDPOINT), "https://op.example.com/token")
242+
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_ISSUER), "https://op.example.com")
243+
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_NAME), "the op")
244+
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_JWKSET_PATH), "https://op.example.com/jwks.json")
245+
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.PRINCIPAL_CLAIM.getClaim()), "sub")
246+
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_REDIRECT_URI), "https://rp.my.com/cb")
247+
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_CLIENT_ID), "rp-my")
248+
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_RESPONSE_TYPE), "code");
249+
final OpenIdConnectRealm realm = new OpenIdConnectRealm(buildConfig(settingsBuilder.build()), null,
250+
null);
251+
final String state = new State().getValue();
252+
final String nonce = new Nonce().getValue();
253+
final String thehint = randomAlphaOfLength(8);
254+
final OpenIdConnectPrepareAuthenticationResponse response = realm.buildAuthenticationRequestUri(state, nonce, thehint);
255+
256+
assertThat(response.getAuthenticationRequestUrl(), equalTo("https://op.example.com/login?login_hint=" + thehint +
257+
"&scope=openid&response_type=code&redirect_uri=https%3A%2F%2Frp.my.com%2Fcb&state=" +
258+
state + "&nonce=" + nonce + "&client_id=rp-my"));
259+
}
260+
238261
private AuthenticationResult authenticateWithOidc(UserRoleMapper roleMapper, boolean notPopulateMetadata, boolean useAuthorizingRealm)
239262
throws Exception {
240263

0 commit comments

Comments
 (0)