API & Webhooks

API Authentication Explained: Keys, OAuth & Tokens

API keys, OAuth, bearer tokens — authentication jargon is confusing. Here's what each method actually does and when you'll encounter it.

OT
OctaTechno Team September 21, 2026
11 min read
API Authentication Explained: Keys, OAuth & Tokens

Why APIs Need Authentication

An API without authentication is like a bank vault with no lock — anyone could read your customer list, delete your data, or rack up charges on your account. Authentication answers two questions: who are you? and what are you allowed to do? There are a few standard ways APIs do this.

1. API Keys (Simplest)

An API key is a long secret string the provider gives you, like sk_live_51H7x9a2b.... You include it with every request, usually in a header:

headers = {
    "Authorization": "Bearer sk_live_51H7x9a2b..."
}
response = requests.get("https://api.example.com/data", headers=headers)

When you'll see it: most SaaS APIs (Stripe, OpenAI, SendGrid) use keys. They're simple and work well for server-to-server communication.

Security rules:

  • Never put API keys in frontend code, public repos, or screenshots — they're secrets
  • Store them in environment variables, not hardcoded in scripts
  • Use separate keys for development and production
  • Rotate (replace) keys immediately if one leaks

2. Bearer Tokens (Temporary Keys)

A bearer token works like an API key, but it's temporary — it expires after minutes or hours. You typically get one by logging in first:

# Step 1: exchange credentials for a token
auth = requests.post("https://api.example.com/login",
                     json={"username": "you", "password": "secret"})
token = auth.json()["access_token"]

# Step 2: use the token (same "Bearer" pattern as API keys)
headers = {"Authorization": f"Bearer {token}"}

Why bother? If a token leaks, it stops working soon anyway. API keys, by contrast, work until someone revokes them.

3. OAuth 2.0 (The "Login with Google" Flow)

OAuth is what happens when you click "Sign in with Google" on a third-party site. It's the standard for letting users grant apps limited access to their accounts — without sharing passwords.

The flow, in plain English:

  1. You click "Connect my Google Calendar" in some app
  2. You're sent to Google, which asks: "Allow this app to read your calendar?"
  3. You approve. Google sends the app a temporary code.
  4. The app exchanges the code for an access token (and usually a refresh token to get new ones later).
  5. The app now calls Google's API with that token — it never saw your password.

When you'll see it: any integration that acts on behalf of a user — "connect your Slack," "import from Google Drive," "post to LinkedIn."

4. Basic Auth (Legacy)

Username and password encoded into the request header. Simple but weak — credentials travel with every request. You'll still see it in older enterprise systems, but modern APIs have mostly moved on.

Quick Comparison

  • API key: simplest, best for your own scripts talking to a service
  • Bearer token: like an API key with an expiry date — safer for sessions
  • OAuth 2.0: for user-facing integrations where people grant access to their accounts
  • Basic auth: legacy — avoid for new projects

OAuth 2.0 Authorization Code Flow, Step by Step

The earlier overview gave you the plain-English version. Here's what actually travels across the wire in the most common OAuth flow — the authorization code flow — so you can follow it in documentation and debugging sessions:

Step 1: Redirect the user to the provider

Your app sends the user to the provider's authorization page with your app's ID, what you're asking for, and where to come back:

https://accounts.google.com/o/oauth2/auth
  ?client_id=YOUR_CLIENT_ID
  &redirect_uri=https://yourapp.com/oauth/callback
  &response_type=code
  &scope=https://www.googleapis.com/auth/calendar.readonly
  &state=RANDOM_STRING

The state parameter is a random value your app generates — it prevents cross-site request forgery by letting you verify the callback matches the request you sent.

Step 2: User approves, provider returns a code

After the user clicks "Allow," the provider redirects back to your redirect_uri with a short-lived authorization code: https://yourapp.com/oauth/callback?code=AUTH_CODE&state=RANDOM_STRING. The code is useless on its own — it's a single-use voucher, not a key.

Step 3: Exchange the code for tokens (server to server)

