Skip to content

Conversation

@buger
Copy link
Member

@buger buger commented Dec 8, 2025

User description

Summary

  • Adds a comprehensive step-by-step example for OAuth 2.0 Authorization Code Grant flow with Tyk as the authorization server
  • Demonstrates the complete SSO implementation including API setup, client registration, authorization flow, and token management
  • Addresses the documentation gap that made it difficult for users to implement OAuth2-secured APIs

Changes Made

  • Added new section "Complete Example: OAuth 2.0 Authorization Code Grant for SSO" to api-management/authentication/oauth-2.mdx
  • Includes 7 steps covering the full flow from API creation to token refresh
  • Provides practical curl commands with sample responses
  • Includes flow summary diagram description and integration notes for identity providers

Test plan

  • Verify MDX renders correctly in Mintlify preview
  • Confirm all curl commands are properly formatted
  • Validate code blocks have correct syntax highlighting
  • Check that internal links work correctly

Resolves: DX-2014

🤖 Generated with Claude Code


PR Type

Documentation


Description

  • Add full OAuth2 Authorization Code example

  • Step-by-step SSO flow with Tyk

  • Include curl commands and responses

  • Add flow summary and IdP notes


Diagram Walkthrough

flowchart LR
  U["User"]:::a
  C["Client App"]:::a
  TG["Tyk Gateway<br/>(/oauth/authorize, /oauth/token)"]:::b
  TD["Tyk Dashboard API"]:::b
  IdP["Identity Server / IdP"]:::c
  API["Upstream API<br/>(httpbin.org)"]:::d

  U -- "login request" --> C
  C -- "authorize (code)" --> TG
  TG -- "redirect to login" --> IdP
  U -- "authenticate & consent" --> IdP
  IdP -- "request auth code" --> TD
  TD -- "issue code" --> IdP
  IdP -- "redirect with code" --> C
  C -- "exchange code for tokens" --> TG
  TG -- "access & refresh tokens" --> C
  C -- "call protected endpoint (Bearer)" --> TG
  TG -- "proxy" --> API

  classDef a fill:#e3f2fd,stroke:#90caf9,color:#0d47a1;
  classDef b fill:#e8f5e9,stroke:#81c784,color:#1b5e20;
  classDef c fill:#fff3e0,stroke:#ffb74d,color:#e65100;
  classDef d fill:#f3e5f5,stroke:#ba68c8,color:#4a148c;
Loading

File Walkthrough

Relevant files
Documentation
oauth-2.mdx
Add complete OAuth2 Authorization Code SSO walkthrough     

api-management/authentication/oauth-2.mdx

  • Add end-to-end Authorization Code grant example
  • Provide curl commands and sample JSON responses
  • Document client registration, token exchange, refresh
  • Add SSO flow summary and IdP integration note
+265/-0 

Add a comprehensive step-by-step example demonstrating the full
OAuth 2.0 Authorization Code Grant flow with Tyk as the authorization
server. This addresses the documentation gap identified in DX-2014.

The example covers:
- API Definition setup with OAuth 2.0 configuration
- OAuth client registration
- Authorization request initiation
- Authorization code request from identity server
- Token exchange for access and refresh tokens
- Accessing protected APIs with the access token
- Token refresh flow

Includes practical curl commands, sample responses, and a flow
summary to help developers successfully implement SSO with Tyk.

Resolves: DX-2014

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@github-actions
Copy link

github-actions bot commented Dec 8, 2025

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 No relevant tests
🔒 Security concerns

Guidance hardening:
Multiple examples use plain HTTP for sensitive endpoints and include Basic auth headers and bearer tokens. While they are placeholders, readers may replicate insecurely. Recommend explicitly stating to use HTTPS, mark secrets/tokens as examples only, and consider masking or shortening tokens. Additionally, verify that including client_secret in the refresh token form data (line 494) matches Tyk’s expected method when Basic auth is already supplied to avoid duplicating credentials.

⚡ Recommended focus areas for review

Possible Inaccuracy

The example suggests the Identity Server calls the Dashboard API to obtain an authorization code, which differs from standard OAuth2 where the authorization endpoint is called directly and requires user context/state. Verify this flow aligns with Tyk’s recommended/secure pattern and clarify roles to avoid confusing readers.

#### Step 4: Identity Server Obtains Authorization Code

After the user authenticates and approves access on the identity server, the identity server requests an authorization code from Tyk:

```bash
curl -X POST http://localhost:3000/api/apis/oauth/<API_ID>/authorize-client \
  -H "Authorization: <DASHBOARD_API_KEY>" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "response_type=code&client_id=c4a3b79a12d34e5f6789ab0c1d2e3f4a&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fidentity-server%2Fcallback"

Response:

{
  "code": "5a4b3c2d1e0f9876543210abcdef1234",
  "redirect_to": "http://localhost:3000/identity-server/callback?code=5a4b3c2d1e0f9876543210abcdef1234"
}

The identity server redirects the user to the callback URL with the authorization code.


</details>

<details><summary><a href='https://github.com/TykTechnologies/tyk-docs/pull/1158/files#diff-07e679aa2a80a762886a1ae8429b1cf1619be9ffe92510ef7fcf23b95e1e6189R445-R495'><strong>Security Headers</strong></a>

Authorization and token endpoints are shown over http with Basic auth and bearer tokens. For docs, consider emphasizing HTTPS-only and avoiding long-lived example tokens to reduce insecure copy/paste patterns.
</summary>

```txt
curl -X POST http://localhost:8080/oauth2-api/oauth/token/ \
  -H "Authorization: Basic YzRhM2I3OWExMmQzNGU1ZjY3ODlhYjBjMWQyZTNmNGE6TVRJek5EVTJOemc1TUdGaVkyUmxabWRvYVdwcmJHMXViM0J4Y25OMGRYWjNlSGw2" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code&client_id=c4a3b79a12d34e5f6789ab0c1d2e3f4a&code=5a4b3c2d1e0f9876543210abcdef1234&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fidentity-server%2Fcallback"

Response:

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U",
  "expires_in": 3600,
  "refresh_token": "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkw",
  "token_type": "bearer"
}

Step 6: Access the Protected API

Use the access token to call the protected API:

curl -X GET http://localhost:8080/oauth2-api/get \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIn0.dozjgNryP4J3jVmNHl0w5N_XgL0n3I9PlFUP0THsR8U"

Response:

{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Host": "httpbin.org",
    "Authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
  },
  "origin": "192.168.1.1",
  "url": "http://httpbin.org/get"
}

Step 7: Refresh the Access Token (Optional)

When the access token expires, use the refresh token to obtain a new one:

curl -X POST http://localhost:8080/oauth2-api/oauth/token/ \
  -H "Authorization: Basic YzRhM2I3OWExMmQzNGU1ZjY3ODlhYjBjMWQyZTNmNGE6TVRJek5EVTJOemc1TUdGaVkyUmxabWRvYVdwcmJHMXViM0J4Y25OMGRYWjNlSGw2" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token&client_id=c4a3b79a12d34e5f6789ab0c1d2e3f4a&client_secret=MTIzNDU2Nzg5MGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6&refresh_token=YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXoxMjM0NTY3ODkw"

</details>

<details><summary><a href='https://github.com/TykTechnologies/tyk-docs/pull/1158/files#diff-07e679aa2a80a762886a1ae8429b1cf1619be9ffe92510ef7fcf23b95e1e6189R310-R349'><strong>Config Accuracy</strong></a>

The OAS `authorizationUrl` and `tokenUrl` are relative paths; confirm Tyk requires/accepts relative URLs in OAS and that the listen path `/oauth2-api/` properly prefixes these during deployment.
</summary>

