OAuth 1.0 Authorization Flow — Step by Step

Walk through the complete OAuth 1.0 authorization flow from registration to protected resource access — with consistent concrete examples, callback URL mechanics, the verifier, and the browser's role at every stage.

Before We Begin

In the previous parts, you learned:

  • Why OAuth exists — to eliminate password sharing.
  • What the seven credentials are and what each one proves.

Now we walk through the complete protocol flow, step by step, using concrete values at every stage.

You can watch the same flow as a step-by-step simulation. It uses these credentials: photo-app-123, SECRET_APP, REQUEST_ABC, and ACCESS_123.

Our Running Example

Actors

EntityRole
AliceResource Owner (user)
PhotoAppConsumer (third-party application)
PhotoProviderService Provider

Credentials (as they are issued)

CredentialValue
consumer_keyphoto-app-123
consumer_secretSECRET_APP
request_tokenREQUEST_ABC
request_token_secretREQUEST_SECRET
oauth_verifierVERIFIER_XYZ
access_tokenACCESS_123
access_token_secretACCESS_SECRET

Complete Flow Overview

The OAuth 1.0 authorization process consists of six stages:

  1. Application Registration (one-time setup)
  2. Request Token (server-to-server)
  3. User Authorization (browser)
  4. Callback + Verifier (browser → server)
  5. Access Token Exchange (server-to-server)
  6. Protected Resource Access (server-to-server)
PhotoProvider (Service Provider)PhotoApp (Consumer)Alice's BrowserPhotoProvider (Service Provider)PhotoApp (Consumer)Alice's Browser0. Application Registration1. Request Token2. User Authorization3. Callback + Verifier4. Access Token Exchange5. Protected Resource AccessAliceRegister application1consumer_key + consumer_secret2Signed Request Token request3Verify signature4request_token + request_token_secret5Redirect to PhotoProvider6Authorization page + request_token7Login page8Enter credentials9Submit credentials10Authenticate Alice11Consent screen12Click "Allow"13Approve14Redirect to PhotoApp callback15request_token + oauth_verifier16Signed request + request_token + verifier17Validate request_token18Validate verifier19Verify signature20access_token + access_token_secret21Sign API request22Signed GET /photos23Validate token + signature24Alice's photos25Alice

Now let’s examine each stage in detail.


Step 0 — Application Registration

Before any OAuth flow can happen, PhotoApp must register with PhotoProvider.

This is a one-time setup, not part of the per-user flow.

What Happens

PhotoApp’s developer visits PhotoProvider’s developer portal and registers the application. During registration, PhotoApp provides:

  • Application Name: PhotoApp
  • Description: Photo editing and collage application
  • Callback URL: https://photoapp.example.com/oauth/callback

PhotoProvider responds with application credentials:

  • consumer_key = photo-app-123
  • consumer_secret = SECRET_APP

What Each Actor Knows After This Step

ActorKnowledge
PhotoApp✅ consumer_key = photo-app-123
✅ consumer_secret = SECRET_APP
PhotoProvider✅ consumer_key = photo-app-123
✅ consumer_secret = SECRET_APP
✅ callback_url = https://photoapp.example.com/oauth/callback
Alice(nothing — she hasn’t interacted with anything yet)

Step 1 — Obtain a Request Token

Alice clicks “Connect my PhotoProvider account” inside PhotoApp. Behind the scenes, PhotoApp starts the OAuth process.

What Happens

PhotoApp sends a signed server-to-server request to PhotoProvider:

POST /oauth/request_token HTTP/1.1
Host: photoprovider.example.com

Authorization: OAuth
  oauth_consumer_key="photo-app-123",
  oauth_signature_method="HMAC-SHA1",
  oauth_timestamp="1780000000",
  oauth_nonce="7d8f3a2b",
  oauth_callback="https://photoapp.example.com/oauth/callback",
  oauth_signature="..."

The signature is computed using the Consumer Secret (SECRET_APP). We will cover signing in detail in Part 4.

How PhotoProvider Responds

PhotoProvider verifies:

  1. Is photo-app-123 a registered application?
  2. Is the signature valid (using its copy of SECRET_APP)?

If both checks pass, PhotoProvider creates a temporary Request Token and responds:

HTTP/1.1 200 OK

oauth_token=REQUEST_ABC
&oauth_token_secret=REQUEST_SECRET
&oauth_callback_confirmed=true

What Each Actor Knows After This Step

ActorKnowledge
PhotoApp✅ consumer_key = photo-app-123
✅ consumer_secret = SECRET_APP
✅ request_token = REQUEST_ABC (NEW)
✅ request_token_secret = REQUEST_SECRET (NEW)
PhotoProvider✅ consumer_key = photo-app-123
✅ consumer_secret = SECRET_APP
✅ request_token = REQUEST_ABC (NEW, stored, linked to photo-app-123)
✅ request_token_secret = REQUEST_SECRET (NEW)
Alice(still nothing — this was server-to-server)

The Request Token does not grant access to Alice’s photos. It is a placeholder for an authorization process that has not yet been approved.


Step 2 — User Authorization

This is the step where Alice gets involved. And it is critical to understand who logs in where.

Who Logs In Where

  • CORRECT: Alice ──────► PhotoProvider (username + password)
  • NOT: Alice ──────► PhotoApp ──────► PhotoProvider (password)

Alice logs in directly at PhotoProvider. PhotoApp never sees, handles, or proxies Alice’s password.

What Happens

Step 2a — PhotoApp redirects Alice’s browser.

PhotoApp constructs a URL and sends Alice’s browser there:

HTTP/1.1 302 Found
Location: https://photoprovider.example.com/oauth/authorize
          ?oauth_token=REQUEST_ABC

Alice’s browser navigates to PhotoProvider.

Step 2b — Alice logs in at PhotoProvider.

PhotoProvider displays its own login page. Alice enters her PhotoProvider username and password directly into PhotoProvider’s website.

PhotoProvider Login Username: [ [email protected] ] Password: [ •••••••• ]

[ Log In ]

PhotoProvider authenticates Alice. This is authentication — verifying Alice’s identity.

Step 2c — Alice reviews the consent screen.

After login, PhotoProvider shows Alice what PhotoApp is asking for:

PhotoProvider PhotoApp wants permission to:

  • ✓ Read your photos
  • ✓ View your albums

[ Allow ]     [ Deny ]

This is authorization — Alice is granting (or denying) permission.

(Note: The exact permissions shown on the consent screen are provider-specific; OAuth 1.0 does not define a universal scope mechanism like OAuth 2.0.)

Step 2d — Alice clicks “Allow”.

Alice approves. PhotoProvider now knows:

  • Alice (authenticated user) has authorized
  • the Request Token REQUEST_ABC (which is linked to PhotoApp)
  • for the requested permissions.

The Browser’s Role

The browser is the transport mechanism, not an actor in the protocol:

PhotoProviderAlice's BrowserPhotoAppPhotoProviderAlice's BrowserPhotoAppAlice types her passwordinto the browserNOT into PhotoAppredirect URLGET /authorizelogin pagecredentialsconsent screen"Allow"

PhotoApp told the browser where to go. Alice interacted with PhotoProvider through her browser. PhotoApp was not involved during the login and consent steps.

What Each Actor Knows After This Step

ActorKnowledge
PhotoApp✅ consumer_key = photo-app-123
✅ consumer_secret = SECRET_APP
✅ request_token = REQUEST_ABC
✅ request_token_secret = REQUEST_SECRET
❌ Alice’s password (never received)
PhotoProvider✅ consumer_key = photo-app-123
✅ consumer_secret = SECRET_APP
✅ request_token = REQUEST_ABC (now marked as “authorized by Alice”)
✅ request_token_secret = REQUEST_SECRET
✅ Alice’s identity = authenticated
✅ oauth_verifier = VERIFIER_XYZ (NEW, created, linked to REQUEST_ABC)
Alice✅ She knows she approved PhotoApp
❌ She does not know any OAuth credentials

Step 3 — Callback + Verifier

After Alice approves, PhotoProvider redirects her browser back to PhotoApp.

What Is the Callback URL?

The callback URL is a URL that PhotoApp registered with PhotoProvider during application registration.

callback_url = https://photoapp.example.com/oauth/callback
QuestionAnswer
What is it?A URL on PhotoApp’s server that receives the authorization result
Why does it exist?So PhotoProvider can return authorization information to PhotoApp through the browser redirect
Who invokes it?PhotoProvider, by redirecting Alice’s browser to it
Why must it be associated with the Consumer?To prevent an attacker from substituting a different callback and intercepting the verifier
What information comes back through it?The Request Token and the OAuth Verifier

What Happens

PhotoProvider redirects Alice’s browser:

HTTP/1.1 302 Found
Location: https://photoapp.example.com/oauth/callback
          ?oauth_token=REQUEST_ABC
          &oauth_verifier=VERIFIER_XYZ

Alice’s browser follows this redirect and makes a request to PhotoApp’s callback URL.

