WildFly Elytron

Securing WildFly Applications Using Okta on OpenShift

WildFly applications can be secured using OpenID Connect and deployed to OpenShift. By using OIDC to secure applications, you delegate authentication to OIDC providers. The elytron-oidc-client subsystem can be used to secure an application deployed to WildFly using any OpenID Provider. This guide demonstrates how to secure an example application deployed to WildFly on OpenShift using Okta as the OpenID Provider.

Prerequisites

To follow along this guide you will need:

Example application

We will use a simple web application in this guide that consists of a single servlet. We will use the simple-webapp-okta application in this repository.

We will need to first fork, and then clone the elytron-examples repository. We will be using the simple-webapp-okta directory in this repo:

git clone git@github.com:wildfly-security-incubator/elytron-examples.git
cd simple-webapp-okta

Log Into the OpenShift Cluster

Before we can deploy our application, we need to log into an OpenShift cluster. You can log in via the OpenShift CLI:

oc login -u myUserName

Alternatively, you can log in using the API token:

oc login --token=myToken --server=myServerUrl

You can request the token via the Copy Login Command link in the OpenShift web console.

If you don’t already have a project created, you can create one using:

oc new-project myProjectName

Once you have your environment set up with the required tools, we can move on to the next step to build and deploy our application on OpenShift.

Configure Okta

For this guide, we will be using Okta as out OpenID provider. In order to secure the application, we will need to access the Okta web console and register our application as a client.

  1. Log in to the Okta dashboard to get started.

  2. At the top right corner, click on Admin to be redirected to the admin dashboard.

  3. On the left hand panel, from the Applications drop down, click on Applications and then Create App Integration. Choose OIDC - OpenID Connect under Sign-in method and Web Application for Application type and click Next.

  4. Under General Settings add the following configurations:

    • App integration name: simple-webapp-okta

    • Grant type: Leave it as is, with Authorization Code checked.

    • Sign-in redirect URIs: Leave it as is for now. We will edit it later.

    • Under the Assignments tab, for Controlled access, select Skip group assignment for now.

    • Click Save

  5. Navigate to the Directory drop down on the left panel and click People. Click Add person and add a person with:

    • First name: Alice

    • Last name: Smith

    • Email: alice@example.org

    • User Name: alice@example.org

    • From the dropdown list for Password, choose Set by admin and set a password that fits the password requirements.

    • Uncheck User must change password on first login and hit Save. For more information about how to add a user manually click here.

  6. Click on the Applications tab on the left hand side. Navigate to Applications and click on simple-webapp-okta. Under the Assignments tab, click on Assign, then click on Assign to People and select Alice. For more information about how to assign a user to an application, please see here.

Advanced OpenID Configuration

In order to extract the user information through the id token, we will need to configure a custom authorization server. Follow the steps below for this:

  1. Under the Security dropdown, select API and click on the edit button next to the Default server.

  2. Under the Claims tab, click on the Add Claim button and to add a claim with the following configurations:

    • Name: IDTClaim

    • Include in token type: ID Token and keep it at always.

    • Value type: Expression

    • Value: appuser.userName and hit Save. We will be using this claim later to extract the username of the user who is currently logged in. You can learn more about Expression Language Reference for Okta here.

  3. Now go back to the API menu and copy the Issuer URI for the Default server.

  4. This will be used as the provider url when configuring our WildFly application.

Add Helm Configuration

  1. Keep the URL obtained from the last step.

  2. Switch to the charts directory in the simple-webapp-okta example.

cd /PATH/TO/ELYTRON/EXAMPLES/simple-webapp-okta/charts

Notice there’s a helm.yaml file in this directory with the following content:

build:
  uri: https://github.com/wildfly-security-incubator/elytron-examples.git
  contextDir: simple-webapp-okta
deploy:
  replicas: 1
  env:
    - name: OIDC_PROVIDER_URL
      value: <OKTA_URL>         (1)
    - name: OIDC_CLIENT_ID
      value: <CLIENT_ID>        (2)
    - name: OIDC_CLIENT_SECRET
      value: <CLIENT_SECRET>    (3)

We will need to make the following changes locally to the helm chart:

1 Replace OKTA_URL with the provider url you copied in the last step.
2 Replace CLIENT_ID with the Client ID listed on the Okta console. Navigate to the General tab for our application on the Okta admin console and copy the Client Id and add it beside the client-id attribute.
3 Replace CLIENT_SECRET with your Client Secret for this application listed on Okta.

Save this file and close it.

Configure the Deployment Settings

Applications deployed to WildFly can be secured with OIDC in a couple different ways:

  1. Using deployment configuration by specifying the attribute values inside oidc.json

  2. or using the elytron-oidc-client subsystem.

This guide uses the deployment configuration, but you can use the same attributes to configure the elytron-oidc-client subsystem. You can view the deployment configuration used in this example by navigating to the oidc.json file. Note that we are making use of the environment variables we defined in the helm chart.

Now that we have added the required changes, we can deploy our application, the helm chart will specify the location for this example application and pull information needed for our deployment specified in the oidc.json file.