Your backend POSTs the code to the provider's token endpoint along with your client secret (which never touches the browser):

POST https://oauth2.googleapis.com/token
  grant_type=authorization_code
  &code=AUTH_CODE
  &client_id=YOUR_CLIENT_ID
  &client_secret=YOUR_CLIENT_SECRET
  &redirect_uri=https://yourapp.com/oauth/callback

Step 4: Receive and store tokens

The provider responds with an access token (used for API calls, expires in about an hour) and a refresh token (long-lived, used to mint new access tokens without bothering the user). Store both server-side, encrypted.

Step 5: Refresh silently

When the access token expires, your app exchanges the refresh token for a new access token — no user interaction needed. If the refresh token is revoked (the user disconnects the integration), your app must handle re-authorization gracefully instead of failing silently.

PKCE, briefly: for mobile and single-page apps that can't keep a client secret, OAuth adds PKCE (pronounced "pixy") — a per-request secret handshake that secures the code exchange without a stored secret. If your docs mention PKCE, that's why.

Generating and Storing API Keys Securely

Getting a key is easy; keeping it safe is the actual skill. The pattern every professional setup follows:

  1. Generate in the provider's dashboard — never invent your own. Note whether it's a test key (sk_test_...) or live key (sk_live_...); use test keys everywhere except production.
  2. Put it in a .env file, never in code:
    # .env (add this filename to .gitignore!)
    STRIPE_SECRET_KEY=sk_live_51H7x9a2b...
    OPENAI_API_KEY=sk-proj-abc123...
  3. Load it with a library like python-dotenv so code reads os.environ["STRIPE_SECRET_KEY"] — the key lives in the environment, not the repository.
  4. Add .env to .gitignore on day one. The most common leak in existence is a key committed to git "temporarily."
  5. On servers, prefer a secrets manager (AWS Secrets Manager, HashiCorp Vault, or your platform's built-in vault) over plain environment variables — you get rotation, audit logs, and access control for free.

The same principle applies in no-code tools through their built-in credential vaults — n8n, for example, encrypts credentials at rest and never displays them in plain text. Our n8n implementation service sets these vaults up correctly as part of every engagement.

Decoding a JWT by Hand

A JWT looks like three blobs separated by dots: xxxxx.yyyyy.zzzzz. Each part is base64-encoded, and the middle one — the payload — is just JSON you can read:

echo "eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ" | base64 -d
# {"sub":"1234567890","name":"John Doe","iat":1516239022}

The three parts:

  • Header — the signing algorithm (e.g., RS256).
  • Payload — claims: who the token is for (sub), when it expires (exp), what it's allowed to do (scope).
  • Signature — proves the first two parts weren't tampered with. Only the issuer can produce a valid signature.

Paste any JWT into jwt.io to decode it in your browser — useful when debugging "why is this token rejected" (nine times out of ten, the exp claim shows it's expired). Remember: signed is not encrypted. Anyone holding the token can read the payload, so never put secrets in JWT claims.

Rotating Keys Without Downtime

"Rotate immediately if a key leaks" is easy advice; doing it without breaking production takes a plan. The safe pattern is overlapping validity:

  1. Generate the new key in the provider's dashboard. Don't revoke the old one yet.
  2. Deploy the new key everywhere the old one is used — servers, CI pipelines, no-code credential vaults. Keep a checklist of every location; this is where most rotations fail.
  3. Verify by watching logs and error rates for 24 hours. Both keys work during this window, so there's no pressure.
  4. Revoke the old key only after verification. Then watch the logs once more — any error spike means you missed a location.

Make rotation routine, not just incident-driven: quarterly for production keys, with a calendar reminder and an owner. A leaked key you rotate every 90 days anyway is a shrug; a leaked key that's been valid for three years is a crisis.

FAQs

Q: API keys or OAuth — how do I choose?

A: If it's your own script talking to a service, API keys. If users connect their accounts to your app, OAuth. If you're choosing a vendor and both are offered, keys mean a faster, cheaper integration; OAuth means more setup but proper per-user permissions.

Q: Where should my team keep shared API keys?

A: A team password manager (1Password, Bitwarden) with access limited to people who need it — never Slack, email, or a shared doc. For keys used by automations rather than humans, put them in the automation platform's credential vault, not alongside the workflow definition.

Q: What exactly is a refresh token?

A: A long-lived credential whose only job is to mint new short-lived access tokens. Access tokens do the actual API work and expire quickly (limiting damage if leaked); refresh tokens stay valid for months and are stored securely server-side. When a user "disconnects" an integration, the app's refresh token is revoked.

Q: A key got committed to a public GitHub repo. Beyond revoking, what else?

A: Revoke first, then: check the provider's usage logs for the exposure window; assume the key was scraped within minutes (bots watch public commits); enable GitHub secret scanning and push protection so it can't happen again; audit whether the same key or pattern was reused anywhere else; and tell the team what changed in the process — blameless, but documented.

Practical Advice for Business Owners

  • When evaluating a tool, check its API docs for authentication — key-based auth means faster, cheaper integrations
  • Never email API keys or paste them into chat — treat them like passwords
  • Ask vendors about scopes: can you create a key that only reads data, not deletes it? Least privilege matters
  • If an integration needs OAuth, budget extra time — the approval flow and token refresh logic add complexity

Storing Secrets Safely

Where API keys live matters as much as how they work:

  • Local scripts: .env files loaded with python-dotenv — never hardcode keys in .py files
  • Servers: environment variables or a secrets manager (AWS Secrets Manager, HashiCorp Vault)
  • n8n/Zapier: built-in credential vaults — encrypted at rest, never shown in plain text
  • Teams: a shared password manager (1Password, Bitwarden) — never Slack, email, or chat
  • Never: in git repos, in frontend JavaScript, in screenshots, in URLs

Understanding OAuth Scopes

OAuth lets you limit what an app can do — these limits are called scopes. When connecting Google Drive, you might grant drive.readonly (see files) instead of drive (full access including delete). Always request the narrowest scope that works. If a vendor asks for full access when read-only would do, that's a red flag worth questioning.

JWT Tokens: What's Inside

Many modern APIs use JWT (JSON Web Tokens) — long strings with three dot-separated parts. The middle part is base64-encoded JSON you can actually decode (try jwt.io) to see what's inside: user ID, expiry time, permissions. They're signed so they can't be tampered with, but they're not encrypted — don't put secrets in them.

What to Do When a Key Leaks

  1. Revoke it immediately in the provider's dashboard — don't wait to "check if it was misused"
  2. Generate a replacement and update every place the old key was used
  3. Check usage logs for suspicious activity during the exposure window
  4. Figure out how it leaked — committed to git? Pasted in chat? Fix the process, not just the key
  5. Rotate related credentials if the same key pattern was reused elsewhere

Set up key rotation as a routine — quarterly for production keys — so a leak is an inconvenience, not a crisis.

Authentication Checklist for New Integrations

  • What auth method does the API use? (key, OAuth, other)
  • Where will the credentials be stored?
  • What's the narrowest scope/permission that works?
  • Do tokens expire? How are they refreshed?
  • Who gets notified if authentication fails in production?
  • Is there a separate sandbox/test API key for development?

Setting up secure API connections across your tools — with proper key management and OAuth flows — is core to what we do. OctaTechno's integration service handles authentication correctly from day one. Get in touch.

#api #security #oauth #authentication
OT
OctaTechno Team Written for OctaTechno — helping teams automate workflows with AI.
✦ Start your project

Ready to automate your workflow?

Tell us about your workflow bottleneck and we'll show you exactly what's automatable.

💬
Need help? Chat with our team in real-time!
OT

OctaTechno Support

Online • Typically replies instantly

Chatting as Guest
Enter your details (optional)
Today
⚡
Welcome to OctaTechno!

Have questions about Enterprise AI, workflow automation, or custom software? Ask us right here!

OT
Support is typing...