Skip to content

Commit de12416

Browse files
committed
docs(auth): FastAPI quickstart, Microsoft/Entra ID y pasada de veracidad
Añade: - quickstart/fastapi.mdx — proteger una API Python como resource server (PyJWT + PyJWKClient, dependencias de scope, Authorize en /docs). Era el único stack sin ejemplo: validate-access-tokens prometía "lo mismo en Python" sin enseñarlo. - social/microsoft.md — Entra ID, app compartida vs propia, restricción por tenant GUID, y los gotchas reales: sub pairwise, picture inservible de Graph, email_verified false por nOAuth. - compare-authelia.mdx + tabla de alternativas en compare.mdx. Corrige claims que no existen en el producto: - MFA y SSO/SAML se anunciaban como ✅ en las 4 comparativas, pricing, get-started y what-is-a-multi-tenant. No hay ni una línea de ninguno de los dos en el repo de auth. - Apple y Facebook documentaban un connection type inexistente. Facebook pasa a ser el ejemplo trabajado de Custom OAuth2; Apple explica por qué esa vía no le vale (client_secret ES256, sin userinfo, form_post). - connections.md prometía OTP por SMS y conectores Okta/Azure AD; ahora lista los 8 connection_type que existen de verdad. Además: clients.md documenta los campos reales del Client, los tres token_endpoint_auth_method y Dynamic Client Registration; el sidebar recupera las 6 páginas que Nextra tiraba al final sin título.
1 parent c9ba110 commit de12416

24 files changed

Lines changed: 863 additions & 216 deletions

content/auth/_meta.ts

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,36 @@
11
export default {
22
'get-started': 'Get Started',
33
quickstart: 'Quickstarts',
4-
'what-is-a-multi-tenant-identity-server':
5-
'What is a multi-tenant identity server?',
6-
compare: 'Faable Auth vs Auth0, Clerk & Keycloak',
7-
'compare-aws-cognito': 'vs AWS Cognito',
8-
'compare-firebase-auth': 'vs Firebase Authentication',
9-
'compare-supabase-auth': 'vs Supabase Auth',
10-
guides: 'Migration Guides',
4+
features: 'Features',
5+
pricing: 'Pricing',
116
academy: '🎓 Academy (Integrator)',
12-
signup: 'Signup',
7+
blocksSeparator: { type: 'separator', title: 'Building Blocks' },
8+
clients: 'Clients',
9+
connections: 'Connections',
1310
social: 'Social Login',
14-
integrations: 'Integrations',
11+
passwordless: 'Passwordless',
12+
apis: 'APIs',
13+
protocolSeparator: { type: 'separator', title: 'Protocol' },
1514
'oauth-flows': 'OAuth 2.0 Flows',
1615
oidc: 'OpenID Connect',
17-
extensibility: 'Extensibility',
16+
'validate-access-tokens': 'Validate Access Tokens',
17+
usersSeparator: { type: 'separator', title: 'Users & Sessions' },
18+
signup: 'Signup',
1819
'change-email': 'Change Email',
1920
'team-invitations': 'Team Invitations',
2021
'suspend-users': 'Suspend Users',
21-
apis: 'APIs',
22-
'validate-access-tokens': 'Validate Access Tokens',
23-
logs: 'Logs'
22+
logs: 'Logs',
23+
advancedSeparator: { type: 'separator', title: 'Advanced' },
24+
extensibility: 'Extensibility',
25+
'custom-domain': 'Custom Domain',
26+
integrations: 'Integrations',
27+
learnSeparator: { type: 'separator', title: 'Learn & Compare' },
28+
'what-is-a-multi-tenant-identity-server':
29+
'What is a multi-tenant identity server?',
30+
compare: 'Faable Auth vs Auth0, Clerk & Keycloak',
31+
'compare-aws-cognito': 'vs AWS Cognito',
32+
'compare-firebase-auth': 'vs Firebase Authentication',
33+
'compare-supabase-auth': 'vs Supabase Auth',
34+
'compare-authelia': 'vs Authelia',
35+
guides: 'Migration Guides'
2436
}

content/auth/academy/02-tenant-building-blocks.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ From the [Get Started](../get-started.md) guide:
1919
or under your own [custom domain](../custom-domain.md). Everything below hangs off
2020
the account.
2121
- **[Connections](../connections.md)**_sources of users_: database (email +
22-
password), social (Google, GitHub, Apple…), passwordless, or generic OIDC/SAML.
22+
password), social (Google, GitHub, Microsoft…), passwordless, or generic OIDC.
2323
- **[Clients](../clients.md)** — the _applications_ that drive an OAuth flow against
2424
your account. Each has a **Client ID**, optional **Client Secret**, and
2525
**Allowed Callback URLs**.
@@ -65,7 +65,8 @@ screen shows the ones enabled for that client. Connections can be restricted to
6565
specific clients (`enabled_clients`). Types include:
6666

6767
- **Database** — email + password, with a configurable password policy.
68-
- **Social** — Google, GitHub, Apple, Facebook, etc. (see [Social](../social/)).
68+
- **Social** — Google, GitHub, Microsoft, Figma, or any OAuth 2.0 provider via a
69+
Custom OAuth2 connection (see [Social](../social/)).
6970
- **Passwordless** — magic link / OTP ([Passwordless](../passwordless.md)).
7071
- **OIDC / Enterprise** — federate to another identity provider.
7172

content/auth/academy/03-login-and-flows.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ it replaces the client secret as the proof of "I'm the one who asked."
5656
5757
## Social login
5858

59-
A social connection (Google, GitHub, Apple…) is the _same_ Authorization Code flow —
59+
A social connection (Google, GitHub, Microsoft…) is the _same_ Authorization Code flow —
6060
Faable just federates the actual authentication to the provider, then issues _your_
6161
tenant's tokens. To the app, nothing changes. See [Social](../social/).
6262

content/auth/clients.md

Lines changed: 96 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,118 @@
11
---
22
title: Clients
3-
description: Understand how to register and configure application Clients in Faable Auth for web, mobile, and machine-to-machine integrations.
3+
description: Register and configure OAuth Clients in Faable Auth for SPAs, mobile, server-side web apps and machine-to-machine services — callbacks, web origins, refresh token lifetimes, client authentication and Dynamic Client Registration.
44
---
55

66
# Clients
77

8-
In Faable Auth, a **Client** represents an application that needs to authenticate users or request authorization to access APIs. Depending on what you are building, a Client could be a Single Page Application (React, Vue, Angular), a native mobile app (iOS, React Native), a server-side web application (Express, Next.js), or a backend machine-to-machine service.
8+
In Faable Auth, a **Client** represents an application that authenticates users or requests authorization to access APIs: a Single Page Application (React, Vue, Angular), a native mobile app, a server-side web application, or a backend machine-to-machine service.
99

