Merge pull request #6643 from eclipse/jetty-9.4.x-6617-openidBasicAuth

Issue #6617 - add support for the client_secret_basic authentication method (jetty-9.4)
This commit is contained in:
Lachlan 2021-08-19 16:18:55 +10:00 committed by GitHub
commit 3de9d3428e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 8 deletions

View File

@ -16,6 +16,7 @@
<Arg><Property name="jetty.openid.provider.tokenEndpoint"/></Arg>
<Arg><Property name="jetty.openid.clientId"/></Arg>
<Arg><Property name="jetty.openid.clientSecret"/></Arg>
<Arg><Property name="jetty.openid.authMethod" default="client_secret_post"/></Arg>
<Arg><Ref refid="HttpClient"/></Arg>
<Call name="addScopes">
<Arg>

View File

@ -1,7 +1,7 @@
# DO NOT EDIT - See: https://www.eclipse.org/jetty/documentation/current/startup-modules.html
[description]
Adds OpenId Connect authentication.
Adds OpenId Connect authentication to the server.
[depend]
security
@ -42,3 +42,6 @@ etc/jetty-openid.xml
## True if all certificates should be trusted by the default SslContextFactory
# jetty.openid.sslContextFactory.trustAll=false
## What authentication method to use with the Token Endpoint (client_secret_post, client_secret_basic).
# jetty.openid.authMethod=client_secret_post

View File

@ -48,6 +48,7 @@ public class OpenIdConfiguration extends ContainerLifeCycle
private final String clientId;
private final String clientSecret;
private final List<String> scopes = new ArrayList<>();
private final String authMethod;
private String authEndpoint;
private String tokenEndpoint;
@ -73,6 +74,22 @@ public class OpenIdConfiguration extends ContainerLifeCycle
*/
public OpenIdConfiguration(String issuer, String authorizationEndpoint, String tokenEndpoint,
String clientId, String clientSecret, HttpClient httpClient)
{
this(issuer, authorizationEndpoint, tokenEndpoint, clientId, clientSecret, "client_secret_post", httpClient);
}
/**
* Create an OpenID configuration for a specific OIDC provider.
* @param issuer The URL of the OpenID provider.
* @param authorizationEndpoint the URL of the OpenID provider's authorization endpoint if configured.
* @param tokenEndpoint the URL of the OpenID provider's token endpoint if configured.
* @param clientId OAuth 2.0 Client Identifier valid at the Authorization Server.
* @param clientSecret The client secret known only by the Client and the Authorization Server.
* @param authMethod Authentication method to use with the Token Endpoint.
* @param httpClient The {@link HttpClient} instance to use.
*/
public OpenIdConfiguration(String issuer, String authorizationEndpoint, String tokenEndpoint,
String clientId, String clientSecret, String authMethod, HttpClient httpClient)
{
this.issuer = issuer;
this.clientId = clientId;
@ -80,6 +97,7 @@ public class OpenIdConfiguration extends ContainerLifeCycle
this.authEndpoint = authorizationEndpoint;
this.tokenEndpoint = tokenEndpoint;
this.httpClient = httpClient != null ? httpClient : newHttpClient();
this.authMethod = authMethod;
if (this.issuer == null)
throw new IllegalArgumentException("Issuer was not configured");
@ -179,6 +197,11 @@ public class OpenIdConfiguration extends ContainerLifeCycle
return tokenEndpoint;
}
public String getAuthMethod()
{
return authMethod;
}
public void addScopes(String... scopes)
{
if (scopes != null)

View File

@ -19,13 +19,16 @@
package org.eclipse.jetty.security.openid;
import java.io.Serializable;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.client.api.Authentication;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.util.BasicAuthentication;
import org.eclipse.jetty.client.util.FormContentProvider;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.ajax.JSON;
@ -173,14 +176,27 @@ public class OpenIdCredentials implements Serializable
{
Fields fields = new Fields();
fields.add("code", authCode);
fields.add("client_id", configuration.getClientId());
fields.add("client_secret", configuration.getClientSecret());
fields.add("redirect_uri", redirectUri);
fields.add("grant_type", "authorization_code");
FormContentProvider formContentProvider = new FormContentProvider(fields);
Request request = configuration.getHttpClient().POST(configuration.getTokenEndpoint())
.content(formContentProvider)
.timeout(10, TimeUnit.SECONDS);
Request request = configuration.getHttpClient().POST(configuration.getTokenEndpoint());
switch (configuration.getAuthMethod())
{
case "client_secret_basic":
URI uri = URI.create(configuration.getTokenEndpoint());
Authentication.Result authentication = new BasicAuthentication.BasicResult(uri, configuration.getClientId(), configuration.getClientSecret());
authentication.apply(request);
break;
case "client_secret_post":
fields.add("client_id", configuration.getClientId());
fields.add("client_secret", configuration.getClientSecret());
break;
default:
throw new IllegalStateException(configuration.getAuthMethod());
}
FormContentProvider formContent = new FormContentProvider(fields);
request = request.content(formContent).timeout(10, TimeUnit.SECONDS);
ContentResponse response = request.send();
String responseBody = response.getContentAsString();
if (LOG.isDebugEnabled())