Skip to content

Commit

Permalink
Merge pull request #544 from PrarthonaPaul/okta-guide
Browse files Browse the repository at this point in the history
Added a guide to demonstrate how to secure a wildfly application using OKTA
  • Loading branch information
bstansberry committed Mar 12, 2024
2 parents 569795a + c42dd94 commit 23f6e82
Show file tree
Hide file tree
Showing 2 changed files with 262 additions and 0 deletions.
3 changes: 3 additions & 0 deletions _data/guides.yaml
Expand Up @@ -31,6 +31,9 @@ categories:
- title: Securing WildFly Apps with SAML on OpenShift
url: /guides/security-saml-openshift
description: Learn how to secure applications deployed to WildFly on OpenShift with SAML.
- title: Securing WildFly Apps with Okta on OpenShift
url: /guides/security-oidc-okta-openshift
description: Learn how to secure applications deployed to WildFly on OpenShift with the Okta OpenID provider.
- category: MicroProfile
cat-id: microprofile
guides:
Expand Down
259 changes: 259 additions & 0 deletions guides/security-oidc-okta-openshift.adoc
@@ -0,0 +1,259 @@
= Securing WildFly Applications Using Okta on OpenShift
:summary: A step by step guide on how to secure a WildFly application using Okta's OpenID Provider and deploy it to OpenShift.
:includedir: _includes
include::{includedir}/_attributes.adoc[]
:prerequisites-time: 15

WildFly applications can be secured using OpenID Connect (OIDC) 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 https://www.okta.com/[Okta] as the OpenID Provider.

include::{includedir}/_prerequisites.adoc[]
* Roughly 15 minutes
* Access to an OpenShift cluster (try the https://developers.redhat.com/developer-sandbox[Red Hat Developer Sandbox] for free)
* https://docs.openshift.com/container-platform/4.14/cli_reference/openshift_cli/getting-started-cli.html[OpenShift CLI]
* https://helm.sh/docs/intro/install/[Helm Chart]
* https://www.okta.com/[Okta OpenID Provider]

== Example Application

We will use a simple web application in this guide that consists of a single https://github.com/wildfly-security-incubator/elytron-examples/blob/main/simple-webapp-okta/src/main/java/org/wildfly/security/examples/SecuredServlet.java[servlet]. We will use the https://github.com/wildfly-security-incubator/elytron-examples/tree/main/simple-webapp-okta[simple-webapp-okta] application in this repository.

We will need to first fork, and then clone the https://github.com/wildfly-security-incubator/elytron-examples[elytron-examples] repository. We will be using the `simple-webapp-okta` directory in this repo:

[source,bash]
----
git clone git@github.com:wildfly-security-incubator/elytron-examples.git
cd simple-webapp-okta
----

include::{includedir}/_proc-log-into-openshift-cluster.adoc[]

== Configure Okta

For this guide, we will be using Okta as our OpenID provider. In order to secure the application, we will need to access the Okta web console and register our application as a client. The following set of steps outlines how to register an OpenID web-application with Okta:

. Log in to the https://www.okta.com/free-trial/[Okta dashboard] to get started.
. At the top right corner, click on *Admin* to be redirected to the admin dashboard.
. 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*.
. 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`.

You can find more information about configuring settings for app integration on Okta https://help.okta.com/en-us/content/topics/apps/apps-configure-settings.htm[here].

Next, we will be adding a user to our directory, and add them to the previously created application using the following steps:

. 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 https://help.okta.com/en-us/content/topics/users-groups-profiles/usgp-add-users.htm[click here].
. 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 https://support.okta.com/help/s/article/How-To-Assign-An-User-To-An-Application?language=en_US[here].

For more information about managing users on Okta, please see https://help.okta.com/en-us/content/topics/users-groups-profiles/usgp-people.htm[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:

. Under the *Security* dropdown, select *API* and click on the edit button next to the *Default* server.
. 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 Okta Expression Language https://developer.okta.com/reference/okta_expression_language/[here].
. Now go back to the _API_ menu and copy the *Issuer URI* for the _Default_ server.
. This will be used as the provider url when configuring our WildFly application.

For more information about Customizing tokens returned from Okta, please refer to this https://developer.okta.com/docs/guides/customize-tokens-returned-from-okta/main/[guide].

[[add-helm-configuration]]
== Add Helm Configuration
. Keep the URL obtained from the last step.
. Switch to the `charts` directory in the `simple-webapp-okta` example.

[source,bash]
----
cd /PATH/TO/ELYTRON/EXAMPLES/simple-webapp-okta/charts
----
Notice there’s a helm.yaml file in this directory with the following content:

[source,yaml]
----
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:

. Using deployment configuration by specifying the attribute values inside `oidc.json`
. 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 learn more about the `elytron-oidc-client` subsystem https://docs.wildfly.org/31/Admin_Guide.html#Elytron_OIDC_Client[here].

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

include::{includedir}/_proc-install-or-update-helm.adoc[]

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

[source,bash]
----
helm install oidc-app -f /PATH/TO/ELYTRON/EXAMPLES/simple-webapp-saml/charts/helm.yaml wildfly/wildfly
----
Notice that this command specifies the file we updated, `helm.yaml`, that contains the values needed to build and deploy our application.

include::{includedir}/_proc-follow-build-and-deployment-openshift.adoc[]

=== Behind the Scenes

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

Examine the https://github.com/wildfly-security-incubator/elytron-examples/blob/main/simple-webapp-okta/pom.xml[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.

[source,xml]
----
<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 https://github.com/wildfly-security-incubator/elytron-examples/blob/main/simple-webapp-okta/src/main/webapp/WEB-INF/web.xml[web.xml] file.
[source,xml]
----
<login-config>
<auth-method>OIDC</auth-method> <1>
</login-config>
----

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

Finally, review the https://github.com/wildfly-security-incubator/elytron-examples/blob/main/simple-webapp-okta/src/main/webapp/WEB-INF/oidc.json[oidc.json] file. The oidc.json is used to configure the native OIDC client subsystem.
[source,json]
----
{
"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 pod running your WildFly server has been provisioned, use the following command to find the URL for your example application:

[source,bash]
----
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.

== What's next?

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.

// Always add this section last to link to any relevant content
[[references]]
== References

* https://help.okta.com/oie/en-us/content/topics/identity-engine/oie-index.htm[Okta Documentation]
* https://developer.okta.com/docs/guides/quickstart/main/[Okta Quickstarts]
* https://docs.wildfly.org/31/wildscribe/subsystem/elytron-oidc-client/index.html[Elytron-oidc-client subsystem]
* https://docs.wildfly.org/31/Admin_Guide.html#Elytron_OIDC_Client[elytron-oidc-client docs]
* https://openid.net/specs/openid-connect-core-1_0.html#[OpenID Specifications]
* https://developer.okta.com/docs/guides/#integrate-authentication-into-your-app[Guides Related on Configuring Okta]
* https://docs.wildfly.org/31/Getting_Started_on_OpenShift.html[Getting Started with WildFly on OpenShift]
* https://docs.openshift.com/container-platform/4.13/cli_reference/openshift_cli/getting-started-cli.html[OpenShift CLI]
* https://docs.wildfly.org/31/Getting_Started_on_OpenShift.html#helm-charts[WildFly Helm Charts]
* <<security-oidc-openshift.adoc#security-oidc-openshift,Securing WildFly Apps with OIDC on OpenShift>>

0 comments on commit 23f6e82

Please sign in to comment.