Issue #7042 - if only 1 OpenIdConfig available select it regardless of realm name
Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
parent
f12d6f5b6c
commit
2a3c65c164
|
@ -20,7 +20,7 @@ etc/jetty-openid.xml
|
|||
|
||||
[ini-template]
|
||||
## The OpenID Identity Provider's issuer ID (the entire URL *before* ".well-known/openid-configuration")
|
||||
# jetty.openid.provider=https://id.example.com/~
|
||||
# jetty.openid.provider=https://id.example.com/
|
||||
|
||||
## The OpenID Identity Provider's authorization endpoint (optional if the metadata of the OP is accessible)
|
||||
# jetty.openid.provider.authorizationEndpoint=https://id.example.com/authorization
|
||||
|
|
|
@ -13,17 +13,23 @@
|
|||
|
||||
package org.eclipse.jetty.security.openid;
|
||||
|
||||
import org.eclipse.jetty.security.Authenticator;
|
||||
import org.eclipse.jetty.security.Authenticator.AuthConfiguration;
|
||||
import org.eclipse.jetty.security.LoginService;
|
||||
import org.eclipse.jetty.security.WrappedAuthConfiguration;
|
||||
|
||||
/**
|
||||
* <p>This class is used to wrap the {@link AuthConfiguration} given to the {@link OpenIdAuthenticator}.</p>
|
||||
* <p>When {@link #getLoginService()} method is called, this implementation will always return an instance of
|
||||
* {@link OpenIdLoginService}. This allows you to configure an {@link OpenIdAuthenticator} using a {@code null}
|
||||
* LoginService or any alternative LoginService implementation which will be wrapped by the OpenIdLoginService</p>
|
||||
*/
|
||||
public class OpenIdAuthConfiguration extends WrappedAuthConfiguration
|
||||
{
|
||||
public static final String AUTHENTICATE_NEW_USERS_INIT_PARAM = "jetty.openid.authenticateNewUsers";
|
||||
|
||||
private final OpenIdLoginService _openIdLoginService;
|
||||
|
||||
public OpenIdAuthConfiguration(OpenIdConfiguration openIdConfiguration, Authenticator.AuthConfiguration authConfiguration)
|
||||
public OpenIdAuthConfiguration(OpenIdConfiguration openIdConfiguration, AuthConfiguration authConfiguration)
|
||||
{
|
||||
super(authConfiguration);
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
package org.eclipse.jetty.security.openid;
|
||||
|
||||
import java.util.Collection;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.eclipse.jetty.security.Authenticator;
|
||||
|
@ -34,8 +35,17 @@ public class OpenIdAuthenticatorFactory implements Authenticator.Factory
|
|||
return new OpenIdAuthenticator(((OpenIdLoginService)loginService).getConfiguration());
|
||||
|
||||
// Otherwise we should find an OpenIdConfiguration for this realm on the Server.
|
||||
Collection<OpenIdConfiguration> configurations = server.getBeans(OpenIdConfiguration.class);
|
||||
if (configurations == null || configurations.isEmpty())
|
||||
throw new IllegalStateException("No OpenIdConfiguration found");
|
||||
|
||||
// If only 1 configuration use that regardless of its realm name.
|
||||
if (configurations.size() == 1)
|
||||
return new OpenIdAuthenticator(configurations.iterator().next());
|
||||
|
||||
// If there are multiple configurations then select one matching the realm name.
|
||||
String realmName = configuration.getRealmName();
|
||||
OpenIdConfiguration openIdConfiguration = server.getBeans(OpenIdConfiguration.class).stream()
|
||||
OpenIdConfiguration openIdConfiguration = configurations.stream()
|
||||
.filter(c -> c.getIssuer().equals(realmName))
|
||||
.findAny()
|
||||
.orElseThrow(() -> new IllegalStateException("No OpenIdConfiguration found for realm \"" + realmName + "\""));
|
||||
|
|
|
@ -0,0 +1,184 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2021 Mort Bay Consulting Pty Ltd and others.
|
||||
//
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License v. 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
|
||||
// which is available at https://www.apache.org/licenses/LICENSE-2.0.
|
||||
//
|
||||
// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.security.openid;
|
||||
|
||||
import org.eclipse.jetty.security.Authenticator;
|
||||
import org.eclipse.jetty.security.ConstraintSecurityHandler;
|
||||
import org.eclipse.jetty.security.LoginService;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.util.security.Constraint;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
public class OpenIdReamNameTest
|
||||
{
|
||||
private final Server server = new Server();
|
||||
|
||||
public static ServletContextHandler configureOpenIdContext(String realmName)
|
||||
{
|
||||
ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
|
||||
assertThat(securityHandler.getKnownAuthenticatorFactories().size(), greaterThanOrEqualTo(2));
|
||||
securityHandler.setAuthMethod(Constraint.__OPENID_AUTH);
|
||||
securityHandler.setRealmName(realmName);
|
||||
ServletContextHandler context = new ServletContextHandler();
|
||||
context.setContextPath("/" + realmName);
|
||||
context.setSecurityHandler(securityHandler);
|
||||
return context;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleConfiguration() throws Exception
|
||||
{
|
||||
// Add some OpenID configurations.
|
||||
OpenIdConfiguration config1 = new OpenIdConfiguration("provider1",
|
||||
"", "", "", "", null);
|
||||
server.addBean(config1);
|
||||
|
||||
// Configure two webapps to select configs based on realm name.
|
||||
ServletContextHandler context1 = configureOpenIdContext("This doesn't matter if only 1 OpenIdConfiguration");
|
||||
ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection();
|
||||
contextHandlerCollection.addHandler(context1);
|
||||
server.setHandler(contextHandlerCollection);
|
||||
|
||||
try
|
||||
{
|
||||
server.start();
|
||||
|
||||
// The OpenIdConfiguration from context1 matches to config1.
|
||||
Authenticator authenticator = context1.getSecurityHandler().getAuthenticator();
|
||||
assertThat(authenticator, instanceOf(OpenIdAuthenticator.class));
|
||||
LoginService loginService = ((OpenIdAuthenticator)authenticator).getLoginService();
|
||||
assertThat(loginService, instanceOf(OpenIdLoginService.class));
|
||||
assertThat(((OpenIdLoginService)loginService).getConfiguration(), is(config1));
|
||||
}
|
||||
finally
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleConfigurationNoRealmName() throws Exception
|
||||
{
|
||||
// Add some OpenID configurations.
|
||||
OpenIdConfiguration config1 = new OpenIdConfiguration("provider1",
|
||||
"", "", "", "", null);
|
||||
server.addBean(config1);
|
||||
|
||||
// Configure two webapps to select configs based on realm name.
|
||||
ServletContextHandler context1 = configureOpenIdContext(null);
|
||||
ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection();
|
||||
contextHandlerCollection.addHandler(context1);
|
||||
server.setHandler(contextHandlerCollection);
|
||||
|
||||
try
|
||||
{
|
||||
server.start();
|
||||
|
||||
// The OpenIdConfiguration from context1 matches to config1.
|
||||
Authenticator authenticator = context1.getSecurityHandler().getAuthenticator();
|
||||
assertThat(authenticator, instanceOf(OpenIdAuthenticator.class));
|
||||
LoginService loginService = ((OpenIdAuthenticator)authenticator).getLoginService();
|
||||
assertThat(loginService, instanceOf(OpenIdLoginService.class));
|
||||
assertThat(((OpenIdLoginService)loginService).getConfiguration(), is(config1));
|
||||
}
|
||||
finally
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleConfiguration() throws Exception
|
||||
{
|
||||
// Add some OpenID configurations.
|
||||
OpenIdConfiguration config1 = new OpenIdConfiguration("provider1",
|
||||
"", "", "", "", null);
|
||||
OpenIdConfiguration config2 = new OpenIdConfiguration("provider2",
|
||||
"", "", "", "", null);
|
||||
server.addBean(config1);
|
||||
server.addBean(config2);
|
||||
|
||||
// Configure two webapps to select configs based on realm name.
|
||||
ServletContextHandler context1 = configureOpenIdContext(config1.getIssuer());
|
||||
ServletContextHandler context2 = configureOpenIdContext(config2.getIssuer());
|
||||
ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection();
|
||||
contextHandlerCollection.addHandler(context1);
|
||||
contextHandlerCollection.addHandler(context2);
|
||||
server.setHandler(contextHandlerCollection);
|
||||
|
||||
try
|
||||
{
|
||||
server.start();
|
||||
|
||||
// The OpenIdConfiguration from context1 matches to config1.
|
||||
Authenticator authenticator = context1.getSecurityHandler().getAuthenticator();
|
||||
assertThat(authenticator, instanceOf(OpenIdAuthenticator.class));
|
||||
LoginService loginService = ((OpenIdAuthenticator)authenticator).getLoginService();
|
||||
assertThat(loginService, instanceOf(OpenIdLoginService.class));
|
||||
assertThat(((OpenIdLoginService)loginService).getConfiguration(), is(config1));
|
||||
|
||||
// The OpenIdConfiguration from context2 matches to config2.
|
||||
authenticator = context2.getSecurityHandler().getAuthenticator();
|
||||
assertThat(authenticator, instanceOf(OpenIdAuthenticator.class));
|
||||
loginService = ((OpenIdAuthenticator)authenticator).getLoginService();
|
||||
assertThat(loginService, instanceOf(OpenIdLoginService.class));
|
||||
assertThat(((OpenIdLoginService)loginService).getConfiguration(), is(config2));
|
||||
}
|
||||
finally
|
||||
{
|
||||
server.stop();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMultipleConfigurationNoMatch() throws Exception
|
||||
{
|
||||
// Add some OpenID configurations.
|
||||
OpenIdConfiguration config1 = new OpenIdConfiguration("provider1",
|
||||
"", "", "", "", null);
|
||||
OpenIdConfiguration config2 = new OpenIdConfiguration("provider2",
|
||||
"", "", "", "", null);
|
||||
server.addBean(config1);
|
||||
server.addBean(config2);
|
||||
|
||||
// Configure two webapps to select configs based on realm name.
|
||||
ServletContextHandler context1 = configureOpenIdContext("provider3");
|
||||
ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection();
|
||||
contextHandlerCollection.addHandler(context1);
|
||||
server.setHandler(contextHandlerCollection);
|
||||
|
||||
// Multiple OpenIdConfigurations were available and didn't match one based on realm name.
|
||||
assertThrows(IllegalStateException.class, server::start);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoConfiguration() throws Exception
|
||||
{
|
||||
ServletContextHandler context1 = configureOpenIdContext(null);
|
||||
ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection();
|
||||
contextHandlerCollection.addHandler(context1);
|
||||
server.setHandler(contextHandlerCollection);
|
||||
|
||||
// If no OpenIdConfigurations are present it is bad configuration.
|
||||
assertThrows(IllegalStateException.class, server::start);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue