Skip to content

Commit 073f35d

Browse files
committed
Fix WebPrincipal not serializable - tests
Add tests for Jakarta Security authentication - test for a custom principal - test for serialization of the internal securityContext, which is transferred across SSO instances Some refactoring - remove redundant empty lines from SimpleMultiRoleMappingTest - add an alternative to test HTTP resources with Java Http Client to GlassFishTestEnvironment
1 parent d132866 commit 073f35d

File tree

10 files changed

+379
-11
lines changed

10 files changed

+379
-11
lines changed

appserver/itest-tools/src/main/java/org/glassfish/main/itest/tools/GlassFishTestEnvironment.java

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, 2024 Eclipse Foundation and/or its affiliates.
2+
* Copyright (c) 2022, 2025 Eclipse Foundation and/or its affiliates.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -27,22 +27,35 @@
2727
import java.net.URI;
2828
import java.net.URISyntaxException;
2929
import java.net.URL;
30+
import java.net.http.HttpClient;
31+
import java.net.http.HttpRequest;
32+
import java.net.http.HttpResponse;
33+
import java.nio.charset.StandardCharsets;
3034
import java.nio.file.Files;
3135
import java.nio.file.Path;
3236
import java.nio.file.Paths;
3337
import java.nio.file.StandardOpenOption;
38+
import java.security.KeyManagementException;
3439
import java.security.KeyStore;
40+
import java.security.NoSuchAlgorithmException;
41+
import java.security.SecureRandom;
42+
import java.time.Duration;
3543
import java.util.Enumeration;
3644
import java.util.HashMap;
3745
import java.util.Locale;
3846
import java.util.logging.Level;
3947
import java.util.logging.Logger;
4048

49+
import javax.net.ssl.SSLContext;
50+
import javax.net.ssl.TrustManager;
51+
import javax.net.ssl.X509TrustManager;
52+
4153
import org.glassfish.admin.rest.client.ClientWrapper;
4254
import org.glassfish.main.itest.tools.asadmin.Asadmin;
4355
import org.glassfish.main.itest.tools.asadmin.AsadminResult;
4456
import org.glassfish.main.itest.tools.asadmin.StartServ;
4557

58+
import static java.net.http.HttpResponse.BodyHandlers.ofString;
4659
import static org.glassfish.main.itest.tools.asadmin.AsadminResultMatcher.asadminOK;
4760
import static org.hamcrest.MatcherAssert.assertThat;
4861

@@ -73,6 +86,7 @@ public class GlassFishTestEnvironment {
7386

7487
private static final int ASADMIN_START_DOMAIN_TIMEOUT = 30_000;
7588
private static final int ASADMIN_START_DOMAIN_TIMEOUT_FOR_DEBUG = 300_000;
89+
private static HttpClient client = null;
7690

7791
static {
7892
LOG.log(Level.INFO, "Using basedir: {0}", BASEDIR);
@@ -228,6 +242,26 @@ public static <T extends HttpURLConnection> T openConnection(final boolean secur
228242
return connection;
229243
}
230244

245+
/**
246+
* Creates a {@link HttpURLConnection} for the given port and context.
247+
*
248+
* @param secured true for https, false for http
249+
* @param port
250+
* @param context - part of the url behind the <code>http://localhost:[port]</code>
251+
* @return a new disconnected {@link HttpURLConnection}.
252+
* @throws IOException
253+
*/
254+
public static HttpResponse<String> getHttpResource(final boolean secured, final int port, final String context)
255+
throws Exception {
256+
final String protocol = secured ? "https" : "http";
257+
URI uri = URI.create(protocol + "://localhost:" + port + context);
258+
final HttpRequest request = HttpRequest.newBuilder(uri)
259+
.timeout(Duration.ofSeconds(15))
260+
.header("X-Requested-By", "JUnit5Test")
261+
.build();
262+
return newInsecureHttpClient().send(request, ofString(StandardCharsets.UTF_8));
263+
}
264+
231265
public static URI webSocketUri(final int port, final String context) throws URISyntaxException {
232266
return webSocketUri(false, port, context);
233267
}
@@ -415,4 +449,37 @@ private interface IOAction {
415449

416450
void execute() throws IOException;
417451
}
452+
453+
private static HttpClient newInsecureHttpClient() throws KeyManagementException, NoSuchAlgorithmException {
454+
if (client == null) {
455+
// Java 17 doesn't allow to close http client, so we reuse a global one.
456+
// Once we start using Java 21, client should be created for every call and returned instance should be closed
457+
SSLContext sslContext = SSLContext.getInstance("TLS");
458+
sslContext.init(null, trustAllCerts, new SecureRandom());
459+
client = HttpClient.newBuilder()
460+
.sslContext(sslContext)
461+
.connectTimeout(Duration.ofMillis(100))
462+
.build();
463+
}
464+
return client;
465+
}
466+
467+
private static final TrustManager[] trustAllCerts = new TrustManager[]{
468+
new X509TrustManager() {
469+
@Override
470+
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
471+
return null;
472+
}
473+
474+
@Override
475+
public void checkClientTrusted(
476+
java.security.cert.X509Certificate[] certs, String authType) {
477+
}
478+
479+
@Override
480+
public void checkServerTrusted(
481+
java.security.cert.X509Certificate[] certs, String authType) {
482+
}
483+
}
484+
};
418485
}