PhotoAppAlice's BrowserPhotoProviderPhotoAppAlice's BrowserPhotoProviderredirect to callbackGET /oauth/callback?oauth_token=REQUEST_ABC&oauth_verifier=VERIFIER_XYZ

PhotoApp now has the oauth_verifier = VERIFIER_XYZ.

Why the Verifier Exists

The Request Token alone is not proof that Alice approved the request. Here’s why:

Without verifier:

  1. PhotoApp obtains Request Token
  2. User authorization somehow happens
  3. PhotoApp exchanges Request Token for Access Token

Problem: How does PhotoProvider know the exchange request corresponds to an actual user approval?

The verifier solves this:

With verifier:

  1. PhotoApp obtains Request Token
  2. Alice approves → PhotoProvider creates VERIFIER_XYZ
  3. VERIFIER_XYZ is delivered to PhotoApp through the callback
  4. PhotoApp presents VERIFIER_XYZ during the exchange

PhotoProvider can verify:

  • REQUEST_ABC was approved
  • VERIFIER_XYZ was created for that approval
  • The exchange request includes the matching verifier

The verifier binds the user’s approval to the token exchange. It confirms that the provider issued an authorization result for that Request Token and that the Consumer presenting it can complete the exchange.

What If the Request Token Is Stolen?

Suppose an attacker intercepts REQUEST_ABC. What can they do?

Scenario: Request Token is stolen Result: Can the attacker get an Access Token? NO. Here’s why:

  1. Request Token ≠ Access Token: It does not grant resource access by itself.
  2. User authorization is still required: The Request Token alone is insufficient to complete the Access Token exchange. The attacker would still need the required secrets and the authorization result associated with that token.
  3. The verifier is needed: Even if the Request Token is somehow authorized, the verifier is delivered to PhotoApp’s registered callback URL, not to the attacker.
  4. The exchange request must be signed: The attacker doesn’t have the Consumer Secret or the Request Token Secret to sign the exchange request.
  5. HTTPS protects the flow in transit: The Request Token was delivered over HTTPS, making interception much harder.

The Request Token is designed to be low-value if compromised. It is temporary, requires additional credentials and user action to be useful, and expires quickly.

What Each Actor Knows After This Step

ActorKnowledge
PhotoApp✅ consumer_key = photo-app-123
✅ consumer_secret = SECRET_APP
✅ request_token = REQUEST_ABC
✅ request_token_secret = REQUEST_SECRET
✅ oauth_verifier = VERIFIER_XYZ (NEW)
PhotoProvider✅ consumer_key = photo-app-123
✅ consumer_secret = SECRET_APP
✅ request_token = REQUEST_ABC (now authorized by Alice)
✅ request_token_secret = REQUEST_SECRET
✅ oauth_verifier = VERIFIER_XYZ (linked to REQUEST_ABC)
Alice✅ She approved the request
(Her part in the flow is done)

Step 4 — Exchange Request Token for Access Token

PhotoApp now has everything it needs: the Request Token, the Verifier, and its own secrets.

What Happens

PhotoApp sends a signed server-to-server request to PhotoProvider:

POST /oauth/access_token HTTP/1.1
Host: photoprovider.example.com

Authorization: OAuth
  oauth_consumer_key="photo-app-123",
  oauth_token="REQUEST_ABC",
  oauth_verifier="VERIFIER_XYZ",
  oauth_signature_method="HMAC-SHA1",
  oauth_timestamp="1780000060",
  oauth_nonce="9c4e1d5f",
  oauth_signature="..."

The signature for this request is computed using:

Signing Key = consumer_secret & request_token_secret
            = SECRET_APP & REQUEST_SECRET

How PhotoProvider Validates

PhotoProvider performs multiple checks:

  1. Is oauth_consumer_key valid?
    • Look up photo-app-123
    • ✅ Found
  2. Is oauth_token valid?
    • Look up REQUEST_ABC
    • ✅ Found, and it belongs to photo-app-123
  3. Has REQUEST_ABC been authorized by a user?
    • ✅ Alice authorized it
  4. Is oauth_verifier correct?
    • Compare VERIFIER_XYZ with the stored verifier for REQUEST_ABC
    • ✅ Match
  5. Is the signature valid?
    • Recalculate using SECRET_APP & REQUEST_SECRET
    • Compare with the received signature
    • ✅ Match

All checks pass → Issue Access Token

Response

PhotoProvider creates the Access Token and responds:

HTTP/1.1 200 OK

oauth_token=ACCESS_123
&oauth_token_secret=ACCESS_SECRET

PhotoProvider also invalidates the Request Token. It can never be used again.

What Each Actor Knows After This Step

ActorKnowledge
PhotoApp✅ consumer_key = photo-app-123
✅ consumer_secret = SECRET_APP
❌ request_token = REQUEST_ABC (INVALIDATED)
❌ request_token_secret = REQUEST_SECRET (INVALIDATED)
❌ oauth_verifier = VERIFIER_XYZ (USED, no longer needed)
✅ access_token = ACCESS_123 (NEW)
✅ access_token_secret = ACCESS_SECRET (NEW)
PhotoProvider✅ consumer_key = photo-app-123
✅ consumer_secret = SECRET_APP
✅ access_token = ACCESS_123 (linked to Alice + photo-app-123)
✅ access_token_secret = ACCESS_SECRET

Step 5 — Access Protected Resources

PhotoApp can now access Alice’s photos.

What Happens

PhotoApp constructs a signed API request:

GET /photos HTTP/1.1
Host: api.photoprovider.example.com

Authorization: OAuth
  oauth_consumer_key="photo-app-123",
  oauth_token="ACCESS_123",
  oauth_signature_method="HMAC-SHA1",
  oauth_timestamp="1780000120",
  oauth_nonce="b2a8c7e4",
  oauth_signature="..."

The signature for this request is computed using:

Signing Key = consumer_secret & access_token_secret
            = SECRET_APP & ACCESS_SECRET

How PhotoProvider Validates

  1. Is the Access Token valid? → Look up ACCESS_123 → ✅ Found, linked to Alice + PhotoApp
  2. Is the timestamp acceptable? → ✅ Within allowed window
  3. Has this nonce been used before? → ✅ Not seen before (no replay)
  4. Is the signature valid? → Recalculate using SECRET_APP & ACCESS_SECRET → Compare with received signature → ✅ Match
  5. Does ACCESS_123 have permission for GET /photos? → ✅ Alice authorized photo read access

All checks pass → Return the resource

Response

HTTP/1.1 200 OK
Content-Type: application/json

{
  "photos": [
    {"id": "1", "title": "Sunset", "url": "..."},
    {"id": "2", "title": "Mountains", "url": "..."},
    {"id": "3", "title": "Beach", "url": "..."}
  ]
}

PhotoApp receives Alice’s photos without ever knowing her password.


Where Each Credential Exists at Each Stage

This table tracks every credential across the entire flow:

CredentialReg. (0)Req. Token (1)User Auth (2)Callback (3)Token Exch. (4)API Access (5)
consumer_key✅✅——✅✅
consumer_secret✅✅——✅✅
request_token—✅✅✅✅❌
request_token_secret—✅——✅❌
oauth_verifier———✅✅❌
access_token————✅✅
access_token_secret————✅✅

✅ = Active and in use, ❌ = Invalidated / no longer valid, — = Does not exist yet


The Complete Flow — Simplified Diagram

PhotoProviderPhotoAppAlice's BrowserPhotoProviderPhotoAppAlice's BrowserRegisterconsumer_key, consumer_secretRequest Token (signed)request_token, request_token_secretRedirect URLLogin + ConsentRedirect to callbackrequest_token + verifierAccess Token Exchange (signed)access_token, access_token_secretGET /photos (signed)Alice's photos

What Comes Next

You have now seen the complete OAuth 1.0 authorization flow in action — every step, every credential, every actor.

But one critical detail has been glossed over: request signing. Every OAuth request that requires Consumer authentication or access to protected resources is cryptographically signed. How does that work? Why is it necessary? What does it protect against?

In the next part, we will dive deep into the request signing mechanism — the signature base string, HMAC-SHA1, the nonce, timestamps, and replay attack protection.


Key Takeaways

  1. Six stages: Registration → Request Token → User Auth → Callback → Token Exchange → API Access
  2. Alice logs in at PhotoProvider, NOT at PhotoApp. PhotoApp never receives Alice’s password.
  3. The browser is a transport mechanism: PhotoApp → redirect → browser → PhotoProvider, PhotoProvider → redirect → browser → PhotoApp
  4. The callback URL is registered with the Provider to prevent interception of the verifier.
  5. The verifier binds user approval to the token exchange.
  6. A stolen Request Token is low-value: temporary, requires user approval, needs the verifier, and the exchange must be signed.
  7. After exchange, the Request Token is invalidated. Only the Access Token survives.
  8. Every OAuth request that requires Consumer authentication or access to protected resources is signed. Signing is covered in the next part.