Merge pull request #7546 from eclipse/jetty-10.0.x-7545-OpenIdXML
Add distribution test for OpenID and fix issues with jetty-openid.xml
This commit is contained in:
commit
0f5824640a
|
@ -24,6 +24,7 @@ import org.eclipse.jetty.client.HttpClient;
|
|||
import org.eclipse.jetty.client.http.HttpClientTransportOverHTTP;
|
||||
import org.eclipse.jetty.io.ClientConnector;
|
||||
import org.eclipse.jetty.util.ajax.JSON;
|
||||
import org.eclipse.jetty.util.annotation.Name;
|
||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -86,8 +87,13 @@ public class OpenIdConfiguration extends ContainerLifeCycle
|
|||
* @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)
|
||||
public OpenIdConfiguration(@Name("issuer") String issuer,
|
||||
@Name("authorizationEndpoint") String authorizationEndpoint,
|
||||
@Name("tokenEndpoint") String tokenEndpoint,
|
||||
@Name("clientId") String clientId,
|
||||
@Name("clientSecret") String clientSecret,
|
||||
@Name("authMethod") String authMethod,
|
||||
@Name("httpClient") HttpClient httpClient)
|
||||
{
|
||||
this.issuer = issuer;
|
||||
this.clientId = clientId;
|
||||
|
|
|
@ -149,6 +149,11 @@
|
|||
<artifactId>websocket-jetty-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-openid</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.tests</groupId>
|
||||
<artifactId>test-felix-webapp</artifactId>
|
||||
|
|
|
@ -41,6 +41,7 @@ import org.eclipse.jetty.http3.client.HTTP3Client;
|
|||
import org.eclipse.jetty.http3.client.http.HttpClientTransportOverHTTP3;
|
||||
import org.eclipse.jetty.io.ClientConnector;
|
||||
import org.eclipse.jetty.start.FS;
|
||||
import org.eclipse.jetty.tests.distribution.openid.OpenIdProvider;
|
||||
import org.eclipse.jetty.toolchain.test.PathAssert;
|
||||
import org.eclipse.jetty.unixsocket.client.HttpClientTransportOverUnixSockets;
|
||||
import org.eclipse.jetty.unixsocket.server.UnixSocketConnector;
|
||||
|
@ -1143,4 +1144,89 @@ public class DistributionTests extends AbstractJettyHomeTest
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOpenID() throws Exception
|
||||
{
|
||||
Path jettyBase = newTestJettyBaseDirectory();
|
||||
String jettyVersion = System.getProperty("jettyVersion");
|
||||
JettyHomeTester distribution = JettyHomeTester.Builder.newInstance()
|
||||
.jettyVersion(jettyVersion)
|
||||
.jettyBase(jettyBase)
|
||||
.mavenLocalRepository(System.getProperty("mavenRepoPath"))
|
||||
.build();
|
||||
|
||||
String[] args1 = {
|
||||
"--create-startd",
|
||||
"--approve-all-licenses",
|
||||
"--add-to-start=http,webapp,deploy,openid"
|
||||
};
|
||||
|
||||
String clientId = "clientId123";
|
||||
String clientSecret = "clientSecret456";
|
||||
OpenIdProvider openIdProvider = new OpenIdProvider(clientId, clientSecret);
|
||||
try (JettyHomeTester.Run run1 = distribution.start(args1))
|
||||
{
|
||||
assertTrue(run1.awaitFor(10, TimeUnit.SECONDS));
|
||||
assertEquals(0, run1.getExitValue());
|
||||
|
||||
File webApp = distribution.resolveArtifact("org.eclipse.jetty.tests:test-openid-webapp:war:" + jettyVersion);
|
||||
distribution.installWarFile(webApp, "test");
|
||||
|
||||
int port = distribution.freePort();
|
||||
openIdProvider.addRedirectUri("http://localhost:" + port + "/test/j_security_check");
|
||||
openIdProvider.start();
|
||||
String[] args2 = {
|
||||
"jetty.http.port=" + port,
|
||||
"jetty.ssl.port=" + port,
|
||||
"jetty.openid.provider=" + openIdProvider.getProvider(),
|
||||
"jetty.openid.clientId=" + clientId,
|
||||
"jetty.openid.clientSecret=" + clientSecret,
|
||||
//"jetty.server.dumpAfterStart=true",
|
||||
};
|
||||
|
||||
try (JettyHomeTester.Run run2 = distribution.start(args2))
|
||||
{
|
||||
assertTrue(run2.awaitConsoleLogsFor("Started Server@", 10, TimeUnit.SECONDS));
|
||||
startHttpClient(false);
|
||||
String uri = "http://localhost:" + port + "/test";
|
||||
openIdProvider.setUser(new OpenIdProvider.User("123456789", "Alice"));
|
||||
|
||||
// Initially not authenticated
|
||||
ContentResponse response = client.GET(uri + "/");
|
||||
assertThat(response.getStatus(), is(HttpStatus.OK_200));
|
||||
String content = response.getContentAsString();
|
||||
assertThat(content, containsString("not authenticated"));
|
||||
|
||||
// Request to login is success
|
||||
response = client.GET(uri + "/login");
|
||||
assertThat(response.getStatus(), is(HttpStatus.OK_200));
|
||||
content = response.getContentAsString();
|
||||
assertThat(content, containsString("success"));
|
||||
|
||||
// Now authenticated we can get info
|
||||
response = client.GET(uri + "/");
|
||||
assertThat(response.getStatus(), is(HttpStatus.OK_200));
|
||||
content = response.getContentAsString();
|
||||
assertThat(content, containsString("userId: 123456789"));
|
||||
assertThat(content, containsString("name: Alice"));
|
||||
assertThat(content, containsString("email: Alice@example.com"));
|
||||
|
||||
// Request to admin page gives 403 as we do not have admin role
|
||||
response = client.GET(uri + "/admin");
|
||||
assertThat(response.getStatus(), is(HttpStatus.FORBIDDEN_403));
|
||||
|
||||
// We are no longer authenticated after logging out
|
||||
response = client.GET(uri + "/logout");
|
||||
assertThat(response.getStatus(), is(HttpStatus.OK_200));
|
||||
content = response.getContentAsString();
|
||||
assertThat(content, containsString("not authenticated"));
|
||||
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
openIdProvider.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2022 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.tests.distribution.openid;
|
||||
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* A basic JWT encoder for testing purposes.
|
||||
*/
|
||||
public class JwtEncoder
|
||||
{
|
||||
private static final Base64.Encoder ENCODER = Base64.getUrlEncoder();
|
||||
private static final String DEFAULT_HEADER = "{\"INFO\": \"this is not used or checked in our implementation\"}";
|
||||
private static final String DEFAULT_SIGNATURE = "we do not validate signature as we use the authorization code flow";
|
||||
|
||||
public static String encode(String idToken)
|
||||
{
|
||||
return stripPadding(ENCODER.encodeToString(DEFAULT_HEADER.getBytes())) + "." +
|
||||
stripPadding(ENCODER.encodeToString(idToken.getBytes())) + "." +
|
||||
stripPadding(ENCODER.encodeToString(DEFAULT_SIGNATURE.getBytes()));
|
||||
}
|
||||
|
||||
private static String stripPadding(String paddedBase64)
|
||||
{
|
||||
return paddedBase64.split("=")[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a basic JWT for testing using argument supplied attributes.
|
||||
*/
|
||||
public static String createIdToken(String provider, String clientId, String subject, String name, long expiry)
|
||||
{
|
||||
return "{" +
|
||||
"\"iss\": \"" + provider + "\"," +
|
||||
"\"sub\": \"" + subject + "\"," +
|
||||
"\"aud\": \"" + clientId + "\"," +
|
||||
"\"exp\": " + expiry + "," +
|
||||
"\"name\": \"" + name + "\"," +
|
||||
"\"email\": \"" + name + "@example.com" + "\"" +
|
||||
"}";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,341 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2022 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.tests.distribution.openid;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.http.HttpVersion;
|
||||
import org.eclipse.jetty.security.openid.OpenIdConfiguration;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Response;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class OpenIdProvider extends ContainerLifeCycle
|
||||
{
|
||||
private static final Logger LOG = LoggerFactory.getLogger(OpenIdProvider.class);
|
||||
|
||||
private static final String CONFIG_PATH = "/.well-known/openid-configuration";
|
||||
private static final String AUTH_PATH = "/auth";
|
||||
private static final String TOKEN_PATH = "/token";
|
||||
private final Map<String, User> issuedAuthCodes = new HashMap<>();
|
||||
|
||||
protected final String clientId;
|
||||
protected final String clientSecret;
|
||||
protected final List<String> redirectUris = new ArrayList<>();
|
||||
private final ServerConnector connector;
|
||||
private final Server server;
|
||||
private int port = 0;
|
||||
private String provider;
|
||||
private User preAuthedUser;
|
||||
|
||||
public static void main(String[] args) throws Exception
|
||||
{
|
||||
String clientId = "CLIENT_ID123";
|
||||
String clientSecret = "PASSWORD123";
|
||||
int port = 5771;
|
||||
String redirectUri = "http://localhost:8080/openid/auth";
|
||||
|
||||
OpenIdProvider openIdProvider = new OpenIdProvider(clientId, clientSecret);
|
||||
openIdProvider.addRedirectUri(redirectUri);
|
||||
openIdProvider.setPort(port);
|
||||
openIdProvider.start();
|
||||
try
|
||||
{
|
||||
openIdProvider.join();
|
||||
}
|
||||
finally
|
||||
{
|
||||
openIdProvider.stop();
|
||||
}
|
||||
}
|
||||
|
||||
public OpenIdProvider(String clientId, String clientSecret)
|
||||
{
|
||||
this.clientId = clientId;
|
||||
this.clientSecret = clientSecret;
|
||||
|
||||
server = new Server();
|
||||
connector = new ServerConnector(server);
|
||||
server.addConnector(connector);
|
||||
|
||||
ServletContextHandler contextHandler = new ServletContextHandler();
|
||||
contextHandler.setContextPath("/");
|
||||
contextHandler.addServlet(new ServletHolder(new OpenIdConfigServlet()), CONFIG_PATH);
|
||||
contextHandler.addServlet(new ServletHolder(new OpenIdAuthEndpoint()), AUTH_PATH);
|
||||
contextHandler.addServlet(new ServletHolder(new OpenIdTokenEndpoint()), TOKEN_PATH);
|
||||
server.setHandler(contextHandler);
|
||||
|
||||
addBean(server);
|
||||
}
|
||||
|
||||
public void join() throws InterruptedException
|
||||
{
|
||||
server.join();
|
||||
}
|
||||
|
||||
public OpenIdConfiguration getOpenIdConfiguration()
|
||||
{
|
||||
String provider = getProvider();
|
||||
String authEndpoint = provider + AUTH_PATH;
|
||||
String tokenEndpoint = provider + TOKEN_PATH;
|
||||
return new OpenIdConfiguration(provider, authEndpoint, tokenEndpoint, clientId, clientSecret, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart() throws Exception
|
||||
{
|
||||
connector.setPort(port);
|
||||
super.doStart();
|
||||
provider = "http://localhost:" + connector.getLocalPort();
|
||||
}
|
||||
|
||||
public void setPort(int port)
|
||||
{
|
||||
if (isStarted())
|
||||
throw new IllegalStateException();
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public void setUser(User user)
|
||||
{
|
||||
this.preAuthedUser = user;
|
||||
}
|
||||
|
||||
public String getProvider()
|
||||
{
|
||||
if (!isStarted() && port == 0)
|
||||
throw new IllegalStateException("Port of OpenIdProvider not configured");
|
||||
return provider;
|
||||
}
|
||||
|
||||
public void addRedirectUri(String uri)
|
||||
{
|
||||
redirectUris.add(uri);
|
||||
}
|
||||
|
||||
public class OpenIdAuthEndpoint extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException
|
||||
{
|
||||
if (!clientId.equals(req.getParameter("client_id")))
|
||||
{
|
||||
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "invalid client_id");
|
||||
return;
|
||||
}
|
||||
|
||||
String redirectUri = req.getParameter("redirect_uri");
|
||||
if (!redirectUris.contains(redirectUri))
|
||||
{
|
||||
LOG.warn("invalid redirectUri {}", redirectUri);
|
||||
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "invalid redirect_uri");
|
||||
return;
|
||||
}
|
||||
|
||||
String scopeString = req.getParameter("scope");
|
||||
List<String> scopes = (scopeString == null) ? Collections.emptyList() : Arrays.asList(StringUtil.csvSplit(scopeString));
|
||||
if (!scopes.contains("openid"))
|
||||
{
|
||||
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "no openid scope");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!"code".equals(req.getParameter("response_type")))
|
||||
{
|
||||
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "response_type must be code");
|
||||
return;
|
||||
}
|
||||
|
||||
String state = req.getParameter("state");
|
||||
if (state == null)
|
||||
{
|
||||
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "no state param");
|
||||
return;
|
||||
}
|
||||
|
||||
if (preAuthedUser == null)
|
||||
{
|
||||
PrintWriter writer = resp.getWriter();
|
||||
resp.setContentType("text/html");
|
||||
writer.println("<h2>Login to OpenID Connect Provider</h2>");
|
||||
writer.println("<form action=\"" + AUTH_PATH + "\" method=\"post\">");
|
||||
writer.println("<input type=\"text\" autocomplete=\"off\" placeholder=\"Username\" name=\"username\" required>");
|
||||
writer.println("<input type=\"hidden\" name=\"redirectUri\" value=\"" + redirectUri + "\">");
|
||||
writer.println("<input type=\"hidden\" name=\"state\" value=\"" + state + "\">");
|
||||
writer.println("<input type=\"submit\">");
|
||||
writer.println("</form>");
|
||||
}
|
||||
else
|
||||
{
|
||||
redirectUser(req, preAuthedUser, redirectUri, state);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException
|
||||
{
|
||||
String redirectUri = req.getParameter("redirectUri");
|
||||
if (!redirectUris.contains(redirectUri))
|
||||
{
|
||||
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "invalid redirect_uri");
|
||||
return;
|
||||
}
|
||||
|
||||
String state = req.getParameter("state");
|
||||
if (state == null)
|
||||
{
|
||||
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "no state param");
|
||||
return;
|
||||
}
|
||||
|
||||
String username = req.getParameter("username");
|
||||
if (username == null)
|
||||
{
|
||||
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "no username");
|
||||
return;
|
||||
}
|
||||
|
||||
User user = new User(username);
|
||||
redirectUser(req, user, redirectUri, state);
|
||||
}
|
||||
|
||||
public void redirectUser(HttpServletRequest request, User user, String redirectUri, String state) throws IOException
|
||||
{
|
||||
String authCode = UUID.randomUUID().toString().replace("-", "");
|
||||
issuedAuthCodes.put(authCode, user);
|
||||
|
||||
try
|
||||
{
|
||||
final Request baseRequest = Objects.requireNonNull(Request.getBaseRequest(request));
|
||||
final Response baseResponse = baseRequest.getResponse();
|
||||
redirectUri += "?code=" + authCode + "&state=" + state;
|
||||
int redirectCode = (baseRequest.getHttpVersion().getVersion() < HttpVersion.HTTP_1_1.getVersion()
|
||||
? HttpServletResponse.SC_MOVED_TEMPORARILY : HttpServletResponse.SC_SEE_OTHER);
|
||||
baseResponse.sendRedirect(redirectCode, baseResponse.encodeRedirectURL(redirectUri));
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
issuedAuthCodes.remove(authCode);
|
||||
throw t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class OpenIdTokenEndpoint extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
|
||||
{
|
||||
String code = req.getParameter("code");
|
||||
|
||||
if (!clientId.equals(req.getParameter("client_id")) ||
|
||||
!clientSecret.equals(req.getParameter("client_secret")) ||
|
||||
!redirectUris.contains(req.getParameter("redirect_uri")) ||
|
||||
!"authorization_code".equals(req.getParameter("grant_type")) ||
|
||||
code == null)
|
||||
{
|
||||
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "bad auth request");
|
||||
return;
|
||||
}
|
||||
|
||||
User user = issuedAuthCodes.remove(code);
|
||||
if (user == null)
|
||||
{
|
||||
resp.sendError(HttpServletResponse.SC_FORBIDDEN, "invalid auth code");
|
||||
return;
|
||||
}
|
||||
|
||||
String accessToken = "ABCDEFG";
|
||||
long expiry = System.currentTimeMillis() + Duration.ofMinutes(10).toMillis();
|
||||
String response = "{" +
|
||||
"\"access_token\": \"" + accessToken + "\"," +
|
||||
"\"id_token\": \"" + JwtEncoder.encode(user.getIdToken(provider, clientId)) + "\"," +
|
||||
"\"expires_in\": " + expiry + "," +
|
||||
"\"token_type\": \"Bearer\"" +
|
||||
"}";
|
||||
|
||||
resp.setContentType("text/plain");
|
||||
resp.getWriter().print(response);
|
||||
}
|
||||
}
|
||||
|
||||
public class OpenIdConfigServlet extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException
|
||||
{
|
||||
String discoveryDocument = "{" +
|
||||
"\"issuer\": \"" + provider + "\"," +
|
||||
"\"authorization_endpoint\": \"" + provider + AUTH_PATH + "\"," +
|
||||
"\"token_endpoint\": \"" + provider + TOKEN_PATH + "\"," +
|
||||
"}";
|
||||
|
||||
resp.getWriter().write(discoveryDocument);
|
||||
}
|
||||
}
|
||||
|
||||
public static class User
|
||||
{
|
||||
private final String subject;
|
||||
private final String name;
|
||||
|
||||
public User(String name)
|
||||
{
|
||||
this(UUID.nameUUIDFromBytes(name.getBytes()).toString(), name);
|
||||
}
|
||||
|
||||
public User(String subject, String name)
|
||||
{
|
||||
this.subject = subject;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getSubject()
|
||||
{
|
||||
return subject;
|
||||
}
|
||||
|
||||
public String getIdToken(String provider, String clientId)
|
||||
{
|
||||
long expiry = System.currentTimeMillis() + Duration.ofMinutes(1).toMillis();
|
||||
return JwtEncoder.createIdToken(provider, clientId, subject, name, expiry);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -41,5 +41,6 @@
|
|||
<module>test-bad-websocket-webapp</module>
|
||||
<module>test-websocket-client-webapp</module>
|
||||
<module>test-websocket-client-provided-webapp</module>
|
||||
<module>test-openid-webapp</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>org.eclipse.jetty.tests</groupId>
|
||||
<artifactId>test-webapps-parent</artifactId>
|
||||
<version>10.0.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>test-openid-webapp</artifactId>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<name>Test :: Jetty OpenId Webapp</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.toolchain</groupId>
|
||||
<artifactId>jetty-servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -0,0 +1,31 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2022 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.test.openid;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class AdminPage extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> userInfo = (Map<String, Object>)request.getSession().getAttribute("org.eclipse.jetty.security.openid.claims");
|
||||
response.getWriter().println(userInfo.get("sub") + ": success");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2022 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.test.openid;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class ErrorPage extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
response.setContentType("text/html");
|
||||
response.getWriter().println("not authorized");
|
||||
response.getWriter().println("<br><a href=\"" + request.getContextPath() + "\">Home</a>");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2022 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.test.openid;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
import java.util.Map;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class HomePage extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
response.setContentType("text/html");
|
||||
Principal userPrincipal = request.getUserPrincipal();
|
||||
if (userPrincipal != null)
|
||||
{
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> userInfo = (Map<String, Object>)request.getSession().getAttribute("org.eclipse.jetty.security.openid.claims");
|
||||
response.getWriter().println("userId: " + userInfo.get("sub") + "<br>");
|
||||
response.getWriter().println("name: " + userInfo.get("name") + "<br>");
|
||||
response.getWriter().println("email: " + userInfo.get("email") + "<br>");
|
||||
response.getWriter().println("<br><a href=\"" + request.getContextPath() + "/logout\">Logout</a>");
|
||||
}
|
||||
else
|
||||
{
|
||||
response.getWriter().println("not authenticated");
|
||||
response.getWriter().println("<br><a href=\"" + request.getContextPath() + "/login\">Login</a>");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2022 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.test.openid;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class LoginPage extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
response.setContentType("text/html");
|
||||
response.getWriter().println("success");
|
||||
response.getWriter().println("<br><a href=\"" + request.getContextPath() + "\">Home</a>");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2022 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.test.openid;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
public class LogoutPage extends HttpServlet
|
||||
{
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException
|
||||
{
|
||||
request.getSession().invalidate();
|
||||
response.sendRedirect(request.getContextPath());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app
|
||||
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
|
||||
metadata-complete="false"
|
||||
version="3.1">
|
||||
|
||||
<login-config>
|
||||
<auth-method>OPENID</auth-method>
|
||||
</login-config>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>AdminPage</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.test.openid.AdminPage</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>AdminPage</servlet-name>
|
||||
<url-pattern>/admin</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>ErrorPage</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.test.openid.ErrorPage</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>ErrorPage</servlet-name>
|
||||
<url-pattern>/error</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>HomePage</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.test.openid.HomePage</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>HomePage</servlet-name>
|
||||
<url-pattern/>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>LoginPage</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.test.openid.LoginPage</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>LoginPage</servlet-name>
|
||||
<url-pattern>/login</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>LogoutPage</servlet-name>
|
||||
<servlet-class>org.eclipse.jetty.test.openid.LogoutPage</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>LogoutPage</servlet-name>
|
||||
<url-pattern>/logout</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<security-role>
|
||||
<role-name>admin</role-name>
|
||||
</security-role>
|
||||
<security-role>
|
||||
<role-name>**</role-name>
|
||||
</security-role>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>User Pages</web-resource-name>
|
||||
<url-pattern>/profile</url-pattern>
|
||||
<url-pattern>/login</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>**</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Admin Page</web-resource-name>
|
||||
<url-pattern>/admin</url-pattern>
|
||||
</web-resource-collection>
|
||||
<auth-constraint>
|
||||
<role-name>admin</role-name>
|
||||
</auth-constraint>
|
||||
</security-constraint>
|
||||
|
||||
</web-app>
|
Loading…
Reference in New Issue