Deploy the Example Application to WildFly on OpenShift

If you have not already installed the WildFly Helm chart, you can install it using the following commands:

helm repo add wildfly https://docs.wildfly.org/wildfly-charts/

If you have it installed already, be sure to update it to ensure you have the latest one:

helm repo update

We can deploy our example application to WildFly on OpenShift using the wildfly Helm Chart:

helm install oidc-app -f /PATH/TO/ELYTRON/EXAMPLES/simple-webapp-saml/charts/helm.yaml wildfly/wildfly

The application will now begin to build. This will take a couple of minutes. The build can be observed using:

oc get build -w

Once complete, you can follow the deployment of the application using:

oc get deployment oidc-app -w

Alternatively, you can check status directly from the OpenShift web console.

Behind the scenes

While our application is building, let’s take a closer look at our application.

Examine the pom.xml file. Notice that it contains an openshift profile. A profile in Maven lets you create a set of configuration values to customize your application build for different environments. The openshift profile in this example defines a configuration that will be used by the WildFly Helm Chart when provisioning the WildFly server on OpenShift.

<profiles>
        <profile>
            <id>openshift</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.wildfly.plugins</groupId>
                        <artifactId>wildfly-maven-plugin</artifactId>
                        <version>${version.wildfly.maven.plugin}</version>          (1)
                        <configuration>
                            <feature-packs>
                                <feature-pack>
                                    <location>org.wildfly:wildfly-galleon-pack:${version.wildfly}</location>
                                </feature-pack>
                                <feature-pack>
                                    <location>org.wildfly.cloud:wildfly-cloud-galleon-pack:${version.wildfly.cloud.galleon.pack}</location>
                                </feature-pack>
                            </feature-packs>
                            <layers>
                                <layer>cloud-server</layer>
                                <layer>elytron-oidc-client</layer>          (2)
                            </layers>
                            <filename>simple-webapp-okta.war</filename>
                        </configuration>
                        <executions>
                            <execution>
                                <goals>
                                    <goal>package</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>
1 wildfly-maven-plugin provisions a WildFly server with the specified layers with our application deployed.
2 elytron-oidc-client automatically adds the native OIDC client subsystem to our WildFly installation.

Now examine the web.xml file.

    <login-config>
        <auth-method>OIDC</auth-method> (1)
    </login-config>
1 When elytron-oidc-client subsystem sees auth-method is set to OIDC, it enables OIDC authentication mechanism for the application.

Finally, review the oidc.json file. The oidc.json is used to configure the native OIDC client subsystem.

{
    "client-id" : "${env.CLIENT_ID}",               (1)
    "provider-url" : "${env.OIDC_PROVIDER_URL}",    (2)
    "public-client" : "false",                      (3)
    "principal-attribute" : "IDTClaim",             (4)
    "ssl-required" : "EXTERNAL",                    (5)
    "credentials" : {
        "secret" : "${env.CLIENT_SECRET}"           (6)
    }
}
1 Client_ID is the unique identifier for our client used by the Okta OpenID provider. Usually for Keycloak, you can create your own client, but for Okta, you are assigned an id. As a result, we are using environment variables to specify this.
2 The provider URL, which is the URL for the authorization server that we created, is specified as an environment variable. We set its value previously in the helm configuration.
3 When public-client set to false, client credentials are sent when communicating with the OpenID provider.
4 We specify that the user name of the identity, which in our case is alice, is to be used as the principal for the identity. We are extracting this information here using a custom claim in the ID token.
5 When ssl-required is set to EXTERNAL, only the communication with external clients happens over HTTPs.
6 Client credentials helps the OIDC server authenticate the client when accepting a request. It is required when public-client is set to false.

Get the Application URL

Once the WildFly server has been provisioned, use the following command to find the URL for your example application:

SIMPLE_WEBAPP_OKTA_URL=https://$(oc get route oidc-app --template='{{ .spec.host }}') &&
echo "" &&
echo "Application URL: $SIMPLE_WEBAPP_OKTA_URL/simple-webapp-okta"  &&
echo "Valid redirect URI: $SIMPLE_WEBAPP_OKTA_URL/simple-webapp-okta/secured/" &&
echo ""

We’ll make use of these URLs in the next two sections.

Finish Configuring Okta

Go back to the General Settings for your application and click on Edit. add the Valid redirect URI under the Sign-in redirect URIs and check the Allow wildcard * in login URI redirect field and hit Save.

Access the App

Now we can access our application using the Application Url from the previous section. Click on "Access Secured Servlet".

Now you will be redirected to the login page for Okta. Login using Alice. You will be prompted for the username. Although we set the username to be alice@example.org, we can just input alice here. You will be presented with three options for loggin in. Choose Password and enter the password you selected for Alice.

Summary

This guide demonstrates how to use an OpenID provider other than Keycloak to secure an application deployed to WildFly. Other OpenID providers can be used to secure WildFly applications as well. And while the specific terms may be slightly different, the overall process should be similar. Please refer to documentations by your OpenID provider for more information.