ApiSkills

Authentication · 10 min

OAuth2 grant types compared

Client Credentials vs Authorization Code vs PKCE vs Refresh — which to use, and why.

OAuth2 is not one flow — it is a family of "grants", each for a different situation. Picking the right one is the whole skill. This sandbox implements all of them so you can try each.

Client Credentials — app acts as itself

No user is involved. Your app authenticates with its client_id + client_secret and gets a token. Use it for server-to-server automation — this is what n8n uses for background jobs, and what the cookbook workflow uses.

curl -X POST https://api.ifsjaipur.cloud/oauth/token -u "APP_ID:APP_SECRET" \
  -d "grant_type=client_credentials&scope=stocks:read"

Authorization Code — app acts on behalf of a user

Used when your app needs to access a user's data with their permission ("Sign in with Google", "Connect your account"). The user logs in at the provider and consents; the provider redirects back to your app with a short-lived code; your app exchanges that code (plus its client_secret) for a token. There is a redirect and a human in the loop.

  1. Redirect the user to /oauth/authorize?response_type=code&client_id=APP_ID&redirect_uri=...&scope=stocks:read&state=xyz
  2. The user approves (auto-approved in this sandbox); they are redirected back with ?code=...
  3. Exchange the code: POST /oauth/token with grant_type=authorization_code, code, redirect_uri, client_id, client_secret → access_token + refresh_token.

PKCE — Authorization Code for apps that cannot keep a secret

PKCE (Proof Key for Code Exchange) is not a separate grant — it is Authorization Code hardened for "public" clients like mobile apps and single-page apps, which cannot safely store a client_secret. Instead of a secret, the app generates a random code_verifier, sends its SHA-256 hash (code_challenge) at the authorize step, and reveals the verifier when exchanging the code. An attacker who intercepts the code cannot use it without the verifier.

# authorize with a challenge
/oauth/authorize?response_type=code&client_id=APP_ID&redirect_uri=...&code_challenge=<sha256url>&code_challenge_method=S256

# exchange with the verifier (no client_secret needed)
POST /oauth/token  grant_type=authorization_code&code=...&code_verifier=<original>&client_id=APP_ID

Refresh Token — stay signed in without re-asking

Access tokens are short-lived (1 hour here). The Authorization Code flow also returns a refresh_token you exchange for a new access token when it expires — no user interaction needed.

curl -X POST https://api.ifsjaipur.cloud/oauth/token \
  -d "grant_type=refresh_token&refresh_token=...&client_id=APP_ID"
GrantUser involved?Client secret?Best for
Client CredentialsNoYesServer-to-server / n8n automations
Authorization CodeYes (login + consent)YesWeb apps acting for a user
Auth Code + PKCEYesNoMobile / SPA / public clients
Refresh TokenNo (renewal)YesRenewing an access token

Tip · Rule of thumb: no user → Client Credentials. A user, on a server you control → Authorization Code. A user, in an app that cannot hide a secret → Authorization Code + PKCE.