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

Adds realm name OIDC _security/oidc/prepare and _security/oidc/authenticate APIs responses #64966

Merged
merged 5 commits into from
Nov 16, 2020
Merged
Changes from 4 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
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@ be used to authenticate this. Useful when multiple realms have been defined.

The following example request exchanges the response that was returned from the
OpenID Connect Provider after a successful authentication, for an {es} access
token and refresh token to be used in subsequent requests. This example is from
token and refresh token to be used in subsequent requests. This example is from
an authentication that uses the authorization code grant flow.

[source,console]
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@
=== OpenID Connect Prepare Authentication API

Creates an oAuth 2.0 authentication request as a URL string based on the
configuration of the respective OpenID Connect authentication realm in {es}.
configuration of the respective OpenID Connect authentication realm in {es}.

[[security-api-oidc-prepare-authentication-request]]
==== {api-request-title}
@@ -16,13 +16,13 @@ configuration of the respective OpenID Connect authentication realm in {es}.
[[security-api-oidc-prepare-authentication-desc]]
==== {api-description-title}

The response of this API is a URL pointing to the Authorization Endpoint of the
configured OpenID Connect Provider and can be used to redirect the browser of
The response of this API is a URL pointing to the Authorization Endpoint of the
configured OpenID Connect Provider and can be used to redirect the browser of
the user in order to continue the authentication process.

{es} exposes all the necessary OpenID Connect related functionality via the
OpenID Connect APIs. These APIs are used internally by {kib} in order to provide
OpenID Connect based authentication, but can also be used by other, custom web
OpenID Connect based authentication, but can also be used by other, custom web
applications or other clients. See also
<<security-api-oidc-authenticate,OpenID Connect authenticate API>>
and <<security-api-oidc-logout,OpenID Connect logout API>>.
@@ -81,7 +81,8 @@ the Authentication Request, as HTTP GET parameters:
{
"redirect" : "http://127.0.0.1:8080/c2id-login?scope=openid&response_type=id_token&redirect_uri=https%3A%2F%2Fmy.fantastic.rp%2Fcb&state=4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I&nonce=WaBPH0KqPVdG5HHdSxPRjfoZbXMCicm5v1OiAj0DUFM&client_id=elasticsearch-rp",
"state" : "4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I",
"nonce" : "WaBPH0KqPVdG5HHdSxPRjfoZbXMCicm5v1OiAj0DUFM"
"nonce" : "WaBPH0KqPVdG5HHdSxPRjfoZbXMCicm5v1OiAj0DUFM",
"realm" : "oidc1"
}
--------------------------------------------------
// TESTRESPONSE[s/4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I/\$\{body.state\}/]
@@ -109,7 +110,8 @@ the Authentication Request, as HTTP GET parameters:
{
"redirect" : "http://127.0.0.1:8080/c2id-login?scope=openid&response_type=id_token&redirect_uri=https%3A%2F%2Fmy.fantastic.rp%2Fcb&state=lGYK0EcSLjqH6pkT5EVZjC6eIW5YCGgywj2sxROO&nonce=zOBXLJGUooRrbLbQk5YCcyC8AXw3iloynvluYhZ5&client_id=elasticsearch-rp",
"state" : "lGYK0EcSLjqH6pkT5EVZjC6eIW5YCGgywj2sxROO",
"nonce" : "zOBXLJGUooRrbLbQk5YCcyC8AXw3iloynvluYhZ5"
"nonce" : "zOBXLJGUooRrbLbQk5YCcyC8AXw3iloynvluYhZ5",
"realm" : "oidc1"
}
--------------------------------------------------

@@ -134,8 +136,9 @@ the Authentication Request, as HTTP GET parameters:
{
"redirect" : "http://127.0.0.1:8080/c2id-login?login_hint=this_is_an_opaque_string&scope=openid&response_type=id_token&redirect_uri=https%3A%2F%2Fmy.fantastic.rp%2Fcb&state=4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I&nonce=WaBPH0KqPVdG5HHdSxPRjfoZbXMCicm5v1OiAj0DUFM&client_id=elasticsearch-rp",
"state" : "4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I",
"nonce" : "WaBPH0KqPVdG5HHdSxPRjfoZbXMCicm5v1OiAj0DUFM"
"nonce" : "WaBPH0KqPVdG5HHdSxPRjfoZbXMCicm5v1OiAj0DUFM",
"realm" : "oidc1"
}
--------------------------------------------------
// TESTRESPONSE[s/4dbrihtIAt3wBTwo6DxK-vdk-sSyDBV8Yf0AjdkdT5I/\$\{body.state\}/]
// TESTRESPONSE[s/WaBPH0KqPVdG5HHdSxPRjfoZbXMCicm5v1OiAj0DUFM/\$\{body.nonce\}/]
// TESTRESPONSE[s/WaBPH0KqPVdG5HHdSxPRjfoZbXMCicm5v1OiAj0DUFM/\$\{body.nonce\}/]
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@
*/
package org.elasticsearch.xpack.core.security.action.oidc;

import org.elasticsearch.Version;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
@@ -28,18 +29,26 @@ public class OpenIdConnectPrepareAuthenticationResponse extends ActionResponse i
* String value used to associate a Client session with an ID Token, and to mitigate replay attacks.
*/
private String nonce;
/*
* String value: name of the realm used to perform authentication.
*/
private String realmName;

