Skip to content

Commit 8d54639

Browse files
authored
OpenID Connect Realm base functionality (#37009)
This commit adds * An OpenID Connect Realm definition * Necessary OpenID Connect Realm settings to support Authorization code grant and Implicit grant flows * Rest and Transport Action and Request/Response objects for initiating and completing the authentication flow * Functionality for generating OIDC Authentication Request URIs Unit tests Notably missing (to be handled in subsequent PRs): * The actual implementation of the authentication flows * Necessary JW{T,S,E} functionality Relates: #35339
1 parent 18a3e48 commit 8d54639

27 files changed

+1391
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
package org.elasticsearch.xpack.core.security.action.oidc;
7+
8+
import org.elasticsearch.action.Action;
9+
import org.elasticsearch.common.io.stream.Writeable;
10+
11+
/**
12+
* Action for initiating an authentication process using OpenID Connect
13+
*/
14+
public final class OpenIdConnectAuthenticateAction extends Action<OpenIdConnectAuthenticateResponse> {
15+
16+
public static final OpenIdConnectAuthenticateAction INSTANCE = new OpenIdConnectAuthenticateAction();
17+
public static final String NAME = "cluster:admin/xpack/security/oidc/authenticate";
18+
19+
private OpenIdConnectAuthenticateAction() {
20+
super(NAME);
21+
}
22+
23+
@Override
24+
public OpenIdConnectAuthenticateResponse newResponse() {
25+
throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable");
26+
}
27+
28+
@Override
29+
public Writeable.Reader<OpenIdConnectAuthenticateResponse> getResponseReader() {
30+
return OpenIdConnectAuthenticateResponse::new;
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
package org.elasticsearch.xpack.core.security.action.oidc;
7+
8+
import org.elasticsearch.action.ActionRequest;
9+
import org.elasticsearch.action.ActionRequestValidationException;
10+
import org.elasticsearch.common.io.stream.StreamInput;
11+
import org.elasticsearch.common.io.stream.StreamOutput;
12+
13+
import java.io.IOException;
14+
15+
/**
16+
* Represents a request for authentication using OpenID Connect
17+
*/
18+
public class OpenIdConnectAuthenticateRequest extends ActionRequest {
19+
20+
/**
21+
* The URI where the OP redirected the browser after the authentication attempt. This is passed as is from the
22+
* facilitator entity (i.e. Kibana)
23+
*/
24+
private String redirectUri;
25+
26+
/**
27+
* The state value that we generated for this specific flow and that should be stored at the user's session with
28+
* the facilitator
29+
*/
30+
private String state;
31+
32+
/**
33+
* The nonce value that we generated for this specific flow and that should be stored at the user's session with
34+
* the facilitator
35+
*/
36+
private String nonce;
37+
38+
public OpenIdConnectAuthenticateRequest() {
39+
40+
}
41+
42+
public OpenIdConnectAuthenticateRequest(StreamInput in) throws IOException {
43+
super.readFrom(in);
44+
redirectUri = in.readString();
45+
state = in.readString();
46+
nonce = in.readOptionalString();
47+
}
48+
49+
public String getRedirectUri() {
50+
return redirectUri;
51+
}
52+
53+
public void setRedirectUri(String redirectUri) {
54+
this.redirectUri = redirectUri;
55+
}
56+
57+
public String getState() {
58+
return state;
59+
}
60+
61+
public void setState(String state) {
62+
this.state = state;
63+
}
64+
65+
public String getNonce() {
66+
return nonce;
67+
}
68+
69+
public void setNonce(String nonce) {
70+
this.nonce = nonce;
71+
}
72+
73+
@Override
74+
public ActionRequestValidationException validate() {
75+
return null;
76+
}
77+
78+
@Override
79+
public void writeTo(StreamOutput out) throws IOException {
80+
super.writeTo(out);
81+
out.writeString(redirectUri);
82+
out.writeString(state);
83+
out.writeOptionalString(nonce);
84+
}
85+
86+
@Override
87+
public void readFrom(StreamInput in) {
88+
throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable");
89+
}
90+
91+
public String toString() {
92+
return "{redirectUri=" + redirectUri + ", state=" + state + ", nonce=" + nonce + "}";
93+
}
94+
}
95+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
package org.elasticsearch.xpack.core.security.action.oidc;
7+
8+
import org.elasticsearch.action.ActionRequestBuilder;
9+
import org.elasticsearch.client.ElasticsearchClient;
10+
11+
/**
12+
* Request builder for populating a {@link OpenIdConnectAuthenticateRequest}
13+
*/
14+
public class OpenIdConnectAuthenticateRequestBuilder
15+
extends ActionRequestBuilder<OpenIdConnectAuthenticateRequest, OpenIdConnectAuthenticateResponse> {
16+
17+
public OpenIdConnectAuthenticateRequestBuilder(ElasticsearchClient client) {
18+
super(client, OpenIdConnectAuthenticateAction.INSTANCE, new OpenIdConnectAuthenticateRequest());
19+
}
20+
21+
public OpenIdConnectAuthenticateRequestBuilder redirectUri(String redirectUri) {
22+
request.setRedirectUri(redirectUri);
23+
return this;
24+
}
25+
26+
public OpenIdConnectAuthenticateRequestBuilder state(String state) {
27+
request.setState(state);
28+
return this;
29+
}
30+
31+
public OpenIdConnectAuthenticateRequestBuilder nonce(String nonce) {
32+
request.setNonce(nonce);
33+
return this;
34+
}
35+
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
package org.elasticsearch.xpack.core.security.action.oidc;
7+
8+
import org.elasticsearch.action.ActionResponse;
9+
import org.elasticsearch.common.io.stream.StreamInput;
10+
import org.elasticsearch.common.io.stream.StreamOutput;
11+
import org.elasticsearch.common.unit.TimeValue;
12+
13+
import java.io.IOException;
14+
15+
public class OpenIdConnectAuthenticateResponse extends ActionResponse {
16+
private String principal;
17+
private String accessTokenString;
18+
private String refreshTokenString;
19+
private TimeValue expiresIn;
20+
21+
public OpenIdConnectAuthenticateResponse(String principal, String accessTokenString, String refreshTokenString, TimeValue expiresIn) {
22+
this.principal = principal;
23+
this.accessTokenString = accessTokenString;
24+
this.refreshTokenString = refreshTokenString;
25+
this.expiresIn = expiresIn;
26+
}
27+
28+
public OpenIdConnectAuthenticateResponse(StreamInput in) throws IOException {
29+
super.readFrom(in);
30+
principal = in.readString();
31+
accessTokenString = in.readString();
32+
refreshTokenString = in.readString();
33+
expiresIn = in.readTimeValue();
34+
}
35+
36+
public String getPrincipal() {
37+
return principal;
38+
}
39+
40+
public String getAccessTokenString() {
41+
return accessTokenString;
42+
}
43+
44+
public String getRefreshTokenString() {
45+
return refreshTokenString;
46+
}
47+
48+
public TimeValue getExpiresIn() {
49+
return expiresIn;
50+
}
51+
52+
@Override
53+
public void readFrom(StreamInput in) {
54+
throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable");
55+
}
56+
57+
@Override
58+
public void writeTo(StreamOutput out) throws IOException {
59+
super.writeTo(out);
60+
out.writeString(principal);
61+
out.writeString(accessTokenString);
62+
out.writeString(refreshTokenString);
63+
out.writeTimeValue(expiresIn);
64+
}
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
package org.elasticsearch.xpack.core.security.action.oidc;
7+
8+
import org.elasticsearch.action.Action;
9+
import org.elasticsearch.common.io.stream.Writeable;
10+
11+
public class OpenIdConnectPrepareAuthenticationAction extends Action<OpenIdConnectPrepareAuthenticationResponse> {
12+
13+
public static final OpenIdConnectPrepareAuthenticationAction INSTANCE = new OpenIdConnectPrepareAuthenticationAction();
14+
public static final String NAME = "cluster:admin/xpack/security/oidc/prepare";
15+
16+
private OpenIdConnectPrepareAuthenticationAction() {
17+
super(NAME);
18+
}
19+
20+
@Override
21+
public OpenIdConnectPrepareAuthenticationResponse newResponse() {
22+
throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable");
23+
}
24+
25+
@Override
26+
public Writeable.Reader<OpenIdConnectPrepareAuthenticationResponse> getResponseReader() {
27+
return OpenIdConnectPrepareAuthenticationResponse::new;
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
package org.elasticsearch.xpack.core.security.action.oidc;
7+
8+
import org.elasticsearch.action.ActionRequest;
9+
import org.elasticsearch.action.ActionRequestValidationException;
10+
import org.elasticsearch.common.Strings;
11+
import org.elasticsearch.common.io.stream.StreamInput;
12+
import org.elasticsearch.common.io.stream.StreamOutput;
13+
14+
import java.io.IOException;
15+
16+
import static org.elasticsearch.action.ValidateActions.addValidationError;
17+
18+
/**
19+
* Represents a request to prepare an OAuth 2.0 authorization request
20+
*/
21+
public class OpenIdConnectPrepareAuthenticationRequest extends ActionRequest {
22+
23+
private String realmName;
24+
25+
public String getRealmName() {
26+
return realmName;
27+
}
28+
29+
public void setRealmName(String realmName) {
30+
this.realmName = realmName;
31+
}
32+
33+
public OpenIdConnectPrepareAuthenticationRequest() {
34+
}
35+
36+
public OpenIdConnectPrepareAuthenticationRequest(StreamInput in) throws IOException {
37+
super.readFrom(in);
38+
realmName = in.readString();
39+
}
40+
41+
@Override
42+
public ActionRequestValidationException validate() {
43+
ActionRequestValidationException validationException = null;
44+
if (Strings.hasText(realmName) == false) {
45+
validationException = addValidationError("realm name must be provided", null);
46+
}
47+
return validationException;
48+
}
49+
50+
@Override
51+
public void writeTo(StreamOutput out) throws IOException {
52+
super.writeTo(out);
53+
out.writeString(realmName);
54+
}
55+
56+
@Override
57+
public void readFrom(StreamInput in) {
58+
throw new UnsupportedOperationException("usage of Streamable is to be replaced by Writeable");
59+
}
60+
61+
public String toString() {
62+
return "{realmName=" + realmName + "}";
63+
}
64+
65+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License;
4+
* you may not use this file except in compliance with the Elastic License.
5+
*/
6+
package org.elasticsearch.xpack.core.security.action.oidc;
7+
8+
import org.elasticsearch.action.ActionRequestBuilder;
9+
import org.elasticsearch.client.ElasticsearchClient;
10+
11+
/**
12+
* Request builder for populating a {@link OpenIdConnectPrepareAuthenticationRequest}
13+
*/
14+
public class OpenIdConnectPrepareAuthenticationRequestBuilder
15+
extends ActionRequestBuilder<OpenIdConnectPrepareAuthenticationRequest, OpenIdConnectPrepareAuthenticationResponse> {
16+
17+
public OpenIdConnectPrepareAuthenticationRequestBuilder(ElasticsearchClient client) {
18+
super(client, OpenIdConnectPrepareAuthenticationAction.INSTANCE, new OpenIdConnectPrepareAuthenticationRequest());
19+
}
20+
21+
public OpenIdConnectPrepareAuthenticationRequestBuilder realmName(String name) {
22+
request.setRealmName(name);
23+
return this;
24+
}
25+
}

0 commit comments

Comments
 (0)