Skip to content

Latest commit

 

History

History
332 lines (254 loc) · 14.8 KB

Elytron_OIDC_Client.adoc

File metadata and controls

332 lines (254 loc) · 14.8 KB

Elytron OpenID Connect Client Subsystem

The ability to secure applications using OpenID Connect is provided by the elytron-oidc-client subsystem.

Subsystem

The elytron-oidc-client subsystem is included in the default configuration. If not present, the subsystem can be added using the following CLI commands.

[standalone@localhost:9990 /] /extension=org.wildfly.extension.elytron-oidc-client:add

[standalone@localhost:9990 /] /subsystem=elytron-oidc-client:add

[standalone@localhost:9990 /] reload

Configuration

By default, the elytron-oidc-client subsystem does not contain any configured resources or attributes.

The configuration required to secure an application with OpenID Connect can either be provided within the application itself or within the elytron-oidc-client subsystem.

Deployment Configuration

The configuration required to secure an application with OpenID Connect can be specified in the deployment.

The first step is to create an oidc.json configuration file in the WEB-INF directory of the application. The second step is to set the auth-method to OIDC in the application’s web.xml file.

Here is an example of an oidc.json configuration file:

{
  "client-id" : "customer-portal",
  "provider-url" : "http://localhost:8180/auth/realms/demo",
  "ssl-required" : "external",
  "use-resource-role-mappings" : false,
  "enable-cors" : true,
  "cors-max-age" : 1000,
  "cors-allowed-methods" : "POST, PUT, DELETE, GET",
  "cors-exposed-headers" : "WWW-Authenticate, My-custom-exposed-Header",
  "enable-basic-auth" : false,
  "expose-token" : true,
  "scope" : "profile email phone",
  "verify-token-audience" : true,
   "credentials" : {
      "secret" : "234234-234234-234234"
   },

   "connection-pool-size" : 20,
   "socket-timeout-millis": 5000,
   "connection-timeout-millis": 6000,
   "connection-ttl-millis": 500,
   "disable-trust-manager": false,
   "allow-any-hostname" : false,
   "truststore" : "path/to/truststore.pkcs12",
   "truststore-password" : "geheim",
   "client-keystore" : "path/to/client-keystore.pkcs12",
   "client-keystore-password" : "geheim",
   "client-key-password" : "geheim",
   "token-minimum-time-to-live" : 10,
   "min-time-between-jwks-requests" : 10,
   "public-key-cache-ttl": 86400,
   "redirect-rewrite-rules" : {
   "^/wsmain/api/(.*)$" : "/api/$1"
   }
}

Subsystem Configuration

Instead of adding configuration to your deployment to secure it with OpenID Connect as described in the previous section, another option is to add configuration to the elytron-oidc-client subsystem instead.

The following example shows how to add configuration to the elytron-oidc-client subsystem.

<subsystem xmlns="urn:wildfly:elytron-oidc-client:1.0">
    <secure-deployment name="DEPLOYMENT_RUNTIME_NAME.war">
        <client-id>customer-portal</client-id>
        <provider-url>http://localhost:8180/auth/realms/demo</provider-url>
        <scope>email profile phone</scope>
        <ssl-required>external</ssl-required>
        <credential name="secret" secret="0aa31d98-e0aa-404c-b6e0-e771dba1e798" />
    </secure-deployment>
</subsystem>

The secure-deployment resource allows you to provide configuration for a specific deployment. In the example above, the secure-deployment resource is providing the configuration that should be used for the DEPLOYMENT_RUNTIME_NAME.war deployment, where DEPLOYMENT_RUNTIME_NAME corresponds to the runtime-name for the deployment.

The various configuration options that can be specified in the secure-deployment configuration correspond to the same options that can be specified in the oidc.json configuration that was explained in the previous section.

If you have multiple applications that are being secured using the same OpenID provider, the provider configuration can be defined separately as shown in the example below:

<subsystem xmlns="urn:wildfly:elytron-oidc-client:1.0">
    <provider name="keycloak">
        <provider-url>http://localhost:8080/auth/realms/demo</provider-url>
        <ssl-required>external</ssl-required>
    </realm>
    <secure-deployment name="customer-portal.war">
        <provider>keycloak</provider>
        <client-id>customer-portal</client-id>
        <credential name="secret" secret="0aa31d98-e0aa-404c-b6e0-e771dba1e798" />
    </secure-deployment>
    <secure-deployment name="product-portal.war">
        <provider>keycloak</provider>
        <client-id>product-portal</client-id>
        <credential name="secret" secret="0aa31d98-e0aa-404c-b6e0-e771dba1e798" />
    </secure-deployment>
</subsystem>

Activation

The elytron-oidc-client subsystem will scan deployments to detect if the OIDC authentication mechanism is required for any web components (i.e., for each deployment, the subsystem will determine if OIDC configuration has either been found within the deployment or if there is OIDC configuration for the deployment in the subsystem configuration). If the subsystem detects that the OIDC mechanism is indeed required, the subsystem will activate the authentication mechanism automatically. Otherwise, no activation will occur and deployment will continue normally.

Scope Configuration

ℹ️
Since this attribute is a preview level feature, the WildFly server’s stability level must be set to preview or lower to enable it. The stability level must not be changed to community or default after configuring the scope attribute. For more information about the stability levels of the WildFly server, please refer to the Admin Guide, particularly the Feature stability levels section.

OpenID Connect allows the client to use scope values to request access to specific privileges for access tokens. An access token’s scopes determine what resources will be available when using the access token to access an OAuth2 protected endpoint. The OpenID Connect specification defines a few scope values including:

  • profile : requests access to the End-User’s default profile Claims, such as name, family_name, given_name, middle_name, nickname, preferred_username, profile, picture, website, gender, birthday etc.

  • email : requests access to the email and email_verified Claims.

  • address : requests access to the address Claim.

  • phone : requests access to the phone_number and phone_number_verified Claims.

Scopes can be used to request that specific sets of information be made available as Claim Values. The scope values must be added as a space separated, case-sensitive list of ascii values.

Subsystem Configuration

It is possible to configure the scope values that would be used in the OIDC authentication request using the scope attribute of a secure-deployment or a secure-server resource in the elytron-oidc-client subsystem.

Deployment Configuration

It is also possible to configure the scope values that would be used via the scope attribute in a deployment’s oidc.json file.

ℹ️
If both the deployment and subsystem configuration is present, then the subsystem configuration will override the deployment values.

Virtual Security

The purpose of using OpenID Connect is to verify a user’s identity based on the authentication that’s been performed by the OpenID provider. For this reason, OpenID Connect deployments do not depend on security-domain resources that have been defined in the Elytron subsystem, like traditional deployments do. Instead, the elytron-oidc-client subsystem will automatically create and make use of its own virtual security domain across the deployment. No further managed configuration is required.

ℹ️

To propagate an identity from a virtual security domain, additional configuration might be required depending on your use case. See Identity Propagation for more details.

OpenID Providers

The provider-url attribute in the oidc.json configuration and in the elytron-oidc-client subsystem configuration allows you to specify the URL for the OpenID provider that you’d like to use. For WildFly 25, the elytron-oidc-client subsystem has been tested with the Keycloak OpenID provider. Other OpenID providers haven’t been extensively tested yet so the use of other OpenID providers should be considered experimental for now and should not be used in a production environment yet. Proper support for other OpenID providers will be added in a future WildFly release.

Disabling "typ" Claim Validation

By default, when verifying an access token, the elytron-oidc-client subsystem expects the token to contain a typ claim with value Bearer. Access tokens provided by the Keycloak OpenID provider contain this claim. However, access tokens provided by other OpenID providers might not include this claim, causing token validation to fail. When using an OpenID provider other than Keycloak, it is possible to disable the typ claim validation by setting the wildfly.elytron.oidc.disable.typ.claim.validation system property to true.

Multi-Tenancy Support

In some cases, it might be desirable to secure an application using multiple oidc.json configuration files. For example, you might want a different oidc.json file to be used depending on the request in order to authenticate users from multiple Keycloak realms. The elytron-oidc-client subsystem makes it possible to use a custom configuration resolver so you can define which configuration file to use for each request.

To make use of the multi-tenancy feature, you need to create a class that implements the org.wildfly.security.http.oidc.OidcClientConfigurationResolver interface, as shown in the example below:

package example;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.wildfly.security.http.oidc.OidcClientConfiguration;
import org.wildfly.security.http.oidc.OidcClientConfigurationBuilder;
import org.wildfly.security.http.oidc.OidcClientConfigurationResolver;
import org.wildfly.security.http.oidc.OidcHttpFacade;

public class MyCustomConfigResolver implements OidcClientConfigurationResolver {

    private final Map<String, OidcClientConfiguration> cache = new ConcurrentHashMap<>();

    @Override
    public OidcClientConfiguration resolve(OidcHttpFacade.Request request) {
        String path = request.getURI();
        String realm = ... // determine which Keycloak realm to use based on the request path
        OidcClientConfiguration clientConfiguration = cache.get(realm);
        if (clientConfiguration == null) {
            InputStream is = getClass().getResourceAsStream("/oidc-" + realm + ".json"); // config to use based on the realm
            clientConfiguration = OidcClientConfigurationBuilder.build(is);
            cache.put(realm, clientConfiguration);
        }
        return clientConfiguration;
    }

}

Once you’ve created your OidcClientConfigurationResolver `, you can specify that you want to make use of your custom configuration resolver by setting the `oidc.config.resolver context-param in your application’s web.xml file, as shown in the example below:

<web-app>
    ...
    <context-param>
        <param-name>oidc.config.resolver</param-name>
        <param-value>example.MyCustomConfigResolver</param-value>
    </context-param>
    ...
</web-app>

Securing the management console with OpenID Connect

The management console can be secured with OpenID Connect using the Keycloak OpenID provider.

ℹ️

The ability to secure the management console with the Keycloak OpenID provider is only available when running a standalone server and is not supported when running a managed domain. The management CLI cannot be secured with OpenID Connect.

To secure the management console with OpenID Connect, configuration is required on the Keycloak side and in the elytron-oidc-client subsystem.

Keycloak Configuration

Follow the steps in Keycloak’s getting started guide to add a new realm called wildfly-infra.

Then, create a new OpenID Connect client called wildfly-console. Set the Valid Redirect URIs using the URI used to access the WildFly management console, e.g., http://localhost:9990/console/. Similarly, you’ll also need to set *Web Origins using the management port for your WildFly instance, e.g., http://localhost:9990.

Next, create a second OpenID Connect client called wildfly-management. This will be a bearer-only client so in the Capability configuration, be sure to uncheck the Standard flow and Direct access grants.

If you will be configuring WildFly to enable Role Based Access Control (RBAC), you can also create a new Realm role (e.g., Administrator) and assign it to a user.

Elytron OIDC Client Subsystem Configuration

We need to add a secure-deployment resource that references the wildfly-management client that was created in the previous section.

A secure-server that references the wildfly-console client is also needed.

Some example CLI commands that add these resources can be seen here:

# Configure the Keycloak provider
/subsystem=elytron-oidc-client/provider=keycloak:add(provider-url=http://localhost:8180/realms/wildfly-infra)

# Create a secure-deployment in order to protect mgmt interface
/subsystem=elytron-oidc-client/secure-deployment=wildfly-management:add(provider=keycloak,client-id=wildfly-management,principal-attribute=preferred_username,bearer-only=true,ssl-required=EXTERNAL)

# Enable RBAC where roles are obtained from the identity
/core-service=management/access=authorization:write-attribute(name=provider,value=rbac)
/core-service=management/access=authorization:write-attribute(name=use-identity-roles,value=true)

# Create a secure-server in order to publish the management console configuration via mgmt interface
/subsystem=elytron-oidc-client/secure-server=wildfly-console:add(provider=keycloak,client-id=wildfly-console,public-client=true)

# reload
reload

Accessing the management console

With the above configuration in place, when you access the management console (e.g., http://localhost:9990/console/), you will be redirected to Keycloak to log in, and will then be redirected back to the management console upon successful authentication.