From 49de954cc2109332ea3b96e8f7dec68d18cdbd6d Mon Sep 17 00:00:00 2001 From: Gaurav Gupta Date: Mon, 6 Aug 2018 16:16:51 +0530 Subject: [PATCH 1/2] PAYARA-2958 OpenId Connect test-case with mock server --- payara/openid/pom.xml | 53 +++++ .../payara/security/oidc/client/Callback.java | 65 +++++ .../security/oidc/client/SecuredPage.java | 73 ++++++ .../security/oidc/client/UnsecuredPage.java | 61 +++++ .../oidc/server/ApplicationConfig.java | 58 +++++ .../security/oidc/server/OidcProvider.java | 223 ++++++++++++++++++ .../main/resources/openid-configuration.json | 51 ++++ .../openid/src/main/webapp/WEB-INF/beans.xml | 6 + .../src/main/webapp/WEB-INF/glassfish-web.xml | 11 + .../oidc/test/InvalidRedirectURITest.java | 103 ++++++++ .../security/oidc/test/OpenIdDefaultTest.java | 89 +++++++ .../security/oidc/test/OpenIdTestUtil.java | 105 +++++++++ .../security/oidc/test/UseCookiesTest.java | 94 ++++++++ .../security/oidc/test/WithoutNonceTest.java | 94 ++++++++ payara/pom.xml | 1 + pom.xml | 2 +- 16 files changed, 1088 insertions(+), 1 deletion(-) create mode 100644 payara/openid/pom.xml create mode 100644 payara/openid/src/main/java/fish/payara/security/oidc/client/Callback.java create mode 100644 payara/openid/src/main/java/fish/payara/security/oidc/client/SecuredPage.java create mode 100644 payara/openid/src/main/java/fish/payara/security/oidc/client/UnsecuredPage.java create mode 100644 payara/openid/src/main/java/fish/payara/security/oidc/server/ApplicationConfig.java create mode 100644 payara/openid/src/main/java/fish/payara/security/oidc/server/OidcProvider.java create mode 100644 payara/openid/src/main/resources/openid-configuration.json create mode 100644 payara/openid/src/main/webapp/WEB-INF/beans.xml create mode 100644 payara/openid/src/main/webapp/WEB-INF/glassfish-web.xml create mode 100644 payara/openid/src/test/java/fish/payara/security/oidc/test/InvalidRedirectURITest.java create mode 100644 payara/openid/src/test/java/fish/payara/security/oidc/test/OpenIdDefaultTest.java create mode 100644 payara/openid/src/test/java/fish/payara/security/oidc/test/OpenIdTestUtil.java create mode 100644 payara/openid/src/test/java/fish/payara/security/oidc/test/UseCookiesTest.java create mode 100644 payara/openid/src/test/java/fish/payara/security/oidc/test/WithoutNonceTest.java diff --git a/payara/openid/pom.xml b/payara/openid/pom.xml new file mode 100644 index 0000000..be70ce6 --- /dev/null +++ b/payara/openid/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + + org.vendoree.payara + payara-parent + 1.0-SNAPSHOT + + + openid + Vendor EE: Payara - OpenId Connect + war + + diff --git a/payara/openid/src/main/java/fish/payara/security/oidc/client/Callback.java b/payara/openid/src/main/java/fish/payara/security/oidc/client/Callback.java new file mode 100644 index 0000000..d9f9aab --- /dev/null +++ b/payara/openid/src/main/java/fish/payara/security/oidc/client/Callback.java @@ -0,0 +1,65 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) [2018] Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.security.oidc.client; + +import fish.payara.security.openid.api.OpenIdContext; +import java.io.IOException; +import javax.inject.Inject; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * @author Gaurav Gupta + */ +@WebServlet("/Callback") +public class Callback extends HttpServlet { + + @Inject + private OpenIdContext context; + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.getWriter().println(context.getAccessToken()); + } + +} diff --git a/payara/openid/src/main/java/fish/payara/security/oidc/client/SecuredPage.java b/payara/openid/src/main/java/fish/payara/security/oidc/client/SecuredPage.java new file mode 100644 index 0000000..760cdea --- /dev/null +++ b/payara/openid/src/main/java/fish/payara/security/oidc/client/SecuredPage.java @@ -0,0 +1,73 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) [2018] Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.security.oidc.client; + +import fish.payara.security.annotations.OpenIdAuthenticationDefinition; +import static fish.payara.security.oidc.server.OidcProvider.CLIENT_ID_VALUE; +import static fish.payara.security.oidc.server.OidcProvider.CLIENT_SECRET_VALUE; +import java.io.IOException; +import javax.annotation.security.DeclareRoles; +import javax.servlet.ServletException; +import javax.servlet.annotation.HttpConstraint; +import javax.servlet.annotation.ServletSecurity; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * @author Gaurav Gupta + */ +@WebServlet("/Secured") +@OpenIdAuthenticationDefinition( + providerURI = "http://localhost:8080/openid-server/webresources/oidc-provider/.well-known/openid-configuration", + clientId = CLIENT_ID_VALUE, + clientSecret = CLIENT_SECRET_VALUE, + redirectURI = "${baseUrl}/Callback") +@DeclareRoles("all") +@ServletSecurity(@HttpConstraint(rolesAllowed = "all")) +public class SecuredPage extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + response.getWriter().println("This is a secured web page"); + } +} diff --git a/payara/openid/src/main/java/fish/payara/security/oidc/client/UnsecuredPage.java b/payara/openid/src/main/java/fish/payara/security/oidc/client/UnsecuredPage.java new file mode 100644 index 0000000..8bbd3a1 --- /dev/null +++ b/payara/openid/src/main/java/fish/payara/security/oidc/client/UnsecuredPage.java @@ -0,0 +1,61 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) [2018] Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.security.oidc.client; + +import java.io.IOException; +import javax.servlet.ServletException; +import javax.servlet.annotation.WebServlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * @author Gaurav Gupta + */ +@WebServlet("/Unsecured") +public class UnsecuredPage extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + response.getWriter().print("This is an unsecured web page"); + } + +} diff --git a/payara/openid/src/main/java/fish/payara/security/oidc/server/ApplicationConfig.java b/payara/openid/src/main/java/fish/payara/security/oidc/server/ApplicationConfig.java new file mode 100644 index 0000000..1c7a9a9 --- /dev/null +++ b/payara/openid/src/main/java/fish/payara/security/oidc/server/ApplicationConfig.java @@ -0,0 +1,58 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) [2018] Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.security.oidc.server; + +import static java.util.Collections.singleton; +import java.util.Set; +import javax.ws.rs.core.Application; + +/** + * + * @author Gaurav Gupta + */ +@javax.ws.rs.ApplicationPath("webresources") +public class ApplicationConfig extends Application { + + @Override + public Set> getClasses() { + return singleton(fish.payara.security.oidc.server.OidcProvider.class); + } + +} diff --git a/payara/openid/src/main/java/fish/payara/security/oidc/server/OidcProvider.java b/payara/openid/src/main/java/fish/payara/security/oidc/server/OidcProvider.java new file mode 100644 index 0000000..7815ca0 --- /dev/null +++ b/payara/openid/src/main/java/fish/payara/security/oidc/server/OidcProvider.java @@ -0,0 +1,223 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) [2018] Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.security.oidc.server; + +import com.nimbusds.jwt.JWTClaimsSet; +import com.nimbusds.jwt.PlainJWT; +import static fish.payara.security.openid.api.OpenIdConstant.ACCESS_TOKEN; +import static fish.payara.security.openid.api.OpenIdConstant.AUTHORIZATION_CODE; +import static fish.payara.security.openid.api.OpenIdConstant.CLIENT_ID; +import static fish.payara.security.openid.api.OpenIdConstant.CLIENT_SECRET; +import static fish.payara.security.openid.api.OpenIdConstant.CODE; +import static fish.payara.security.openid.api.OpenIdConstant.ERROR_PARAM; +import static fish.payara.security.openid.api.OpenIdConstant.GRANT_TYPE; +import static fish.payara.security.openid.api.OpenIdConstant.IDENTITY_TOKEN; +import static fish.payara.security.openid.api.OpenIdConstant.NONCE; +import static fish.payara.security.openid.api.OpenIdConstant.REDIRECT_URI; +import static fish.payara.security.openid.api.OpenIdConstant.RESPONSE_TYPE; +import static fish.payara.security.openid.api.OpenIdConstant.SCOPE; +import static fish.payara.security.openid.api.OpenIdConstant.STATE; +import static fish.payara.security.openid.api.OpenIdConstant.SUBJECT_IDENTIFIER; +import static fish.payara.security.openid.api.OpenIdConstant.TOKEN_TYPE; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URI; +import java.net.URISyntaxException; +import static java.util.Arrays.asList; +import java.util.Date; +import java.util.UUID; +import static java.util.logging.Level.SEVERE; +import java.util.logging.Logger; +import static java.util.stream.Collectors.joining; +import javax.json.Json; +import javax.json.JsonObjectBuilder; +import javax.ws.rs.FormParam; +import javax.ws.rs.GET; +import javax.ws.rs.HeaderParam; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.ResponseBuilder; + +/** + * + * @author Gaurav Gupta + */ +@Path("/oidc-provider") +public class OidcProvider { + + private static final String AUTHORIZATION_HEADER = "Authorization"; + private static final String BEARER_TYPE = "Bearer"; + + private static final String AUTH_CODE_VALUE = "sample_auth_code"; + private static final String ACCESS_TOKEN_VALUE = "sample_access_token"; + public static final String CLIENT_ID_VALUE = "sample_client_id"; + public static final String CLIENT_SECRET_VALUE = "sample_client_secret"; + private static final String SUBJECT_VALUE = "sample_subject"; + + private static String nonce; + + private static final Logger LOGGER = Logger.getLogger(OidcProvider.class.getName()); + + @Path("/.well-known/openid-configuration") + @GET + @Produces(APPLICATION_JSON) + public Response getConfiguration() { + String result = null; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + try (InputStream inputStream = classLoader.getResourceAsStream("openid-configuration.json")) { + result = new BufferedReader(new InputStreamReader(inputStream)) + .lines() + .collect(joining("\n")); + } catch (IOException ex) { + LOGGER.log(SEVERE, null, ex); + } + return Response.ok(result) + .header("Access-Control-Allow-Origin", "*") + .build(); + } + + @Path("/auth") + @GET + public Response authEndpoint(@QueryParam(CLIENT_ID) String clientId, + @QueryParam(SCOPE) String scope, + @QueryParam(RESPONSE_TYPE) String responseType, + @QueryParam(NONCE) String nonce, + @QueryParam(STATE) String state, + @QueryParam(REDIRECT_URI) String redirectUri) throws URISyntaxException { + + StringBuilder returnURL = new StringBuilder(redirectUri); + returnURL.append("?&" + STATE + "=").append(state); + returnURL.append("&" + CODE + "=" + AUTH_CODE_VALUE); + + this.nonce = nonce; + JsonObjectBuilder jsonBuilder = Json.createObjectBuilder(); + if (!CODE.equals(responseType)) { + jsonBuilder.add(ERROR_PARAM, "invalid_response_type"); + return Response.serverError().entity(jsonBuilder.build()).build(); + } + if (!CLIENT_ID_VALUE.equals(clientId)) { + jsonBuilder.add(ERROR_PARAM, "invalid_client_id"); + return Response.serverError().entity(jsonBuilder.build()).build(); + } + return Response.seeOther(new URI(returnURL.toString())).build(); + } + + @Path("/token") + @POST + @Produces(APPLICATION_JSON) + public Response tokenEndpoint( + @FormParam(CLIENT_ID) String clientId, + @FormParam(CLIENT_SECRET) String clientSecret, + @FormParam(GRANT_TYPE) String grantType, + @FormParam(CODE) String code, + @FormParam(REDIRECT_URI) String redirectUri) { + + ResponseBuilder builder; + JsonObjectBuilder jsonBuilder = Json.createObjectBuilder(); + if (!CLIENT_ID_VALUE.equals(clientId)) { + jsonBuilder.add(ERROR_PARAM, "invalid_client_id"); + builder = Response.serverError(); + } else if (!CLIENT_SECRET_VALUE.equals(clientSecret)) { + jsonBuilder.add(ERROR_PARAM, "invalid_client_secret"); + builder = Response.serverError(); + } else if (!AUTHORIZATION_CODE.equals(grantType)) { + jsonBuilder.add(ERROR_PARAM, "invalid_grant_type"); + builder = Response.serverError(); + } else if (!AUTH_CODE_VALUE.equals(code)) { + jsonBuilder.add(ERROR_PARAM, "invalid_auth_code"); + builder = Response.serverError(); + } else { + + Date now = new Date(); + JWTClaimsSet jwtClaims = new JWTClaimsSet.Builder() + .issuer("http://localhost:8080/openid-server/webresources/oidc-provider") + .subject(SUBJECT_VALUE) + .audience(asList(CLIENT_ID_VALUE)) + .expirationTime(new Date(now.getTime() + 1000 * 60 * 10)) + .notBeforeTime(now) + .issueTime(now) + .jwtID(UUID.randomUUID().toString()) + .claim(NONCE, nonce) + + .build(); + PlainJWT idToken = new PlainJWT(jwtClaims); + jsonBuilder.add(IDENTITY_TOKEN, idToken.serialize()); + jsonBuilder.add(ACCESS_TOKEN, ACCESS_TOKEN_VALUE); + jsonBuilder.add(TOKEN_TYPE, BEARER_TYPE); + builder = Response.ok(); + } + + return builder.entity(jsonBuilder.build()).build(); + } + + @Path("/userinfo") + @Produces(APPLICATION_JSON) + @GET + public Response userinfoEndpoint(@HeaderParam(AUTHORIZATION_HEADER) String authorizationHeader) { + String accessToken = authorizationHeader.substring(BEARER_TYPE.length() + 1); + + ResponseBuilder builder; + JsonObjectBuilder jsonBuilder = Json.createObjectBuilder(); + if (ACCESS_TOKEN_VALUE.equals(accessToken)) { + builder = Response.ok(); + jsonBuilder.add(SUBJECT_IDENTIFIER, SUBJECT_VALUE) + .add("name", "Gaurav") + .add("family_name", "Gupta ") + .add("given_name", "Gaurav Gupta") + .add("profile", "https://abc.com/+jGauravGupta") + .add("picture", "https://abc.com/photo.jpg") + .add("email", "gaurav.gupta.jc@gmail.com") + .add("email_verified", true) + .add("gender", "male") + .add("locale", "en"); + } else { + jsonBuilder.add(ERROR_PARAM, "invalid_access_token"); + builder = Response.serverError(); + } + return builder.entity(jsonBuilder.build().toString()).build(); + } + +} diff --git a/payara/openid/src/main/resources/openid-configuration.json b/payara/openid/src/main/resources/openid-configuration.json new file mode 100644 index 0000000..a6bed87 --- /dev/null +++ b/payara/openid/src/main/resources/openid-configuration.json @@ -0,0 +1,51 @@ +{ + "issuer": "http://localhost:8080/openid-server/webresources/oidc-provider", + "authorization_endpoint": "http://localhost:8080/openid-server/webresources/oidc-provider/auth", + "token_endpoint": "http://localhost:8080/openid-server/webresources/oidc-provider/token", + "userinfo_endpoint": "http://localhost:8080/openid-server/webresources/oidc-provider/userinfo", + "revocation_endpoint": "http://localhost:8080/openid-server/webresources/oidc-provider/revoke", + "jwks_uri": "http://localhost:8080/openid-server/webresources/oidc-provider/certs", + "response_types_supported": [ + "code", + "token", + "id_token", + "code token", + "code id_token", + "token id_token", + "code token id_token", + "none" + ], + "subject_types_supported": [ + "public" + ], + "id_token_signing_alg_values_supported": [ + "RS256" + ], + "scopes_supported": [ + "openid", + "email", + "profile" + ], + "token_endpoint_auth_methods_supported": [ + "client_secret_post", + "client_secret_basic" + ], + "claims_supported": [ + "aud", + "email", + "email_verified", + "exp", + "family_name", + "given_name", + "iat", + "iss", + "locale", + "name", + "picture", + "sub" + ], + "code_challenge_methods_supported": [ + "plain", + "S256" + ] +} \ No newline at end of file diff --git a/payara/openid/src/main/webapp/WEB-INF/beans.xml b/payara/openid/src/main/webapp/WEB-INF/beans.xml new file mode 100644 index 0000000..2777559 --- /dev/null +++ b/payara/openid/src/main/webapp/WEB-INF/beans.xml @@ -0,0 +1,6 @@ + + + diff --git a/payara/openid/src/main/webapp/WEB-INF/glassfish-web.xml b/payara/openid/src/main/webapp/WEB-INF/glassfish-web.xml new file mode 100644 index 0000000..e9d67f7 --- /dev/null +++ b/payara/openid/src/main/webapp/WEB-INF/glassfish-web.xml @@ -0,0 +1,11 @@ + + + + /oauthtest + + + + Keep a copy of the generated servlet class' java code. + + + diff --git a/payara/openid/src/test/java/fish/payara/security/oidc/test/InvalidRedirectURITest.java b/payara/openid/src/test/java/fish/payara/security/oidc/test/InvalidRedirectURITest.java new file mode 100644 index 0000000..5a6a1a6 --- /dev/null +++ b/payara/openid/src/test/java/fish/payara/security/oidc/test/InvalidRedirectURITest.java @@ -0,0 +1,103 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) [2018] Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.security.oidc.test; + +import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; +import com.gargoylesoftware.htmlunit.WebClient; +import static fish.payara.security.annotations.OpenIdAuthenticationDefinition.OPENID_MP_REDIRECT_URI; +import java.io.IOException; +import java.net.URL; +import static javax.ws.rs.core.Response.Status.NOT_FOUND; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.OperateOnDeployment; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * + * @author Gaurav Gupta + */ +@RunWith(Arquillian.class) +public class InvalidRedirectURITest { + + private WebClient webClient; + + @OperateOnDeployment("openid-client") + @ArquillianResource + private URL base; + + @Before + public void init() { + webClient = new WebClient(); + } + + @Deployment(name = "openid-server") + public static WebArchive createServerDeployment() { + return OpenIdTestUtil.createServerDeployment(); + } + + @Deployment(name = "openid-client") + public static WebArchive createClientDeployment() { + StringAsset mpConfig = new StringAsset(OPENID_MP_REDIRECT_URI + "=invalid_callback"); + return OpenIdTestUtil + .createClientDeployment() + .addAsWebInfResource(mpConfig, "classes/META-INF/microprofile-config.properties"); + } + + @Test + @RunAsClient + public void testOpenIdConnect() throws IOException { + try { + webClient.getPage(base + "Secured"); + fail("redirect uri is valid"); + } catch (FailingHttpStatusCodeException ex) { + assertEquals(NOT_FOUND.getStatusCode(), ex.getStatusCode()); + } + } + +} diff --git a/payara/openid/src/test/java/fish/payara/security/oidc/test/OpenIdDefaultTest.java b/payara/openid/src/test/java/fish/payara/security/oidc/test/OpenIdDefaultTest.java new file mode 100644 index 0000000..fb018de --- /dev/null +++ b/payara/openid/src/test/java/fish/payara/security/oidc/test/OpenIdDefaultTest.java @@ -0,0 +1,89 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) [2018] Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.security.oidc.test; + +import com.gargoylesoftware.htmlunit.WebClient; +import java.io.IOException; +import java.net.URL; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.OperateOnDeployment; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * + * @author Gaurav Gupta + */ +@RunWith(Arquillian.class) +public class OpenIdDefaultTest { + + private WebClient webClient; + + @OperateOnDeployment("openid-client") + @ArquillianResource + private URL base; + + @Before + public void init() { + webClient = new WebClient(); + } + + @Deployment(name = "openid-server") + public static WebArchive createServerDeployment() { + return OpenIdTestUtil.createServerDeployment(); + } + + @Deployment(name = "openid-client") + public static WebArchive createClientDeployment() { + return OpenIdTestUtil.createClientDeployment(); + } + + @Test + @RunAsClient + public void testOpenIdConnect() throws IOException { + OpenIdTestUtil.testOpenIdConnect(webClient, base); + } + +} diff --git a/payara/openid/src/test/java/fish/payara/security/oidc/test/OpenIdTestUtil.java b/payara/openid/src/test/java/fish/payara/security/oidc/test/OpenIdTestUtil.java new file mode 100644 index 0000000..36d6a1a --- /dev/null +++ b/payara/openid/src/test/java/fish/payara/security/oidc/test/OpenIdTestUtil.java @@ -0,0 +1,105 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) [2018] Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.security.oidc.test; + +import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; +import com.gargoylesoftware.htmlunit.TextPage; +import com.gargoylesoftware.htmlunit.WebClient; +import fish.payara.security.oidc.client.Callback; +import fish.payara.security.oidc.client.SecuredPage; +import fish.payara.security.oidc.client.UnsecuredPage; +import fish.payara.security.oidc.server.ApplicationConfig; +import fish.payara.security.oidc.server.OidcProvider; +import java.io.IOException; +import java.net.URL; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.EmptyAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.fail; + +/** + * + * @author Gaurav Gupta + * @author Jonathan + */ +public class OpenIdTestUtil { + + public static WebArchive createServerDeployment() { + WebArchive war = ShrinkWrap + .create(WebArchive.class, "openid-server.war") + .addClass(OidcProvider.class) + .addClass(ApplicationConfig.class) + .addAsResource("openid-configuration.json") + .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); + System.out.println(war.toString(true)); + return war; + } + + public static WebArchive createClientDeployment() { + WebArchive war = ShrinkWrap + .create(WebArchive.class, "openid-client.war") + .addClass(Callback.class) + .addClass(SecuredPage.class) + .addClass(UnsecuredPage.class) + .addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml"); + System.out.println(war.toString(true)); + return war; + } + + public static void testOpenIdConnect(WebClient webClient, URL base) throws IOException { + String result = ((TextPage) webClient.getPage(base + "Unsecured")).getContent(); + assertEquals("This is an unsecured web page", result); + + TextPage page = (TextPage) webClient.getPage(base + "Secured"); + assertEquals("/openid-client/Callback", page.getUrl().getPath()); + assertNotEquals("null", page.getContent()); + + try { + webClient.getPage(base + "Secured"); + fail("Roles test failed"); + } catch (FailingHttpStatusCodeException e) { + System.out.println("Successfully forbidden from accessing page because of " + e.getStatusMessage()); + } + + } + +} diff --git a/payara/openid/src/test/java/fish/payara/security/oidc/test/UseCookiesTest.java b/payara/openid/src/test/java/fish/payara/security/oidc/test/UseCookiesTest.java new file mode 100644 index 0000000..c9f38d8 --- /dev/null +++ b/payara/openid/src/test/java/fish/payara/security/oidc/test/UseCookiesTest.java @@ -0,0 +1,94 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) [2018] Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.security.oidc.test; + +import com.gargoylesoftware.htmlunit.WebClient; +import static fish.payara.security.annotations.OpenIdAuthenticationDefinition.OPENID_MP_USE_SESSION; +import java.io.IOException; +import java.net.URL; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.OperateOnDeployment; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * + * @author Gaurav Gupta + */ +@RunWith(Arquillian.class) +public class UseCookiesTest { + + private WebClient webClient; + + @OperateOnDeployment("openid-client") + @ArquillianResource + private URL base; + + @Before + public void init() { + webClient = new WebClient(); + } + + @Deployment(name = "openid-server") + public static WebArchive createServerDeployment() { + return OpenIdTestUtil.createServerDeployment(); + } + + @Deployment(name = "openid-client") + public static WebArchive createClientDeployment() { + StringAsset mpConfig = new StringAsset(OPENID_MP_USE_SESSION + "=" + Boolean.FALSE.toString()); + return OpenIdTestUtil + .createClientDeployment() + .addAsWebInfResource(mpConfig, "classes/META-INF/microprofile-config.properties"); + } + + @Test + @RunAsClient + public void testOpenIdConnect() throws IOException { + OpenIdTestUtil.testOpenIdConnect(webClient, base); + } + +} diff --git a/payara/openid/src/test/java/fish/payara/security/oidc/test/WithoutNonceTest.java b/payara/openid/src/test/java/fish/payara/security/oidc/test/WithoutNonceTest.java new file mode 100644 index 0000000..0846c47 --- /dev/null +++ b/payara/openid/src/test/java/fish/payara/security/oidc/test/WithoutNonceTest.java @@ -0,0 +1,94 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright (c) [2018] Payara Foundation and/or its affiliates. All rights reserved. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common Development + * and Distribution License("CDDL") (collectively, the "License"). You + * may not use this file except in compliance with the License. You can + * obtain a copy of the License at + * https://github.com/payara/Payara/blob/master/LICENSE.txt + * See the License for the specific + * language governing permissions and limitations under the License. + * + * When distributing the software, include this License Header Notice in each + * file and include the License file at glassfish/legal/LICENSE.txt. + * + * GPL Classpath Exception: + * The Payara Foundation designates this particular file as subject to the "Classpath" + * exception as provided by the Payara Foundation in the GPL Version 2 section of the License + * file that accompanied this code. + * + * Modifications: + * If applicable, add the following below the License Header, with the fields + * enclosed by brackets [] replaced by your own identifying information: + * "Portions Copyright [year] [name of copyright owner]" + * + * Contributor(s): + * If you wish your version of this file to be governed by only the CDDL or + * only the GPL Version 2, indicate your decision by adding "[Contributor] + * elects to include this software in this distribution under the [CDDL or GPL + * Version 2] license." If you don't indicate a single choice of license, a + * recipient has the option to distribute your version of this file under + * either the CDDL, the GPL Version 2 or to extend the choice of license to + * its licensees as provided above. However, if you add GPL Version 2 code + * and therefore, elected the GPL Version 2 license, then the option applies + * only if the new code is made subject to such option by the copyright + * holder. + */ +package fish.payara.security.oidc.test; + +import com.gargoylesoftware.htmlunit.WebClient; +import static fish.payara.security.annotations.OpenIdAuthenticationDefinition.OPENID_MP_USE_NONCE; +import java.io.IOException; +import java.net.URL; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.container.test.api.OperateOnDeployment; +import org.jboss.arquillian.container.test.api.RunAsClient; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * + * @author Gaurav Gupta + */ +@RunWith(Arquillian.class) +public class WithoutNonceTest { + + private WebClient webClient; + + @OperateOnDeployment("openid-client") + @ArquillianResource + private URL base; + + @Before + public void init() { + webClient = new WebClient(); + } + + @Deployment(name = "openid-server") + public static WebArchive createServerDeployment() { + return OpenIdTestUtil.createServerDeployment(); + } + + @Deployment(name = "openid-client") + public static WebArchive createClientDeployment() { + StringAsset mpConfig = new StringAsset(OPENID_MP_USE_NONCE + "=" + Boolean.FALSE.toString()); + return OpenIdTestUtil + .createClientDeployment() + .addAsWebInfResource(mpConfig, "classes/META-INF/microprofile-config.properties"); + } + + @Test + @RunAsClient + public void testOpenIdConnect() throws IOException { + OpenIdTestUtil.testOpenIdConnect(webClient, base); + } + +} diff --git a/payara/pom.xml b/payara/pom.xml index e62d969..c514baf 100644 --- a/payara/pom.xml +++ b/payara/pom.xml @@ -17,6 +17,7 @@ jacc-per-app rolesPermitted oauth2 + openid diff --git a/pom.xml b/pom.xml index 89a0e65..16c9a25 100644 --- a/pom.xml +++ b/pom.xml @@ -32,7 +32,7 @@ - 5.182 + 5.183-SNAPSHOT 5.182 17.0.0.4 2018.4.1 From 3b640ae938c0a002f541739513f763e9e7d07012 Mon Sep 17 00:00:00 2001 From: Gaurav Gupta Date: Tue, 7 Aug 2018 17:55:14 +0530 Subject: [PATCH 2/2] baseURL EL typo --- .../java/fish/payara/security/oidc/client/SecuredPage.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/payara/openid/src/main/java/fish/payara/security/oidc/client/SecuredPage.java b/payara/openid/src/main/java/fish/payara/security/oidc/client/SecuredPage.java index 760cdea..23e1fea 100644 --- a/payara/openid/src/main/java/fish/payara/security/oidc/client/SecuredPage.java +++ b/payara/openid/src/main/java/fish/payara/security/oidc/client/SecuredPage.java @@ -57,10 +57,11 @@ */ @WebServlet("/Secured") @OpenIdAuthenticationDefinition( - providerURI = "http://localhost:8080/openid-server/webresources/oidc-provider/.well-known/openid-configuration", + providerURI = "http://localhost:8080/openid-server/webresources/oidc-provider", clientId = CLIENT_ID_VALUE, clientSecret = CLIENT_SECRET_VALUE, - redirectURI = "${baseUrl}/Callback") + redirectURI = "${baseURL}/Callback" +) @DeclareRoles("all") @ServletSecurity(@HttpConstraint(rolesAllowed = "all")) public class SecuredPage extends HttpServlet {