```txt
    "oauth2": {
      "type": "oauth2",
      "flows": {
        "authorizationCode": {
          "authorizationUrl": "/oauth/authorize",
          "tokenUrl": "/oauth/token",
          "scopes": {}
        }
      }
    }
  }
},
"x-tyk-api-gateway": {
  "info": {
    "name": "OAuth2 Protected API",
    "state": {
      "active": true
    }
  },
  "server": {
    "listenPath": {
      "strip": true,
      "value": "/oauth2-api/"
    },
    "authentication": {
      "enabled": true,
      "securitySchemes": {
        "oauth2": {
          "enabled": true,
          "allowedAuthorizeTypes": ["code"],
          "authLoginRedirect": "http://localhost:3000/identity-server/login",
          "refreshToken": true
        }
      }
    }
  },
  "upstream": {
    "url": "http://httpbin.org/"
  }
}

@github-actions
Copy link

github-actions bot commented Dec 8, 2025

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Switch authorize to GET

Use the correct HTTP method for the authorization endpoint per spec and Tyk
expectations. Authorization requests should be sent via GET with query parameters to
ensure redirects work consistently.

api-management/authentication/oauth-2.mdx [401-404]

-curl -X POST http://localhost:8080/oauth2-api/oauth/authorize/ \
-  -H "Content-Type: application/x-www-form-urlencoded" \
-  -d "response_type=code&client_id=c4a3b79a12d34e5f6789ab0c1d2e3f4a&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fidentity-server%2Fcallback"
+curl -X GET "http://localhost:8080/oauth2-api/oauth/authorize?response_type=code&client_id=c4a3b79a12d34e5f6789ab0c1d2e3f4a&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fidentity-server%2Fcallback"
Suggestion importance[1-10]: 8

__

Why: The OAuth 2.0 authorization endpoint is typically invoked via GET with query parameters; this improves correctness for redirects and matches common expectations, directly fixing a likely issue.

Medium
Remove duplicate client credentials

Avoid sending client_id (and later client_secret) in the body when using HTTP Basic
auth for the token endpoint to prevent conflicting credential sources. Rely solely
on the Authorization header with grant_type, code, and redirect_uri in the body.

api-management/authentication/oauth-2.mdx [445-449]

-curl -X POST http://localhost:8080/oauth2-api/oauth/token/ \
+curl -X POST http://localhost:8080/oauth2-api/oauth/token \
   -H "Authorization: Basic YzRhM2I3OWExMmQzNGU1ZjY3ODlhYjBjMWQyZTNmNGE6TVRJek5EVTJOemc1TUdGaVkyUmxabWRvYVdwcmJHMXViM0J4Y25OMGRYWjNlSGw2" \
   -H "Content-Type: application/x-www-form-urlencoded" \
-  -d "grant_type=authorization_code&client_id=c4a3b79a12d34e5f6789ab0c1d2e3f4a&code=5a4b3c2d1e0f9876543210abcdef1234&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fidentity-server%2Fcallback"
+  -d "grant_type=authorization_code&code=5a4b3c2d1e0f9876543210abcdef1234&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fidentity-server%2Fcallback"
Suggestion importance[1-10]: 7

__

Why: When using Basic auth at the token endpoint, omitting client_id in the body avoids conflicting credentials and aligns with RFC 6749; beneficial for correctness though not strictly mandatory.

Medium
Use absolute OAuth endpoint URLs

Use absolute URLs (including scheme, host, and the API listen path) for the OAuth
endpoints to avoid misrouting behind proxies or when the Gateway is not at root.
This prevents clients and tools from calling incorrect paths during the flow.

api-management/authentication/oauth-2.mdx [313-316]

-"authorizationUrl": "/oauth/authorize",
-"tokenUrl": "/oauth/token",
+"authorizationUrl": "http://localhost:8080/oauth2-api/oauth/authorize",
+"tokenUrl": "http://localhost:8080/oauth2-api/oauth/token",
Suggestion importance[1-10]: 6

__

Why: Using absolute URLs for authorizationUrl and tokenUrl can reduce misrouting in proxied setups and aligns with deployed paths; the change is reasonable and contextually accurate but not critical.

Low

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants