From 2e8d83cd2c2bf50f4369dfad1f72660eb819b36b Mon Sep 17 00:00:00 2001 From: Ralph Soika Date: Mon, 12 Jun 2023 22:22:02 +0200 Subject: [PATCH] impl draft Issue #3 --- imixs-oidc/README.md | 74 ++++++++++--------- imixs-oidc/pom.xml | 10 ++- .../main/java/org/imixs/oidc/OidcConfig.java | 48 ++++++++++++ .../java/org/imixs/oidc/Securitybean.java | 23 +++--- 4 files changed, 111 insertions(+), 44 deletions(-) create mode 100644 imixs-oidc/src/main/java/org/imixs/oidc/OidcConfig.java diff --git a/imixs-oidc/README.md b/imixs-oidc/README.md index 3bf82d2..b8ef8df 100644 --- a/imixs-oidc/README.md +++ b/imixs-oidc/README.md @@ -1,18 +1,16 @@ # OpenID Connect for Jakarta EE 10 -This project provides a generic library to setup an OpenID Connect security mechanism for web applications running on Jakarta EE 10. Jakarta EE 10 provides a security API to support OpenID Connect. This implementation was also inspired by [Andrew Hughes blogpost about Jakarta EE and OIDC](https://auth0.com/blog/jakarta-ee-oidc/). - +This project provides a generic library to setup an OpenID Connect security mechanism for web applications running on Jakarta EE 10. Jakarta EE 10 provides a security API to support OpenID Connect. This implementation was also inspired by [Andrew Hughes blogpost about Jakarta EE and OIDC](https://auth0.com/blog/jakarta-ee-oidc/). +Specification details can be found [here](https://jakarta.ee/specifications/security/3.0/jakarta-security-spec-3.0.html#openid-connect-annotation). ## Background -Since Jakarta EE 8 a new Security API was introduced providing a new standard and portable way of handling security concerns in Java containers. This new standard allows to configure the authentication mechanism of an application directly in a CDI bean, instead through the web.xml file. So web applications can now configure authentication mechanisms by providing implementations of the new `HttpAuthenticationMechanism` interface. Beside the standard implementations for Basic, Form and CustomForm authentication Jakarta EE 10 adapted this concept to provide an authentication mechanism for OpenID Connect. We introduced this library for an easy security setup of Web Applications. The library can be added simply as a dependency to a web application project. - - +Since Jakarta EE 8 a new Security API was introduced providing a new standard and portable way of handling security concerns in Java containers. This new standard allows to configure the authentication mechanism of an application directly in a CDI bean, instead through the web.xml file. So web applications can now configure authentication mechanisms by providing implementations of the new `HttpAuthenticationMechanism` interface. Beside the standard implementations for Basic, Form and CustomForm authentication Jakarta EE 10 adapted this concept to provide an authentication mechanism for OpenID Connect. We introduced this library for an easy security setup of Web Applications. The library can be added simply as a dependency to a web application project. ## Maven Dependecy -To use this library your application needs to be deployed into Payara 5 Platform. You simply need to add the following maven dependencies to your pom.xml: +To use this library your application needs to be deployed into Jakarta EE 10 Application. You simply need to add the following maven dependencies to your pom.xml: ```xml @@ -25,31 +23,16 @@ To use this library your application needs to be deployed into Payara 5 Platform The Jakarta EE 10 Runtime automatically scann this library during deployment and initializes the OpenID Connect auth mechanism automatically for your application. This is possible because of the `beans.xml` file located in the META-INF folder of this library. This library also includes a `CallbackServlet` that is used to redirect the user into your application after a successful login. So no additional implementation should be necessary. - ## Configuration -The Payara5 OpenID Client configuration attributes can be configured via Microprofile Config using the following properties : +The OpenID Client configuration attributes can be configured via Microprofile Config using the following properties : ``` - payara.security.openid.providerURI - payara.security.openid.clientId - payara.security.openid.clientSecret - payara.security.openid.redirectURI + OIDCCONFIG_ISSUERURI: "" + OIDCCONFIG_CLIENTID: "xxxxxxxxxx" + OIDCCONFIG_CLIENTSECRET: "xxxxxxxxxx" ``` -Microprofile Config is part of Payara 5 and the properties value take precedence over @OpenIdAuthenticationDefinition annotation values. - -Setting the properties in a Docker or a Kubernetes environment use the corresponding Unix style to name the variables: - -``` - PAYARA_SECURITY_OPENID_PROVIDERURI - PAYARA_SECURITY_OPENID_CLIENTID - PAYARA_SECURITY_OPENID_CLIENTSECRET - PAYARA_SECURITY_OPENID_REDIRECTURI -``` - -A full list of all possible configuration values can be found [on the Payara OpenID Connect Support page](https://docs.payara.fish/enterprise/docs/documentation/payara-server/public-api/openid-connect-support.html). - ### The ClaimsDefinition Within the OpenID standard it is not defined how Roles or Groups a user is assigned to are provided in a result token. For this reason it is necessary to declare with a so called `ClaimsDefinition` which attribute contains the groups to be resolved by the `OpenIdAuthenticationDefinition`. @@ -68,6 +51,31 @@ When using this library you can set the GroupsClaim with the property `payara.se To setup Auth0 with user roles can be a little tricky but you will find a good tutorial [here](https://auth0.com/blog/jakarta-ee-oidc/). +### Wildfly + +To Enable the OpenIdAuthenticationMechanismDefinition in Wildfly Server you need to disalbe + +This can be done either by the wildfly-cli command: + + /subsystem=undertow/application-security-domain=other:add(security-domain=ApplicationDomain, integrated-jaspi=false) + +or by changing the standalone.xml file: + +```xml + ....... + + + + + ....... +``` + +### Auth0.com + +For auth0.com you need to provide an additional parameter to resolve role names configured in auth0.com + + extraParameters = { "audience=https://.auth0.com/api/v2/" }, // + ## Protecting CDI Beans, EJBs and Pages Within you application code you work with the usual Jakarta EE security API. There is no need to use any additional OpenID configuration or annotations. @@ -75,8 +83,8 @@ Within you application code you work with the usual Jakarta EE security API. The The following example shows a EJB protected with the role 'super-admin' ```java -@DeclareRoles({ "super-admin" }) -@RolesAllowed({ "super-admin" }) +@DeclareRoles({ "org.imixs.ACCESSLEVEL.MANAGERACCESS" }) +@RolesAllowed({ "org.imixs.ACCESSLEVEL.MANAGERACCESS" }) @Named @RequestScoped public class ConfigBean { @@ -94,8 +102,8 @@ public class ConfigBean { In the same way you can protect your EJBs. ```java -@DeclareRoles({ "super-admin" }) -@RolesAllowed({ "super-admin" }) +@DeclareRoles({ "org.imixs.ACCESSLEVEL.MANAGERACCESS" }) +@RolesAllowed({ "org.imixs.ACCESSLEVEL.MANAGERACCESS" }) @Stateless @LocalBean public class ConfigService { @@ -115,11 +123,11 @@ Protecting JSF pages or static html pages can be done as usual in the web.xml fi /api/* - super-admin + org.imixs.ACCESSLEVEL.MANAGERACCESS - super-admin + org.imixs.ACCESSLEVEL.MANAGERACCESS .... @@ -134,8 +142,8 @@ Protecting JSF pages or static html pages can be done as usual in the web.xml fi / - super-admin - super-admin + org.imixs.ACCESSLEVEL.MANAGERACCESS + org.imixs.ACCESSLEVEL.MANAGERACCESS diff --git a/imixs-oidc/pom.xml b/imixs-oidc/pom.xml index 4b9271b..03be201 100644 --- a/imixs-oidc/pom.xml +++ b/imixs-oidc/pom.xml @@ -64,6 +64,7 @@ UTF-8 10.0.0 + 3.0 @@ -241,7 +242,14 @@ 4.13.1 test - + + + org.eclipse.microprofile + microprofile + ${microprofile.version} + pom + provided + diff --git a/imixs-oidc/src/main/java/org/imixs/oidc/OidcConfig.java b/imixs-oidc/src/main/java/org/imixs/oidc/OidcConfig.java new file mode 100644 index 0000000..11c14ed --- /dev/null +++ b/imixs-oidc/src/main/java/org/imixs/oidc/OidcConfig.java @@ -0,0 +1,48 @@ +package org.imixs.oidc; + +import java.io.Serializable; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import jakarta.inject.Named; + +/** + * The OidcConfig is a CDI config bean used to provide the config values for the + * {@link Securitybean}. + * + * @author rsoika + * + */ +@ApplicationScoped +@Named +public class OidcConfig implements Serializable { + + private static final long serialVersionUID = 7027147503119012594L; + + @Inject + @ConfigProperty(name = "OIDCCONFIG_ISSUERURI", defaultValue = "http://localhost/") + String issuerUri; + + @Inject + @ConfigProperty(name = "OIDCCONFIG_CLIENTID", defaultValue = "undefined") + String clientId; + + @Inject + @ConfigProperty(name = "OIDCCONFIG_CLIENTSECRET", defaultValue = "undefined") + String clientSecret; + + public String getClientId() { + return clientId; + } + + public String getClientSecret() { + return clientSecret; + } + + public String getIssuerUri() { + return issuerUri; + } + +} \ No newline at end of file diff --git a/imixs-oidc/src/main/java/org/imixs/oidc/Securitybean.java b/imixs-oidc/src/main/java/org/imixs/oidc/Securitybean.java index 1eba842..ba9096c 100644 --- a/imixs-oidc/src/main/java/org/imixs/oidc/Securitybean.java +++ b/imixs-oidc/src/main/java/org/imixs/oidc/Securitybean.java @@ -9,6 +9,7 @@ import jakarta.enterprise.context.RequestScoped; import jakarta.inject.Inject; import jakarta.security.enterprise.authentication.mechanism.http.OpenIdAuthenticationMechanismDefinition; +import jakarta.security.enterprise.authentication.mechanism.http.openid.ClaimsDefinition; import jakarta.security.enterprise.identitystore.openid.OpenIdContext; import jakarta.ws.rs.GET; import jakarta.ws.rs.Path; @@ -28,17 +29,19 @@ @DeclareRoles({ "org.imixs.ACCESSLEVEL.NOACCESS", "org.imixs.ACCESSLEVEL.READERACCESS", "org.imixs.ACCESSLEVEL.AUTHORACCESS", "org.imixs.ACCESSLEVEL.EDITORACCESS", "org.imixs.ACCESSLEVEL.MANAGERACCESS" }) -@OpenIdAuthenticationMechanismDefinition( // find details here: - // https://docs.payara.fish/enterprise/docs/documentation/payara-server/public-api/openid-connect-support.html - // providerURI = "${payara.security.openid.providerURI}", // - // clientId = "${payara.security.openid.clientId}", // - // clientSecret = "${payara.security.openid.clientSecret}", // - // redirectURI = "${payara.security.openid.redirectURI}", // - scope = { - "email", "openid", "profile" } // -// claimsDefinition = @ClaimsDefinition(callerGroupsClaim = -// "http://www.imixs.org/roles") // +@OpenIdAuthenticationMechanismDefinition( // + clientId = "${oidcConfig.clientId}", // + clientSecret = "${oidcConfig.clientSecret}", // + redirectURI = "${baseURL}/callback", // + providerURI = "${oidcConfig.issuerUri}", // + tokenAutoRefresh = true, // + // extraParameters = { "audience=https://.eu.auth0.com/api/v2/" }, + // // + claimsDefinition = @ClaimsDefinition(callerGroupsClaim = "http://www.imixs.org/roles") + ) +// Caller Groups: +// OpenIdAuthenticationMechanismDefinition.claimsDefinition.callerGroupsClaim. public class Securitybean implements Serializable { private static final long serialVersionUID = 1L;