Cannot get refresh_token with Okta Workforce Enterprise Connection

Goal

Our subsidiary organization is using Auth0 to have a federated login to our parent companies Okta IdP. We are looking to Authenticate AND authorize access to Auth0 protected tools by taking Okta AD groups placed on the Okta issued id_token claim to Auth0 and mapping those AD groups to Auth0’s Authorization Core RBAC Roles. We’d like that mapping of roles to sync every time we issue a new access_token from Auth0 (1 hour)

What Works

We have working federated authentication solutions with both:

  1. Enterprise OIDC Connection
  2. Okta Workforce Connection.

We also have a working solution for federated authorization mapping within an Auth0 Rule or Auth0 Action (Auth0 Rule saving us an extra request to the Management API since the access_token is passed into the user’s identities in the Auth0 Rule)

The Problem

After an hour has passed since the initial federated login, the access_token issued to Auth0 from Okta (exp of +1 hour when issued) goes stale and expires. The Auth0 docs suggest using a refresh_token issued from the IdP (Okta in this case) so that we can get a new access_token. However, both the Enterprise OIDC Connection and the Okta Workforce Connection do NOT store a refresh token in the user’s identities even if present on the code exchange between Auth0 and Okta. Therefore, we cannot get a new Okta access_token for the purpose of getting the latest AD group claims via Okta’s /userinfo route. Because of that, we can’t map those AD groups to the latest RBAC permissions defined in Auth0. At worst, we would be updating our Auth0 RBAC roles for as long as the Auth0 session is maintained (and not needing to go to Okta) – which in our case is the default 7 days. That’s undesired, as we’d want to adjust RBAC roles on the Auth0 side if a user had a removed AD group on the Okta side (removal of access)

Solutions Explored

  1. Use a Social Federated Login (OAuth2.0) and leverage the fact that it stores both the access_token and refresh_token
    • Problem: We need the identifier first feature for our connection. And that’s only possible with an Enterprise Connection
  2. Use the Enterprise OIDC Connection and expect that “Auth0 automatically syncs user profile data with each user login” according to this doc
    • Problem: Although the docs say “with each user login”, I don’t think that means once an Auth0 session is established or for silent auth’s with a response_mode=web_message & prompt=none
      • Both of these scenarios cause Auth0 to redirect back to the primary application without going back to Okta first. Which leads me to believe that there is no way that claims are being synced unless Auth0 is somehow storing and auto using the refresh token to fetch updated claims via the Okta /userinfo route. But I highly doubt that.
  3. Require Application to force re-auth as described in these docs (max_age param).
    • Problem: This works well, however it allows the application to define when the full upstream authentication happens. In our case, our applications are all first party and we desire that the sync between Okta AD group claims and Auth0 RBAC roles happens as part of the identity server logic and not determine by a single application/client.
  4. Use Auth0 Rules to define a redirect back to our Auth0 /authorize route but with the connection name for Okta defined so it forces the login to go to Okta first before issuing a token back to the client. Thereby, allowing us to get a fresh new acces_token stored for the user on every new application session.
    • When the access_token in the Okta connection expires, we would simply force a redirect by using context.redirect = { url : redirectUrl }
    • Problem: Although this does indeed work to refresh the access_token so we can fetch new claims from the Okta /userinfo route, we cannot add the initial scopes (or any) requested by the client application to the redirect URL. Otherwise, we get “Invalid redirect URL” as a text response from the /authorize endpoint
      • we’ve tried URL encoding it as well
      • example req/resp traces:
        • x-auth0-requestid: 9fe90ac5861ee86c635c
        • traceparent: 00-00000000000000005699ba5454a99e24-7c1a930519c4279c-01
        • auth0-request-id=7be37d6e2f564523,auth0=true
      • example bad redirect
  context.redirect = {
    url: "https://{{AUTH_SERVER}}/authorize?response_type=code&scope=openid email profile offline_access&client_id={{CLIENT_ID}}&redirect_uri={{WHITELISTED_CALLBACK_URL}}&connection={{OKTA_WORKFORCE_CONNECTION_NAME}}",
  };
  1. Use Auth0 Actions to define a redirect back to our Auth0 /authorize route but with the connection name for Okta defined so it forces the login to go to Okta first before issuing a token back to the client. Thereby, allowing us to get a fresh new acces_token stored for the user on every new application session.
    • When the access_token in the Okta connection expires, we would simply force a redirect by using api.redirect.sendUserTo(redirectUrl.href)
    • Currently our best solution
    • Problem: I am needing to make a Management API request to simply get the access_token for the user while in the Auth0 Rule, the user.identities has the access_token. Unfortunately the Auth0 Action does NOT.

Questions

  1. Will Enterprise Connections ever store refresh tokens in the user’s identities storage? Is that on the roadmap?
    • it seems OIDC Connections might have that coming down the pipeline according to this link, but what about other Enterprise Connections?
  2. The Okta Enterprise Connection does not allow us in the UI to adjust the scopes fetched from Okta. I needed to change the scopes requested (adding the offline_access scope for the refresh token) via the Management API connection PUT action https://{{auth0_domain}}/api/v2/connections/:conn_id . Is there plans for the Okta Enterprise connection to allow this change via the UI?
  3. (reference: Solutions Explored #4) is the inclusion of scopes on a Rule redirect truly something we shouldn’t or can’t do? or is it a bug?
  4. (reference: Solutions Explored #5) will access_token ever be present on the function’s event.user variable? This would save us a Management API fetch (doing our best to avoid the rate limits).
  5. Are there other methods to sync Okta AD group claims to Auth0 that we didn’t explore?
1 Like