10-
Clients are the entities that initiate the OAuth2 and OpenID Connect flows. You register and manage all your clients directly from the [Faable Dashboard](https://dashboard.faable.com)
10+
Clients are what initiate the OAuth 2.0 and OpenID Connect flows. You manage them from the [Faable Dashboard](https://dashboard.faable.com), or create them programmatically with [Dynamic Client Registration](#dynamic-client-registration).
1111

1212
## Creating a Client
1313

14-
To integrate your application with Faable Auth, the first step is always to register a new Client in the dashboard. When you create a client, Faable Auth generates critical credentials that your app will use to identify itself to the authorization server:
14+
Registering a client generates two credentials:
1515

16-
- **Client ID:** A public, unique identifier for your application. This is safe to expose in client-side code (like a React or Expo app) and is used to tell Faable Auth which application is requesting a login screen.
17-
- **Client Secret:** A confidential string used to authenticate the identity of the application. _This must be kept secure and should never be exposed in public apps (like SPAs or mobile apps)._ It is primarily used by backend services to exchange authorization codes for tokens.
16+
- **Client ID** — a public, unique identifier. Safe to ship in client-side code (React, Expo); it tells Faable Auth which application is asking.
17+
- **Client Secret** — a confidential string that proves the application's identity. _Never expose it in a SPA, a mobile binary, or anything a user can read._ It belongs to backends only.
1818

1919
## Types of Clients
2020

21-
When building with Faable Auth, the architecture of your application dictates how the Client should be configured and which OAuth2 flows it should use:
21+
Your architecture dictates the configuration and the flow:
2222

23-
- **Single Page Web Applications (SPAs):** For frontend apps running entirely in the browser. Since they cannot securely store a Client Secret, they must use the Authorization Code Flow with PKCE.
24-
- **Native / Mobile Apps:** For mobile and desktop applications. Like SPAs, they cannot guarantee the secrecy of credentials and also rely on PKCE for secure authentication.
25-
- **Regular Web Applications:** For traditional server-side applications (like Express MVC or Next.js server components). Because the code runs on a secure backend server, these clients can safely store and utilize a Client Secret during the authentication flow.
26-
- **Machine to Machine (M2M):** For backend services or background workers that need to securely call APIs without any human user involvement. They typically use the Client Credentials flow.
23+
| Client type | Where the code runs | Secret? | Flow |
24+
| ---------------------- | ------------------------------------------------ | ------- | -------------------------------------------------------------- |
25+
| **Single Page App** | The browser (React, Vue, Angular) || [Authorization Code + PKCE](oauth-flows/authorization-code.md) |
26+
| **Native / Mobile** | The user's device (iOS, Android, React Native) || [Authorization Code + PKCE](oauth-flows/authorization-code.md) |
27+
| **Regular Web App** | Your server (Express, Next.js server components) || [Authorization Code](oauth-flows/authorization-code.md) |
28+
| **Machine to Machine** | A backend service or worker, no human involved || [Client Credentials](oauth-flows/client-credentials.md) |
29+
| **Device / TV / CLI** | An input-constrained device || [Device Code](oauth-flows/device-code.md) |
30+
31+
Faable Auth enforces **PKCE with `S256`** — it advertises no other code challenge method — so public clients are covered whether or not a secret is present.
2732

2833
## Client Configuration
2934

30-
Within the dashboard, you can define essential security boundaries for each Client:
35+
### Security boundaries
3136

32-
- **Allowed Callback URLs (Redirect URIs):** A strict whitelist of URLs (e.g., `https://myapp.com/callback`) where Faable Auth is permitted to redirect the user after a successful login. This is a critical security measure to prevent open redirect vulnerabilities.
33-
- **Allowed Logout URLs:** URLs where users can be redirected after they successfully log out of their session.
34-
- **Allowed Web Origins:** Origins (`scheme://host[:port]`, no path — e.g. `http://localhost:5173`) permitted to make cross-origin (CORS) requests to the token and passwordless endpoints for this client. **When the list is empty, any origin is allowed** — set it to lock browser calls down to your app's origins. The account's own auth domain (where the hosted login page lives) is always allowed implicitly, so you only need to list your application origins.
35-
- **Connections:** You have granular control over which authentication methods (e.g., Google login, Passwordless) are enabled for each specific client.
37+
- **Allowed Callback URLs (`callbacks`)** — the whitelist of URLs Faable Auth may redirect to after login (e.g. `https://myapp.com/callback`). Prevents open-redirect abuse.
38+
- **Allowed Logout URLs (`logout_urls`)** where users may be sent after [RP-Initiated Logout](oidc/logout.md).
39+
- **Allowed Web Origins (`web_origins`)** — origins (`scheme://host[:port]`, **no path** — e.g. `http://localhost:5173`) permitted to make cross-origin calls to the token and passwordless endpoints. **When the list is empty, any origin is allowed**; fill it in to lock browser calls down to your own app. Your account's auth domain is always allowed implicitly, so you only list your application origins.
40+
- **Connections** which authentication methods (Google, passwordless, database…) this specific client may use. Set on each [connection](connections.md) via its _Enabled clients_ list.
3641

37-
## Next Steps
42+
### Token lifetimes
43+
44+
| Setting | Effect |
45+
| ------------------------------ | --------------------------------------------------------------------------------------------------------------------------- |
46+
| `refresh_token.token_lifetime` | Lifetime of issued refresh tokens, in seconds. **Default 2592000** (30 days). |
47+
| Access token lifetime | Not a client setting — it comes from the [API](apis.md) the token is issued for (`token_lifetime`), defaulting to 24 hours. |
48+
49+
> `refresh_token.expiration_mode` and `refresh_token.infinite_token_lifetime` exist on the client object for Auth0 compatibility, but are **not enforced today** — only `token_lifetime` governs how long a refresh token lives. Don't rely on them to build a never-expiring session.
50+
51+
### Client authentication at the token endpoint
52+
53+
`POST /oauth/token` accepts three methods, as published in your tenant's [discovery document](oidc):
54+
55+
| `token_endpoint_auth_method` | How the client authenticates | For |
56+
| ---------------------------- | -------------------------------------------------------------- | ----------------------------- |
57+
| `client_secret_basic` | HTTP Basic header with `client_id:client_secret` (the default) | Confidential clients |
58+
| `client_secret_post` | `client_id` + `client_secret` in the form body | Confidential clients |
59+
| `none` | No secret — the PKCE `code_verifier` is the proof | Public SPA and native clients |
60+
61+
### Application metadata
62+
63+
Optional fields, mostly consumed by consent screens and by tooling: `client_uri`, `logo_uri`, `tos_uri`, `policy_uri`, `contacts`, `application_type` (`web` | `native`), `software_id`, `software_version`.
64+
65+
### Front-Channel Logout
3866

39-
Once you have your Client ID and configured your callback URLs, you are ready to write code.
67+
A client may register a `frontchannel_logout_uri`: Faable loads it in a hidden iframe when the user logs out of the OP, so your application can clear its own session. Set `frontchannel_logout_session_required` to `true` and Faable includes `iss` and `sid` on that call, letting you scope the cleanup to the exact session. See [Logout](oidc/logout.md).
68+
69+
## Dynamic Client Registration
70+
71+
Clients can be created over HTTP instead of through the dashboard, per [OIDC Dynamic Client Registration 1.0 / RFC 7591](https://datatracker.ietf.org/doc/html/rfc7591). This is what lets a third-party tool onboard itself against your tenant — MCP clients, IDE integrations and OAuth debuggers commonly expect it.
72+
73+
The endpoint is published in your discovery document as `registration_endpoint`:
74+
75+
```bash
76+
curl -X POST 'https://your-domain.auth.faable.link/oidc/register' \
77+
-H 'content-type: application/json' \
78+
-d '{
79+
"client_name": "My Tool",
80+
"redirect_uris": ["https://tool.example.com/callback"],
81+
"grant_types": ["authorization_code", "refresh_token"],
82+
"response_types": ["code"],
83+
"token_endpoint_auth_method": "client_secret_basic"
84+
}'
85+
```
86+
87+
Response (`201`), per RFC 7591 §3.2.1 — this is the only time the secret is returned:
88+
89+
```json
90+
{
91+
"client_id": "",
92+
"client_secret": "",
93+
"client_id_issued_at": 1751641200,
94+
"client_secret_expires_at": 0,
95+
"redirect_uris": ["https://tool.example.com/callback"],
96+
"client_name": "My Tool",
97+
"grant_types": ["authorization_code", "refresh_token"],
98+
"response_types": ["code"],
99+
"token_endpoint_auth_method": "client_secret_basic",
100+
"application_type": "web"
101+
}
102+
```
103+
104+
Notes on behaviour:
105+
106+
- **`redirect_uris` is the only required field.** Everything else defaults per spec: `grant_types` to `["authorization_code"]`, `response_types` to `["code"]`, `token_endpoint_auth_method` to `client_secret_basic`, `application_type` to `web`.
107+
- **Unsupported metadata is rejected**, not silently accepted. Requesting a grant type Faable doesn't implement returns `400`. Supported grants are `authorization_code`, `refresh_token`, `client_credentials`, `urn:ietf:params:oauth:grant-type:device_code`, `urn:ietf:params:oauth:grant-type:token-exchange` and Auth0's passwordless OTP grant.
108+
- **`client_secret_expires_at` is `0`** — issued secrets don't expire.
109+
- **The client is bound to the tenant resolved from the request host**, so register against the domain you actually want it to live in.
110+
- **`web_origins`** is accepted as a non-standard extra, with the same rules as in the dashboard.
111+
- **Registration is not itself authenticated.** Anyone who can reach your auth domain can create a client in your tenant — a new client grants no access on its own, but if that's not a trade-off you want, keep an eye on `oauth.client.register` entries in your [logs](logs.md).
112+
113+
## Next Steps
40114

41-
- **[Connections](connections.md):** Learn more about the different identity providers you can attach to your clients.
42-
- **[Authorization Code Flow](oauth-flows/authorization-code.md):** Understand the mechanics of the standard login flow.
43-
- **[Quickstart Next.js](quickstart/nextjs.md):** Jump straight into the code and see a full authentication implementation in action.
44-
- **[Quickstart React Native](quickstart/react-native.md):** Jump straight into the code and see a full authentication implementation in action.
115+
- **[Connections](connections.md)** the identity providers you attach to a client.
116+
- **[Authorization Code Flow](oauth-flows/authorization-code.md)** the mechanics of the standard login flow.
117+
- **[APIs](apis.md)** — register the resource servers your clients request tokens for.
118+
- **[Quickstarts](quickstart/nextjs.md)** — jump into working code, including [FastAPI](quickstart/fastapi.md) on the backend side.

0 commit comments

Comments
 (0)