appserver/security/webintegration/src/main/java/com/sun/web/security/RealmAdapter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2021, 2024 Contributors to the Eclipse Foundation.
2+
* Copyright 2021, 2025 Contributors to the Eclipse Foundation.
33
* Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
44
*
55
* This program and the accompanying materials are made available under the

appserver/tests/application/pom.xml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!--
33
4-
Copyright (c) 2023, 2024 Contributors to the Eclipse Foundation. All rights reserved.
4+
Copyright (c) 2023, 2025 Contributors to the Eclipse Foundation. All rights reserved.
55
66
This program and the accompanying materials are made available under the
77
terms of the Eclipse Public License v. 2.0, which is available at
@@ -108,6 +108,11 @@
108108
<artifactId>jakarta.authentication-api</artifactId>
109109
<scope>provided</scope>
110110
</dependency>
111+
<dependency>
112+
<groupId>jakarta.security.enterprise</groupId>
113+
<artifactId>jakarta.security.enterprise-api</artifactId>
114+
<scope>provided</scope>
115+
</dependency>
111116
<dependency>
112117
<groupId>jakarta.xml.ws</groupId>
113118
<artifactId>jakarta.xml.ws-api</artifactId>
@@ -159,6 +164,12 @@
159164
<version>${project.version}</version>
160165
<scope>provided</scope>
161166
</dependency>
167+
<dependency>
168+
<groupId>org.glassfish.main.security</groupId>
169+
<artifactId>security</artifactId>
170+
<version>${project.version}</version>
171+
<scope>provided</scope>
172+
</dependency>
162173

163174
<dependency>
164175
<groupId>org.glassfish.tyrus</groupId>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (c) 2025 Contributors to the Eclipse Foundation
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0, which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the
10+
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11+
* version 2 with the GNU Classpath Exception, which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
*/
16+
17+
package org.glassfish.main.test.app.security.jakartasecurity;
18+
19+
import java.io.Serializable;
20+
import java.security.Principal;
21+
22+
public class CustomPrincipal implements Principal, Serializable {
23+
24+
private static final long serialVersionUID = 1L;
25+
private final String name;
26+
27+
public CustomPrincipal(String name) {
28+
this.name = name;
29+
}
30+
31+
@Override
32+
public String getName() {
33+
return name;
34+
}
35+
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
/*
2+
* Copyright (c) 2025 Contributors to the Eclipse Foundation
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0, which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the
10+
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11+
* version 2 with the GNU Classpath Exception, which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
*/
16+
17+
package org.glassfish.main.test.app.security.jakartasecurity;
18+
19+
import jakarta.annotation.security.DeclareRoles;
20+
import jakarta.inject.Inject;
21+
import jakarta.security.enterprise.SecurityContext;
22+
import jakarta.servlet.ServletException;
23+
import jakarta.servlet.annotation.WebServlet;
24+
import jakarta.servlet.http.HttpServlet;
25+
import jakarta.servlet.http.HttpServletRequest;
26+
import jakarta.servlet.http.HttpServletResponse;
27+
28+
import java.io.IOException;
29+
import java.security.Principal;
30+
31+
import static jakarta.security.enterprise.authentication.mechanism.http.AuthenticationParameters.withParams;
32+
33+
/**
34+
* Test Servlet that authenticates the request and returns
35+
* the class name of the caller principal
36+
*/
37+
@DeclareRoles("admin")
38+
@WebServlet("/customPrincipal")
39+
public class CustomPrincipalServlet extends HttpServlet {
40+
41+
private static final long serialVersionUID = 1L;
42+
43+
@Inject
44+
private SecurityContext securityContext;
45+
46+
@Override
47+
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
48+
securityContext.authenticate(request, response, withParams());
49+
50+
response.setContentType("text/plain");
51+
52+
final Principal callerPrincipal = securityContext.getCallerPrincipal();
53+
54+
response.getWriter().write(callerPrincipal.getClass().getName() + ",");
55+
Principal applicationPrincipal = securityContext.getPrincipalsByType(CustomPrincipal.class)
56+
.toArray(new CustomPrincipal[0])[0];
57+
58+
response.getWriter().write(applicationPrincipal.getClass().getName() + ": " + applicationPrincipal.getName());
59+
}
60+
61+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright (c) 2025 Contributors to the Eclipse Foundation
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0, which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the
10+
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11+
* version 2 with the GNU Classpath Exception, which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
*/
16+
17+
package org.glassfish.main.test.app.security.jakartasecurity;
18+
19+
import jakarta.annotation.security.DeclareRoles;
20+
import jakarta.inject.Inject;
21+
import jakarta.security.enterprise.SecurityContext;
22+
import jakarta.servlet.ServletException;
23+
import jakarta.servlet.annotation.WebServlet;
24+
import jakarta.servlet.http.HttpServlet;
25+
import jakarta.servlet.http.HttpServletRequest;
26+
import jakarta.servlet.http.HttpServletResponse;
27+
28+
import java.io.ByteArrayOutputStream;
29+
import java.io.IOException;
30+
import java.io.ObjectOutputStream;
31+
32+
import static jakarta.security.enterprise.authentication.mechanism.http.AuthenticationParameters.withParams;
33+
34+
/**
35+
* Test Servlet that authenticates that authenticates the request and verifies that GlassFish SecurityContext can be serialized
36+
*/
37+
@DeclareRoles("admin")
38+
@WebServlet("/serializableCoreSecurityContext")
39+
public class SerializableCoreSecurityContextServlet extends HttpServlet {
40+
41+
private static final long serialVersionUID = 1L;
42+
43+
@Inject
44+
private SecurityContext securityContext;
45+
46+
@Override
47+
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
48+
securityContext.authenticate(request, response, withParams());
49+
50+
response.setContentType("text/plain");
51+
52+
final ObjectOutputStream oos = new ObjectOutputStream(new ByteArrayOutputStream());
53+
54+
try {
55+
// verify internal core security context is serializable so that it can be used in SSO
56+
oos.writeObject(com.sun.enterprise.security.SecurityContext.getCurrent());
57+
} catch (Exception e) {
58+
response.setStatus(500);
59+
response.getWriter().write("Exception " + e);
60+
return;
61+
}
62+
63+
response.getWriter().write("OK");
64+
}
65+
66+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
* Copyright (c) 2025 Contributors to the Eclipse Foundation
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0, which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the
10+
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11+
* version 2 with the GNU Classpath Exception, which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
*/
16+
17+
package org.glassfish.main.test.app.security.jakartasecurity;
18+
19+
import jakarta.enterprise.context.ApplicationScoped;
20+
import jakarta.security.enterprise.AuthenticationException;
21+
import jakarta.security.enterprise.AuthenticationStatus;
22+
import jakarta.security.enterprise.authentication.mechanism.http.AutoApplySession;
23+
import jakarta.security.enterprise.authentication.mechanism.http.HttpAuthenticationMechanism;
24+
import jakarta.security.enterprise.authentication.mechanism.http.HttpMessageContext;
25+
import jakarta.servlet.http.HttpServletRequest;
26+
import jakarta.servlet.http.HttpServletResponse;
27+
28+
import static java.util.Collections.singleton;
29+
30+
@ApplicationScoped
31+
@AutoApplySession
32+
public class TestAuthenticationMechanism implements HttpAuthenticationMechanism {
33+
34+
@Override
35+
public AuthenticationStatus validateRequest(HttpServletRequest request, HttpServletResponse response, HttpMessageContext httpMessageContext) throws AuthenticationException {
36+
37+
httpMessageContext.notifyContainerAboutLogin(
38+
new CustomPrincipal("admin" + System.currentTimeMillis()),
39+
singleton("admin"));
40+
41+
return AuthenticationStatus.SUCCESS;
42+
}
43+
44+
}

0 commit comments

Comments
 (0)