public OpenIdConnectPrepareAuthenticationResponse(String authorizationEndpointUrl, String state, String nonce) {
public OpenIdConnectPrepareAuthenticationResponse(String authorizationEndpointUrl, String state, String nonce, String realmName) {
this.authenticationRequestUrl = authorizationEndpointUrl;
this.state = state;
this.nonce = nonce;
this.realmName = realmName;
}

public OpenIdConnectPrepareAuthenticationResponse(StreamInput in) throws IOException {
super(in);
authenticationRequestUrl = in.readString();
state = in.readString();
nonce = in.readString();
if (in.getVersion().onOrAfter(Version.V_7_11_0)) {
realmName = in.readString();
}
}

public String getAuthenticationRequestUrl() {
@@ -54,15 +63,23 @@ public String getNonce() {
return nonce;
}

public String getRealmName() {
return realmName;
}

@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeString(authenticationRequestUrl);
out.writeString(state);
out.writeString(nonce);
if (out.getVersion().onOrAfter(Version.V_7_11_0)) {
out.writeString(realmName);
}
}

public String toString() {
return "{authenticationRequestUrl=" + authenticationRequestUrl + ", state=" + state + ", nonce=" + nonce + "}";
return "{authenticationRequestUrl=" + authenticationRequestUrl + ", state=" + state + ", nonce="
+ nonce + ", realmName" + realmName + "}";
}

@Override
@@ -71,6 +88,9 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
builder.field("redirect", authenticationRequestUrl);
builder.field("state", state);
builder.field("nonce", nonce);
if(realmName != null){
builder.field("realm", realmName);
}
builder.endObject();
return builder;
}
Original file line number Diff line number Diff line change
@@ -363,7 +363,7 @@ public OpenIdConnectPrepareAuthenticationResponse buildAuthenticationRequestUri(
builder.loginHint(loginHint);
}
return new OpenIdConnectPrepareAuthenticationResponse(builder.build().toURI().toString(),
state.getValue(), nonce.getValue());
state.getValue(), nonce.getValue(), this.name());
}

public boolean isIssuerValid(String issuer) {
Original file line number Diff line number Diff line change
@@ -269,6 +269,7 @@ public void testBuildRelyingPartyConfigWithoutOpenIdScope() {
assertThat(response.getAuthenticationRequestUrl(),
equalTo("https://op.example.com/login?scope=scope1+scope2+openid&response_type=code" +
"&redirect_uri=https%3A%2F%2Frp.my.com%2Fcb&state=" + state + "&nonce=" + nonce + "&client_id=rp-my"));
assertThat(response.getRealmName(), equalTo(REALM_NAME));
}

public void testBuildingAuthenticationRequest() {
@@ -292,6 +293,7 @@ public void testBuildingAuthenticationRequest() {
assertThat(response.getAuthenticationRequestUrl(),
equalTo("https://op.example.com/login?scope=openid+scope1+scope2&response_type=code" +
"&redirect_uri=https%3A%2F%2Frp.my.com%2Fcb&state=" + state + "&nonce=" + nonce + "&client_id=rp-my"));
assertThat(response.getRealmName(), equalTo(REALM_NAME));
}

public void testBuilidingAuthenticationRequestWithDefaultScope() {
@@ -313,6 +315,7 @@ public void testBuilidingAuthenticationRequestWithDefaultScope() {
final String nonce = response.getNonce();
assertThat(response.getAuthenticationRequestUrl(), equalTo("https://op.example.com/login?scope=openid&response_type=code" +
"&redirect_uri=https%3A%2F%2Frp.my.com%2Fcb&state=" + state + "&nonce=" + nonce + "&client_id=rp-my"));
assertThat(response.getRealmName(), equalTo(REALM_NAME));
}

public void testBuildLogoutResponse() throws Exception {
@@ -370,6 +373,7 @@ public void testBuildingAuthenticationRequestWithExistingStateAndNonce() {

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

public void testBuildingAuthenticationRequestWithLoginHint() {
@@ -394,6 +398,7 @@ public void testBuildingAuthenticationRequestWithLoginHint() {
assertThat(response.getAuthenticationRequestUrl(), equalTo("https://op.example.com/login?login_hint=" + thehint +
"&scope=openid&response_type=code&redirect_uri=https%3A%2F%2Frp.my.com%2Fcb&state=" +
state + "&nonce=" + nonce + "&client_id=rp-my"));
assertThat(response.getRealmName(), equalTo(REALM_NAME));
}

private AuthenticationResult authenticateWithOidc(String principal, UserRoleMapper roleMapper, boolean notPopulateMetadata,
Original file line number Diff line number Diff line change
@@ -420,6 +420,7 @@ private Tuple<String, String> completeAuthentication(String redirectUri, String
logger.info(" OpenIDConnect authentication response {}", responseBody);
assertNotNull(responseBody.get("access_token"));
assertNotNull(responseBody.get("refresh_token"));
assertNotNull(responseBody.get("realm"));
assertNotNull(responseBody.get("authentication"));
assertEquals("alice", ((Map)responseBody.get("authentication")).get("username"));
return Tuple.tuple(responseBody.get("access_token").toString(), responseBody.get("refresh_token").toString());
@@ -517,11 +518,13 @@ class PrepareAuthResponse {
private URI authUri;
private String state;
private String nonce;
private String realm;

PrepareAuthResponse(URI authUri, String state, String nonce, @Nullable String realm) {
PrepareAuthResponse(URI authUri, String state, String nonce, String realm) {
this.authUri = authUri;
this.state = state;
this.nonce = nonce;
this.realm = realm;
}

URI getAuthUri() {
@@ -536,5 +539,7 @@ String getNonce() {
return nonce;
}

String getRealm() { return realm; }

}
}