Skip to content

Two-Legged OAuth 2.0

Two-legged OAuth is the simpler of the two flows IMan supports, and the one to reach for whenever a service will let you. There is no browser, no consent screen and nobody to ask: your integration presents a client id and a client secret, the service returns an access token, and IMan puts that token on every subsequent request.

The two legs are the two parties — your integration and the service. Nothing represents an end user, so the flow suits an unattended integration.

Do you have a two-legged service?

Vendors rarely use the phrase. Match on what they describe:

What the vendor's documentation says What it means
"client credentials"; grant_type=client_credentials; "machine to machine"; "server to server" Two-legged. This page
"authorization code"; "redirect URI"; "the user will be asked to approve"; a consent screen in the screenshots Three-legged. See Three-Legged OAuth 2.0
A single long-lived key with no token exchange at all Not OAuth. See Basic Authentication

The reliable tell is the redirect URI. If registering the application asked you for one, the vendor expects a user to be sent somewhere and sent back, and you are looking at a three-legged flow.

The two halves

This is the part worth understanding before touching the screen, because getting it wrong produces an error that points somewhere else entirely.

An OAuth setup describes two different requests:

  1. The token request. IMan presents the client credentials to the service and receives an access token. Configured by Token Request URL, Token Request Path, Token Request Body Type, Token Request Form URL Parameters and Token Request Headers.
  2. The authenticated API request. Every subsequent call to the service, carrying that token. Configured by Authenticated API Request Headers, and by nothing else.

Both must be set up. Configure only the first and the token exchange succeeds, then IMan calls the API with an Authorization header carrying no token — the trace reads Authorization - Bearer and nothing after it — and the service answers with a credentials error, because from where it is standing an unauthenticated request is indistinguishable from a badly authenticated one. PayPal's wording for this is "Authentication failed due to invalid authentication credentials or a missing Authorization header", which sends you to check the client id and secret. They are fine. The second half is missing.

There are no Client ID and Client Secret fields here

There are no Client ID and Client Secret fields on this screen, and that is deliberate. You enter the credentials wherever the vendor's documentation puts them — a Basic Authorization header, or client_id and client_secret form parameters — and IMan reads them back out of whichever you used. %[client_id] and %[client_secret] then work either way.

PayPal

PayPal documents the token request as a curl command, which is the most common way to find one:

curl -v https://api-m.sandbox.paypal.com/v1/oauth2/token \
  -u "CLIENT_ID:CLIENT_SECRET" \
  -d "grant_type=client_credentials"

Key facts

Three things are in that command, and each maps to one part of the screen:

  • -u "CLIENT_ID:CLIENT_SECRET" is HTTP Basic authentication. That is a Token Request Header, not a body parameter.
  • -d "grant_type=client_credentials" is a form-encoded body. That is a Token Request Form URL Parameter, and IMan pre-seeds it for you.
  • The URL is the Token Request URL, in full.

The command does not say how to present the token afterwards. Look at any other page of the API reference for that: every example carries Authorization: Bearer <Access-Token>, which is the Authenticated API Request Header.

Sandbox and live are different hosts — api-m.sandbox.paypal.com and api-m.paypal.com — and sandbox credentials are rejected by live with the same message as a bad key. Create the app under Apps & Credentials in the PayPal developer dashboard, and note which tab you were on.

IMan setup

The PayPal OAuth object, showing OAuth ID, Description, OAuth Flow Type set to 2-Legged (Client Credentials), the Token Request URL, Path and Body Type, the Token Request Form URL Parameters holding grant_type equals client_credentials, the Token Request Headers holding a Basic Authorization header, the Authenticated API Request Headers holding Bearer with the token placeholder, and the Test URL.

Field Value
OAuth Flow Type 2-Legged (Client Credentials)
Token Request URL https://api-m.sandbox.paypal.com/v1/oauth2/token
Token Request Path access_token
Token Request Body Type Form URL Encoded
Token Request Form URL Parameters grant_type = client_credentials
Test URL https://api-m.sandbox.paypal.com/v1/catalogs/products?page_size=1

Token Request Path is not a URL path. It is where the token sits in the response — the JPath into the JSON that comes back. PayPal returns {"access_token": "...", "token_type": "Bearer", ...}, so the path is access_token, which is also the default. A service that nests it deeper needs the full path.

The token request header

-u means Basic, so this is the same header control, and the same Authorisation Type, as the Basic Authentication page. The client id goes in as the user name and the secret as the password.

The Add Header dialog on the Token Request Headers list, with Header Name Authorization, Authorisation Type Basic, Prefix Basic, the PayPal client id as the User Name and the client secret as the Password.

The authenticated API request header

Add this to the Authenticated API Request Headers list, not the token one.

The Add Header dialog on the Authenticated API Request Headers list, with Header Name Authorization, Authorisation Type Bearer, Prefix Bearer and the value set to the token placeholder.

%[token] is a placeholder that IMan replaces with whatever the token request returned. You give IMan the shape of the header, and IMan fills in the value it does not hold until run time.

The flow preview

The right-hand pane draws the flow you have configured, from the values you have typed, and updates as you change them.

The OAuth Flow Preview showing four numbered steps between IMan, Token Request and Resource Server: a POST to the PayPal token URL carrying the Basic credentials header and the client credentials grant type, a 200 response containing an access token, a GET to the Test URL carrying the bearer header, and a 200 data response.

Read it before pressing Test. It is the fastest way to see the mistake described above: if step 3 has no yellow header box against it, the Authenticated API Request Headers list is empty and the API call will go out unauthenticated.

It is also honest about what it does not know. [credentials] and %[token] appear as placeholders rather than as values, because at design time the token does not exist yet.

Testing it

Test URL is any endpoint of the service that answers a GET, and the Test performs the whole flow: the token request, then a real API call with the token. A pass therefore means both halves work, which is more than a token exchange on its own would tell you.

The Test Results tab carries the exchange itself.

The Test Results tab after a successful test, listing the token request and the authenticated API request with their responses.

When the Test fails

  • A credentials error on the API call, not the token call. The Authenticated API Request Headers list is empty or wrong. Check the flow preview: step 3 should carry an Authorization header.
  • invalid_client on the token request. The client id and secret are wrong for this host — most often sandbox credentials against the live host, or the reverse.
  • A token is returned and the API call still fails. The token is real but the application lacks permission for that endpoint. This is a scope problem at the vendor, not an IMan problem.
  • Nothing at all in Test Results. Tick Enable Trace Logging and run it again.

Once the Test passes, the authentication is ready to be attached to a service by a Webservice Behaviour.


Verified against IMan 6.1 and the PayPal REST API sandbox on 2 September 2026.