The ability to secure applications using OpenID Connect is provided by the elytron-oidc-client 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
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.
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"
}
}
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>
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.
ℹ️
|
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.
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.
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. |
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.
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
.
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>
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.
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.
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
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.