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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .optimize-cache.json
Original file line number Diff line number Diff line change
Expand Up @@ -1587,6 +1587,26 @@
"static/images/docs/network/edges-map.png": "12ecc1ea200905ba75eb7cfd17055a156fd51fccf746869a1058f923dfd7ac1b",
"static/images/docs/network/pops-map.png": "205ead599703cf47d0df316db8fcc4f48d5eed01508109fc740d17914275e9ab",
"static/images/docs/network/regions-map.png": "c65f1423ab19c3048bf8bf93117e8f2e1d13a2bc705c00307de7ee821e5668a1",
"static/images/docs/oauth-server/dark/oauth2-server-apps-empty.png": "b81617a77c6489bc93cfe3c118c2fd075eebda850fc5803cba4b1b62792269f1",
"static/images/docs/oauth-server/dark/oauth2-server-apps-list.png": "a0b1a9bcc5708bb48f7d4684d754cfc8af8e666f808e11d00fc42182ee7ccf6e",
"static/images/docs/oauth-server/dark/oauth2-server-create-app.png": "8237a7890f6246661086cf80b7eb6cdbf0b27b4bc1a5cbcf485209ef9a27dfcf",
"static/images/docs/oauth-server/dark/oauth2-server-discovery.png": "e688439f87c4ae73086b76ee094e036d5bddb14b9431aaad5901d281ab3ca413",
"static/images/docs/oauth-server/dark/oauth2-server-secret-created.png": "d675fe574706d58b224ce823c8904145482472f64ab940a8bb37b92fcc33008e",
"static/images/docs/oauth-server/dark/oauth2-server-settings-disabled.png": "ad51d531eaa3736839859097c024bca41a28d1339ceef773e376c06936e040ee",
"static/images/docs/oauth-server/dark/oauth2-server-settings.png": "18da0340416739f803b8c04d66c191e92e7eafa70cd301acb1e269d8dd5a0c81",
"static/images/docs/oauth-server/dark/oauth2-server-token-lifetimes.png": "46743e2f0a3e8c126d590809668a37c2beb1f1c5483002839d9a15eca9e110d4",
"static/images/docs/oauth-server/guide/taskflow-consent.png": "5c4f4cbc6b225c60d5d6e2f1616abe45f0e6b66a5014438961fca98db349bd18",
"static/images/docs/oauth-server/guide/taskflow-login.png": "5d0013b31b211efe4d3a2f6a9f224a5b547d3ef1370e507b9a183bb276fc90e1",
"static/images/docs/oauth-server/guide/vantage-dashboard.png": "b2e95c34ec9c19be090e5f3384e0c3278dd840059b3f015ccdb13a16c135dde1",
"static/images/docs/oauth-server/guide/vantage-landing.png": "dc597717bcc93de02b2e5336a0f05d743ea66e6d91cef40fbdc61f8380577bec",
"static/images/docs/oauth-server/oauth2-server-apps-empty.png": "6f7b5c2021df2db7a3a1c4da3dfcf9b2ff119e98450e755eb64f03263030da0a",
"static/images/docs/oauth-server/oauth2-server-apps-list.png": "e3f38509e45e502f742e7532ae1a19bdd35b0891821b6a81601b7960ff16b38c",
"static/images/docs/oauth-server/oauth2-server-create-app.png": "182c207475ebd8f386d3d1ec522058f23f59cb47d85f4b681889d0dd08eb8cd8",
"static/images/docs/oauth-server/oauth2-server-discovery.png": "5b75f8e780cac92a68fda24a9686ba89ce83d89ac66e5f651428b4c62bb81cbd",
"static/images/docs/oauth-server/oauth2-server-secret-created.png": "5a6d48595018a8faaa26aeafe099c3dda23613a35e49884decbecb0029449168",
"static/images/docs/oauth-server/oauth2-server-settings-disabled.png": "648091d9d81308ab93dd456f172fa1c1977c2fbce9b8aa03893398bdefe10595",
"static/images/docs/oauth-server/oauth2-server-settings.png": "914aa6511caedb568f199eacef837366c523f78125c551afa992e39098707431",
"static/images/docs/oauth-server/oauth2-server-token-lifetimes.png": "895bf62c7f5171c8f244fda37b516760266c47447f2c66c93c3c812139823b96",
"static/images/docs/platform/add-platform.png": "5a05bb9d75a8d5270bfa5e67df7e6de20a9fad174476a112b5bdab72e7bdad30",
"static/images/docs/platform/create-api-key.png": "7661b3845e13704643f8ff4f763faa8e61efb90878c3ffa7466ece0910b8ecab",
"static/images/docs/platform/create-webhook.png": "77e08173da6ac534524e025433cf75e532d853a135944a7c6ba2278357d88b2d",
Expand Down
7 changes: 7 additions & 0 deletions src/routes/docs/Sidebar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,13 @@
href: '/docs/partners/project',
icon: 'icon-briefcase',
isParent: true
},
{
label: 'OAuth server',
href: '/docs/partners/oauth-server',
icon: 'icon-key',
isParent: true,
new: isNewUntil('31 Aug 2026')
}
]
},
Expand Down
64 changes: 64 additions & 0 deletions src/routes/docs/partners/oauth-server/+layout.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<script lang="ts">
import Docs from '$lib/layouts/Docs.svelte';
import Sidebar, { type NavParent, type NavTree } from '$lib/layouts/Sidebar.svelte';

