Integrating Workspace ONE Access and UAG with JWT

If you’re leveraging Workspace ONE Access with Horizon and allowing external access, you are likely leveraging multifactor authentication for additional security from the outside. When combined with UAG, a common scenario is to separate out Connection Servers and place them in Workspace ONE mode and setting SAML to required, like this:

When pointing the UAG to a Connection Server with this, it only accepts launches from Workspace ONE Access. While this is a great way to do this, you are separating your “internal” and “external” Connection Servers. You could set them all the same (required), but if you have zero clients internally or workflows that require accessing the Horizon Client directly, this requires you to have two separate configurations and VIPs.

You may have noticed when configuring your Horizon launch URLs from Workspace ONE Access, you have a mysterious option for “Wrap artifact in JWT.” JWT stands for JSON Web Token and is an IETF standard for signing a payload. When launching a Horizon resource from Workspace ONE Access, a SAML artifact is presented with the launch URI and is validated by the Connection Server. With JWT, we are taking an additional layer and wrapping that artifact with a signature from Workspace ONE, which is validated by the UAG, and then the normal SAML artifact is passed onto the Connection Server for validation. This allows us to have the UAG be the gatekeeper and keep all of our Connection Servers set to Allowed for SAML, so no more separating out internal vs external Connection Servers!

Setting this up fairly simple! Head over to your UAG and underneath Advanced Settings, click the JWT Settings gear. Then, click add:

Name the JWT source a friendly name, such as WS1 Access. The only thing you need to configure here is that and the Dynamic Public Key URL. Workspace ONE Access has a URL that presents the public key in PEM format, and the UAG can dynamically fetch the public key for trust. This prevents you from having to re-upload certificates whenever cert changes happen on Access, which is especially important for SaaS tenants since you have no control over this. Note that the UAG must be able to reach this URL to fetch the file.

Here it is! Just fill in your Access URL: https://<WS1 Access URL>/SAAS/API/1.0/REST/auth/token?attribute=publicKey&format=pem

This will unlock a couple of new settings in the Horizon configuration section, so head there. You will notice JWT Settings and JWT Audiences:

Select the new JWT issuer you just created. For JWT audiences, configure the URL that you will be using to access the UAG. This can be a VIP name as well. That wraps it up for the UAG configuration!

Jump over to your Workspace ONE Access admin portal, go to Virtual Apps Collection, and select the hyperlink for your Horizon deployment.

Head over to network ranges and select the range(s) that will be accessing Horizon via UAG. Along with the launch URL to point to the UAG, we will also set “Wrap Artifact in JWT” to Yes and fill in the matching JWT audience that we configured in the UAG earlier:

If everything is working correctly, the UAG will now ONLY accept launches from Workspace ONE Access. If you try and launch from the Horizon Client or HTML, you’ll get the following error, much like setting the Connection Server to SAML required. This is because the UAG is expecting a trusted JWT along with the request, which will only come from launches via Access!

To wrap it up, this is a great way to configure a “trust” between UAG and Workspace ONE Access. This prevents you from having separate SAML-required Connection Servers just to point the UAGs at when enforcing MFA via Access, which simplifies the design and deployment. Hope this helps, and let me know if you have any questions or feedback!

Note: Henry Heres ran into an issue where his SaaS WS1 Access tenant only had a 1024 size signing key. When the UAG went to validate the JWT, it rejected it. As of this post, there is no method to upgrade to a 2048 key. See Henry’s blogpost here for more details. Thanks for the great collaboration and troubleshooting here, Henry!