Skip to main content

Set Up Client-Credentials Auth for a Machine User with Okta

Client credentials let a machine user reach an internal MCP server that uses Proxy Passthrough. Because a machine user has no interactive login, Willow mints an OAuth token from your identity provider using the machine user's client credentials and forwards that token to the MCP server on each call.

This tutorial walks through the full setup with Okta. Keycloak works the same way; see the note at the end.

By the end, you will have:

  • an Okta API Services app that issues client-credentials tokens
  • client credentials enabled for machine users in Willow
  • a machine user configured with those credentials
  • an internal MCP server set to Proxy Passthrough that receives the minted token

Prerequisites

You need:

  • admin access to Willow, with Okta already configured as your SSO provider (see Configure Okta)
  • an Okta org with API Access Management (available on the free Okta Integrator Free Plan and on paid Workforce Identity orgs)
  • Okta admin access to create applications and authorization servers
  • a machine user and an internal MCP server you can point at Willow

Part 1: Configure Okta

Create an API Services application

  1. In the Okta Admin Console, go to Applications > Applications and select Create App Integration.
  2. Select API Services and select Next.
  3. Enter a name (for example, "Willow Machine User") and select Save.
  4. On the app's General tab, under Client Secrets, select Generate new secret. A new API Services app has no secret until you generate one. Copy the secret now, because Okta only shows it once.
  5. Still on the General tab, edit General Settings and clear Require Demonstrating Proof of Possession (DPoP) header in token requests, then select Save.
DPoP breaks the client-credentials grant

Okta enables DPoP by default on API Services apps. A standard client-credentials grant fails with invalid_dpop_proof while it is enabled, so you must turn it off.

Add a scope and access policy

  1. Go to Security > API and open the default authorization server.
  2. On the Scopes tab, select Add Scope. Name it api.access, and check Set as a default scope. Select Create.
  3. On the Access Policies tab, select Add Policy. Name it "Client Credentials Policy", assign it to All clients, and select Create Policy.
  4. Inside the policy, select Add Rule. Name it, check Client Credentials under grant type, and select Create Rule.

Copy the Client ID from the app's General tab. Your Token Endpoint is https://{your-okta-domain}/oauth2/default/v1/token.

Part 2: Enable client credentials in Willow

  1. Go to Settings > Authentication Settings. With Okta selected as the provider, check Enable Client Credentials for Machine Users.
  2. A Token Endpoint field appears. Set it to your custom authorization server's token endpoint, https://{your-okta-domain}/oauth2/default/v1/token (where the api.access scope lives). This is not the same as your SSO issuer, which is the org authorization server, so the auto-discovered value can point at the wrong server. Select Save Changes.
Authentication Settings with Okta selected and Enable Client Credentials for Machine Users

Part 3: Configure the machine user

  1. Open Manage > Machine Users. In the Client Credentials column, your machine user shows Not configured. Select it to open the Client Credentials dialog.
  2. Enter the Client ID and Client Secret from your Okta API Services app, and set Token URL to https://{your-okta-domain}/oauth2/default/v1/token. Leave it blank only when the organization Token Endpoint from Part 2 already points there. If a machine user's Token URL resolves to the org authorization server, the grant fails with "Failed to generate access token".
  3. Select Save.

The Client Credentials column now shows the configured Client ID.

Part 4: Point an internal MCP server at Proxy Passthrough

  1. Open your internal MCP server and go to its Setup tab.
  2. Set the authentication mode to Proxy Passthrough.
  3. Select Save Changes, and make sure the machine user's group has this server assigned.

Now, when the machine user calls a tool on this server, Willow requests a token from Okta using the machine user's client credentials and forwards it as the Authorization header. The MCP server receives a bearer token issued by Okta, with cid matching your API Services app and the api.access scope.

Verify it worked

  • The machine user's Client Credentials column shows the Client ID, not "Not configured".
  • A tool call from the machine user to the Proxy Passthrough server succeeds.
  • The MCP server receives an Authorization: Bearer <token> whose issuer is your Okta domain.
  • If the machine user has no client credentials configured, the call fails with "Failed to generate access token... Please reauthorize."

Using Keycloak instead

Keycloak works identically. Create a realm and a client with service accounts (client credentials) enabled, and use its token endpoint (https://{keycloak-host}/realms/{realm}/protocol/openid-connect/token) as the Token URL. Everything else, including the machine user configuration and Proxy Passthrough, is the same.

Next steps