Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/tutorials/faq.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ Submit an [application](/request-access) to receive your `client_id` and `client

Include your OAuth2 access token in the `x-auth-token` header and your client ID in the `x-client-id` header when calling authenticated endpoints.

For web apps, the recommended pattern is to store the user session in your backend or secure `httpOnly` cookies and have your backend or serverless proxy send `x-auth-token` and `x-client-id` to Quran Foundation.

## Why does the same request work in curl but fail in the browser?
Comment thread
basit3407 marked this conversation as resolved.

`curl` usually sends no browser `Origin` header, while browser JavaScript does. If you call a User API directly from page code on a third-party origin, the request can be rejected by the target service's browser-origin policy even when the token itself is valid.

For confidential web integrations, route the resource request through your backend or serverless proxy instead of calling Quran Foundation directly from the page.

## What are the best practices for refresh tokens?

Store refresh tokens securely and reuse them until they expire. Refresh tokens allow you to obtain new access tokens without asking the user to re-authorize.
Expand Down
2 changes: 2 additions & 0 deletions docs/tutorials/oidc/example-integration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ const response = await fetch(
const bookmarks = await response.json();
```

This example keeps the user session on the server and uses the server to send `x-auth-token` and `x-client-id` to Quran Foundation. That is the recommended pattern for confidential web clients. If you move the resource call into frontend browser code, you leave that server-side pattern and may run into browser-origin restrictions.

## Accessing Resources

Once authenticated, explore the [User APIs](/docs/category/user-related-apis):
Expand Down
16 changes: 13 additions & 3 deletions docs/tutorials/oidc/getting-started-with-oauth2.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,10 @@ sequenceDiagram
Auth-->>Backend: Token Response<br/>(access_token, refresh_token)
Backend-->>App: Session or token payload

App->>API: Use token to call Quran.Foundation's API
API-->>App: Requested resource
App->>Backend: Request resource
Backend->>API: Use token to call Quran.Foundation's API
API-->>Backend: Requested resource
Backend-->>App: Requested resource
Comment thread
basit3407 marked this conversation as resolved.

Note over App,Backend: Access token expires (1 hour)

Expand Down Expand Up @@ -757,6 +759,8 @@ x-client-id: YOUR_CLIENT_ID

Note: the collections examples below require the `collection` scope, and other User API endpoints may require additional scopes such as `user`. A token granted only `openid offline_access` is sufficient for login and refresh, but not for every User API call.

For confidential web clients, the recommended pattern is to have your backend or serverless proxy send these headers on outbound requests to Quran Foundation. Your app can keep the user session in a server session or secure `httpOnly` cookies while the backend injects `x-auth-token` and `x-client-id`.

<details>
<summary><b>cURL — Get collections</b></summary>

Expand Down Expand Up @@ -822,6 +826,8 @@ Implementation requirements (server-side)
- Build a client wrapper that automatically:
- injects x-auth-token and x-client-id on every request
- targets the correct API base URL from getQfOAuthConfig()
- For web apps, prefer making the resource call from your backend or proxy layer rather than from page JavaScript.
- If you intentionally make the resource call from browser code, the browser origin must still be accepted by the target service.

User API base
- Use apiBaseUrl from config:
Expand Down Expand Up @@ -1007,6 +1013,7 @@ Acceptance checklist
- Scopes: Use `openid offline_access user collection`. Add more scopes only as needed.
- Scopes note: Quran.Foundation expects `offline_access` (not `offline`).
- Token storage: Store `refresh_token` securely; rotate if compromised.
- Browser-origin policy: Direct browser calls to User APIs require the calling origin to be allowlisted by the target service. If your origin is not allowlisted, call the API from your backend instead.
- Clock skew: Ensure system time is correct (e.g., via NTP) to avoid `invalid_grant` due to time drift.

> Do not mix tokens across environments. A token from Pre-Production will not work on Production, and vice versa.
Expand Down Expand Up @@ -1054,6 +1061,7 @@ Acceptance checklist
| `redirect_uri_mismatch` | Redirect URI not exact match | Align with registered value |
| `invalid_scope` | Scope misspelled or not allowed | Use valid scopes; request incrementally |
| `401 Unauthorized` (APIs) | Missing/expired token | Send `x-auth-token` and `x-client-id`, refresh token |
| `403 Forbidden` (APIs) | Direct browser call from a restricted origin, or scope/permission is not granted | For web apps, route the request through your backend or proxy; otherwise use a supported browser origin and request the correct scope |

<details>
<summary><b>AI prompt: troubleshooting + safe logs</b></summary>
Expand All @@ -1071,6 +1079,8 @@ User API errors
- 401: missing/expired token:
- refresh once (if refresh_token exists), retry once
- if still failing, require re-auth (do not loop)
- 403: browser origin not allowlisted:
- move the resource call to your backend, or use an origin the target service allows
- 403: scope/permission not granted:
- hide/disable feature and prompt user for correct consent

Expand Down Expand Up @@ -1131,7 +1141,7 @@ x-auth-token: YOUR_ACCESS_TOKEN
x-client-id: YOUR_CLIENT_ID
```

See [Step 4: Call User APIs with Headers](#step-4-call-user-apis-with-headers) for complete examples in cURL, JavaScript, and Python.
For web apps, your backend or serverless proxy should usually be the component that sends these headers to Quran Foundation. See [Step 4: Call User APIs with Headers](#step-4-call-user-apis-with-headers) for complete examples in cURL, JavaScript, and Python.

### I'm getting `invalid_client` — what's wrong?

Expand Down
11 changes: 11 additions & 0 deletions docs/tutorials/oidc/user-apis-quickstart.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ Quran Foundation User APIs use OAuth2 Authorization Code flow with PKCE and Open

This pattern gives you OAuth2 and OpenID Connect without embedding secrets in a mobile app or browser app. It also keeps the integration aligned with how most Request Access clients are provisioned today.

For web apps, the recommended shape is:

- keep token exchange and refresh on your backend
Comment thread
basit3407 marked this conversation as resolved.
- keep the app's user session in secure server storage or `httpOnly` cookies
Comment thread
basit3407 marked this conversation as resolved.
- have your backend or serverless proxy send `x-auth-token` and `x-client-id` when calling Quran Foundation User APIs

Direct browser calls from third-party origins are not the recommended web pattern and may be rejected by CORS allowlisting or other origin allowlist checks.

## Choose Your Platform

Use the quickstart guidance on this page for the architecture decision, then jump to the guide that matches your stack.
Expand Down Expand Up @@ -87,6 +95,8 @@ const response = await fetch(
const bookmarks = await response.json();
```

For web apps, this request is typically made by your backend or serverless proxy, not by page JavaScript. Cookies are for your app's own session; `x-auth-token` and `x-client-id` are the headers your server sends to Quran Foundation.

## Quick Reference

### Common scopes
Expand Down Expand Up @@ -120,6 +130,7 @@ Request only the scopes your app actually needs.
- Mixing prelive and production OAuth2 environments.
- Requesting more scopes than your app needs.
- Treating the `id_token` as an API access token instead of using the `access_token`.
- Calling User APIs directly from browser JavaScript in a confidential web integration instead of routing the request through your backend or proxy.

## AI Handoff Prompt

Expand Down