const parent: NavParent = {
href: '/docs',
label: 'OAuth server'
};

const navigation: NavTree = [
{
label: 'Getting started',
items: [
{
label: 'Overview',
href: '/docs/partners/oauth-server'
},
{
label: 'Quick start',
href: '/docs/partners/oauth-server/quick-start'
}
]
},
{
label: 'Concepts',
items: [
{
label: 'Clients',
href: '/docs/partners/oauth-server/clients'
},
{
label: 'Authorization',
href: '/docs/partners/oauth-server/authorization'
},
{
label: 'Tokens',
href: '/docs/partners/oauth-server/tokens'
},
{
label: 'Scopes',
href: '/docs/partners/oauth-server/scopes'
},
{
label: 'Device flow',
href: '/docs/partners/oauth-server/device-flow'
}
]
},
{
label: 'Guides',
items: [
{
label: 'Sign in with your product',
href: '/docs/partners/oauth-server/sign-in-with-your-product/step-1'
}
]
}
];
</script>

<Docs variant="two-side-navs">
<Sidebar {navigation} {parent} />
<slot />
</Docs>
68 changes: 68 additions & 0 deletions src/routes/docs/partners/oauth-server/+page.markdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
layout: article
title: OAuth server
description: Turn your Appwrite project into an OAuth 2.1 and OpenID Connect provider so third-party apps can sign in with your product.
back: /docs
---

Appwrite can act as an **OAuth 2.1 and OpenID Connect provider**. When you enable the OAuth server on a project, third-party apps register as clients, send your users to a consent screen you host, and receive tokens your project issues. The users in your project become an identity provider that any standards-compliant OAuth or OIDC library can integrate with, the same way apps integrate with "Sign in with Google" or "Sign in with GitHub".

{% only_dark %}
![OAuth2 server settings in the Appwrite Console](/images/docs/oauth-server/dark/oauth2-server-settings.avif)
{% /only_dark %}
{% only_light %}
![OAuth2 server settings in the Appwrite Console](/images/docs/oauth-server/oauth2-server-settings.avif)
{% /only_light %}

This is the inverse of the [OAuth providers](/docs/partners/project/oauth) feature. OAuth providers let your users sign in to your project *with* an external service. The OAuth server lets external services sign their users in *with your project*.

# How it works {% #how-it-works %}

The OAuth server has three moving parts.

1. **The authorization server.** Enabling the server on your project exposes a full set of OIDC endpoints: authorization, token, userinfo, discovery, JWKS, revocation, and introspection. A keypair is generated for your project on first enable and used to sign tokens.
2. **Clients.** Each third-party app registers as a [client](/docs/partners/oauth-server/clients), either confidential (it has a backend that can hold a secret) or public (a browser or mobile app that cannot). Clients declare the redirect URIs they are allowed to return to.
3. **The consent screen.** You host a consent screen at an authorization URL you configure. When a user authorizes a client, Appwrite redirects them to your screen, your screen confirms the grant, and Appwrite issues an authorization code the client exchanges for tokens.

The flow follows the OAuth 2.1 authorization code grant with PKCE, plus the OpenID Connect layer for identity. Because the server is spec-compliant, integrators can point any OAuth or OIDC client library at your project's discovery URL and it works without Appwrite-specific code.

# Standards support {% #standards %}

The server implements the current OAuth 2.1 and OpenID Connect security practices:

- **Authorization code grant with PKCE.** PKCE uses `S256` and is required for public clients. The password grant and the implicit access-token grant are not supported.
- **Refresh tokens with rotation.** Every refresh issues a new refresh token and invalidates the previous one. Reusing an old refresh token revokes the whole token family.
- **Exact redirect URI matching.** A returned redirect URI must exactly match a registered one, with a narrow loopback-port exception for public native clients (RFC 8252).
- **OpenID Connect.** The server issues `id_token` values, serves a discovery document at `/.well-known/openid-configuration`, and publishes signing keys at `/.well-known/jwks.json`.
- **Device authorization grant** (RFC 8628) for input-constrained devices like TVs and CLIs.

# Concepts {% #concepts %}

{% cards %}
{% cards_item href="/docs/partners/oauth-server/quick-start" title="Quick start" %}
Enable the server, register a client, and run your first sign-in end to end.
{% /cards_item %}
{% cards_item href="/docs/partners/oauth-server/clients" title="Clients" %}
Register confidential and public OAuth clients and manage their secrets.
{% /cards_item %}
{% cards_item href="/docs/partners/oauth-server/authorization" title="Authorization" %}
The authorization code flow, PKCE, and hosting your own consent screen.
{% /cards_item %}
{% cards_item href="/docs/partners/oauth-server/tokens" title="Tokens" %}
Access, refresh, and ID tokens, their lifetimes, introspection, and revocation.
{% /cards_item %}
{% cards_item href="/docs/partners/oauth-server/scopes" title="Scopes" %}
The built-in OpenID scopes and the custom scopes your clients can request.
{% /cards_item %}
{% cards_item href="/docs/partners/oauth-server/device-flow" title="Device flow" %}
Authorize TVs, CLIs, and other input-constrained devices.
{% /cards_item %}
{% /cards %}

# Guide {% #guide %}

{% cards %}
{% cards_item href="/docs/partners/oauth-server/sign-in-with-your-product/step-1" title="Sign in with your product" %}
Build a full sign-in with your product experience end to end, from the consent screen to the token exchange.
{% /cards_item %}
{% /cards %}
Loading
Loading