Skip to content

Commit

Permalink
Fix credentials encoding for OIDC token request (#43808)
Browse files Browse the repository at this point in the history
As defined in https://tools.ietf.org/html/rfc6749#section-2.3.1
both client id and client secret need to be encoded with the
application/x-www-form-urlencoded encoding algorithm when used as
credentials for HTTP Basic Authentication in requests to the OP.

Resolves #43709
  • Loading branch information
jkakavas committed Jul 2, 2019
1 parent 4cdb24b commit 4ea17b7
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;

import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
Expand Down Expand Up @@ -465,8 +467,9 @@ private void exchangeCodeForToken(AuthorizationCode code, ActionListener<Tuple<A
}
httpPost.setEntity(new UrlEncodedFormEntity(params));
httpPost.setHeader("Content-type", "application/x-www-form-urlencoded");
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(rpConfig.getClientId().getValue(),
rpConfig.getClientSecret().toString());
UsernamePasswordCredentials creds =
new UsernamePasswordCredentials(URLEncoder.encode(rpConfig.getClientId().getValue(), StandardCharsets.UTF_8),
URLEncoder.encode(rpConfig.getClientSecret().toString(), StandardCharsets.UTF_8));
httpPost.addHeader(new BasicScheme().authenticate(creds, httpPost, null));
SpecialPermission.check();
AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
Expand Down
2 changes: 1 addition & 1 deletion x-pack/qa/oidc-op-tests/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ testClusters.integTest {
setting 'xpack.security.authc.realms.oidc.c2id.op.userinfo_endpoint', { "http://127.0.0.1:${ephemeralPort}/c2id/userinfo" }
setting 'xpack.security.authc.realms.oidc.c2id.op.jwkset_path', 'op-jwks.json'
setting 'xpack.security.authc.realms.oidc.c2id.rp.redirect_uri', 'https://my.fantastic.rp/cb'
setting 'xpack.security.authc.realms.oidc.c2id.rp.client_id', 'elasticsearch-rp'
setting 'xpack.security.authc.realms.oidc.c2id.rp.client_id', 'https://my.elasticsearch.org/rp'
keystore 'xpack.security.authc.realms.oidc.c2id.rp.client_secret', 'b07efb7a1cf6ec9462afe7b6d3ab55c6c7880262aa61ac28dded292aca47c9a2'
setting 'xpack.security.authc.realms.oidc.c2id.rp.response_type', 'code'
setting 'xpack.security.authc.realms.oidc.c2id.claims.principal', 'sub'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,23 +76,38 @@ public void setupUserAndRoles() throws IOException {
* C2id server only supports dynamic registration, so we can't pre-seed it's config with our client data. Execute only once
*/
@BeforeClass
public static void registerClient() throws Exception {
public static void registerClients() throws Exception {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
HttpPost httpPost = new HttpPost(REGISTRATION_URL);
final BasicHttpContext context = new BasicHttpContext();
String json = "{" +
"\"grant_types\": [\"implicit\", \"authorization_code\"]," +
"\"response_types\": [\"code\", \"token id_token\"]," +
String codeClient = "{" +
"\"grant_types\": [\"authorization_code\"]," +
"\"response_types\": [\"code\"]," +
"\"preferred_client_id\":\"https://my.elasticsearch.org/rp\"," +
"\"preferred_client_secret\":\"b07efb7a1cf6ec9462afe7b6d3ab55c6c7880262aa61ac28dded292aca47c9a2\"," +
"\"redirect_uris\": [\"https://my.fantastic.rp/cb\"]" +
"}";
String implicitClient = "{" +
"\"grant_types\": [\"implicit\"]," +
"\"response_types\": [\"token id_token\"]," +
"\"preferred_client_id\":\"elasticsearch-rp\"," +
"\"preferred_client_secret\":\"b07efb7a1cf6ec9462afe7b6d3ab55c6c7880262aa61ac28dded292aca47c9a2\"," +
"\"redirect_uris\": [\"https://my.fantastic.rp/cb\"]" +
"}";
httpPost.setEntity(new StringEntity(json, ContentType.APPLICATION_JSON));
HttpPost httpPost = new HttpPost(REGISTRATION_URL);
final BasicHttpContext context = new BasicHttpContext();
httpPost.setEntity(new StringEntity(codeClient, ContentType.APPLICATION_JSON));
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
httpPost.setHeader("Authorization", "Bearer 811fa888f3e0fdc9e01d4201bfeee46a");
CloseableHttpResponse response = SocketAccess.doPrivileged(() -> httpClient.execute(httpPost, context));
assertThat(response.getStatusLine().getStatusCode(), equalTo(200));
httpPost.setEntity(new StringEntity(implicitClient, ContentType.APPLICATION_JSON));
HttpPost httpPost2 = new HttpPost(REGISTRATION_URL);
httpPost2.setEntity(new StringEntity(implicitClient, ContentType.APPLICATION_JSON));
httpPost2.setHeader("Accept", "application/json");
httpPost2.setHeader("Content-type", "application/json");
httpPost2.setHeader("Authorization", "Bearer 811fa888f3e0fdc9e01d4201bfeee46a");
CloseableHttpResponse response2 = SocketAccess.doPrivileged(() -> httpClient.execute(httpPost2, context));
assertThat(response2.getStatusLine().getStatusCode(), equalTo(200));
}
}

Expand Down

0 comments on commit 4ea17b7

Please sign in to comment.