Skip to content

Commit 38ccd84

Browse files
Merge branch 'main' into partners-catalog
2 parents ef6309e + 0c65a80 commit 38ccd84

File tree

6 files changed

+330
-9
lines changed

6 files changed

+330
-9
lines changed
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
---
2+
layout: post
3+
title: "Understanding OAuth2: The backbone of modern authorization"
4+
description: A quick guide to OAuth2, its flows, and when to use each one.
5+
date: 2025-06-12
6+
cover: /images/blog/understand-oauth2/cover.png
7+
timeToRead: 06
8+
author: laura-du-ry
9+
callToAction: true
10+
unlisted: true
11+
category: product
12+
---
13+
14+
In today’s interconnected app ecosystem, users expect seamless, secure access across services. OAuth2 has emerged as the industry standard for handling secure delegated access, making it a critical protocol for developers to understand.
15+
16+
This guide explains OAuth2, how it works, the different flows available, and when to use each one, helping you build secure, scalable authorization experiences.
17+
18+
# What is OAuth2?
19+
20+
OAuth2 is an open standard for authorization. It allows users to grant limited access to their resources on one service to another service without sharing credentials.
21+
22+
Rather than handing out a username and password, users authorize apps to act on their behalf using access tokens. OAuth2 ensures that:
23+
24+
- Apps never directly handle user credentials.
25+
- Users retain control over what permissions they grant.
26+
- Access can be easily revoked.
27+
28+
# Core components of OAuth2
29+
30+
Before diving into the flows, it's important to understand the key players:
31+
32+
- **Resource owner**: The user who authorizes access to their data.
33+
- **Client**: The application requesting access.
34+
- **Authorization server**: Issues access tokens after authenticating the user.
35+
- **Resource server**: Hosts the protected resources.
36+
37+
These components work together to ensure secure authorization across systems.
38+
39+
Refer to the OAuth2 [documentation](/docs/product/auth/oauth2) for complete technical details.
40+
41+
# How OAuth2 works: A simple flow
42+
43+
1. **Authorization request**: The client asks the resource owner for permission.
44+
2. **Authorization grant**: If the user consents, the server issues a grant (authorization code, token, etc.).
45+
3. **Token request**: The client exchanges the grant for an access token.
46+
4. **Resource access**: The client uses the token to access protected resources.
47+
48+
Tokens are typically short-lived and scoped, meaning they only allow the operations the user approved.
49+
50+
# Major OAuth2 flows
51+
52+
OAuth2 offers different "flows" to accommodate various scenarios. Here's a breakdown of the major ones:
53+
54+
## 1. Authorization code flow
55+
56+
**Best for**: Server-side applications
57+
58+
- User authenticates via browser.
59+
- Client receives an authorization code.
60+
- Server exchanges the code for an access token.
61+
62+
**Advantages**:
63+
64+
- Highly secure (authorization code exchanged server-side).
65+
- Supports refresh tokens.
66+
67+
**Typical use cases**:
68+
69+
- Web apps with secure backend servers.
70+
71+
{% call_to_action title="Customer identity without the hassle" description="Add secure authentication for your users in just a couple of minutes." point1="Multiple OAuth providers" point2="Built-in security" point3="Custom roles and permissions" point4="Integrates with your favourite SDK" cta="Contact sales" url="https://appwrite.io/contact-us/enterprise" /%}
72+
73+
74+
## 2. Authorization code flow with PKCE (Proof Key for Code Exchange)
75+
76+
**Best for**: Mobile and SPA (Single Page Applications)
77+
78+
- Similar to Authorization Code Flow, but with an added security layer (PKCE).
79+
- Prevents interception attacks.
80+
81+
**Advantages**:
82+
83+
- Stronger protection for public clients.
84+
85+
**Typical use cases**:
86+
87+
- Mobile apps, SPAs.
88+
89+
## 3. Client credentials flow
90+
91+
**Best for**: Machine-to-machine (M2M) communication
92+
93+
- No user interaction.
94+
- Client authenticates itself to obtain an access token.
95+
96+
**Advantages**:
97+
98+
- Efficient for service-to-service communication.
99+
100+
**Typical use cases**:
101+
102+
- APIs accessed by backend services.
103+
104+
## 4. Implicit Flow (Legacy)
105+
106+
**Best for**: SPAs (historically)
107+
108+
- Tokens returned directly in browser URL.
109+
- Faster but less secure.
110+
111+
**Note**: Now largely replaced by Authorization Code Flow with PKCE due to security risks.
112+
113+
## 5. Device authorization flow
114+
115+
**Best for**: Devices without browsers/keyboards
116+
117+
- User authenticates on a separate device.
118+
- Device polls authorization server for approval.
119+
120+
**Typical use cases**:
121+
122+
- Smart TVs, IoT devices.
123+
124+
[Appwrite Auth](/products/auth) supports all major OAuth2 flows, making it easy to integrate secure authentication into any app
125+
126+
# OAuth2 Tokens: Access and refresh
127+
128+
OAuth2 commonly uses two types of tokens:
129+
130+
- **Access Token**: Grants access to protected resources.
131+
- **Refresh Token**: Used to obtain new access tokens without re-authenticating the user.
132+
133+
Tokens are often JWTs (JSON Web Tokens) containing claims about the user and the permissions granted.
134+
135+
# When to Use OAuth2
136+
137+
- **Third-party integrations**: Allowing users to connect external services securely.
138+
- **APIs**: Protecting APIs from unauthorized access.
139+
- **Mobile and web Apps**: Enabling secure login and data access without managing credentials.
140+
- **B2B applications**: Secure service-to-service communication.
141+
142+
# Common OAuth2 pitfalls
143+
144+
- **Over-scoped tokens**: Granting too many permissions.
145+
- **Insecure storage**: Storing tokens in insecure locations (e.g., localStorage without encryption).
146+
- **Ignoring token expiration**: Failing to handle token refresh flows.
147+
- **Misusing Implicit Flow**: Using legacy flows where better options (PKCE) are available.
148+
149+
# OAuth2: A key enabler of modern security
150+
151+
OAuth2 powers secure, flexible authorization across the modern internet. Understanding its core flows and best practices helps developers build safer, more user-friendly apps.
152+
153+
Choosing the proper OAuth2 flow based on your application's architecture and user needs is critical to balancing security, usability, and scalability.
154+
155+
Ready to explore OAuth2 more deeply? Check
156+
157+
- [Appwrite Authentication docs](/docs/products/auth)
158+
- [Overview of all the OAuth providers](/integrations#auth)
159+
- [Appwrite Authentication overview](/products/auth)

src/routes/docs/advanced/self-hosting/environment-variables/+page.markdoc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ If running in production, it might be easier to use a 3rd party SMTP server as i
109109
| `_APP_STORAGE_S3_ACCESS_KEY` | **version >= 0.13.0** AWS S3 storage access key. Required when the storage adapter is set to S3. You can get your access key from your AWS console. |
110110
| `_APP_STORAGE_S3_SECRET` | **version >= 0.13.0** AWS S3 storage secret key. Required when the storage adapter is set to S3. You can get your secret key from your AWS console. |
111111
| `_APP_STORAGE_S3_REGION` | **version >= 0.13.0** AWS S3 storage region. Required when storage adapter is set to S3. You can find your region info for your bucket from AWS console. |
112-
| `_APP_STORAGE_S3_BUCKET` | **version >= 0.13.0** AWS S3 storage bucket. Required when storage adapter is set to S3. You can create buckets in your AWS console. |
113-
| `_APP_STORAGE_S3_ENDPOINT` | **version >= 1.7.0** Override the S3 endpoint to use an S3-compatible provider. This should just be the host (without 'https://'). |
112+
| `_APP_STORAGE_S3_BUCKET` | **version >= 0.13.0** AWS S3 storage bucket. Required when storage adapter is set to S3 and using path-style requests (where the bucket is in the path). You can create buckets in your AWS console. If using virtual-hosted-style paths where the bucket is in the endpoint URL, this should be empty. |
113+
| `_APP_STORAGE_S3_ENDPOINT` | **version >= 1.7.0** Override the S3 endpoint to use an S3-compatible provider. This should just be the host (without 'https://'). If using virtual-hosted-style paths where the bucket is included in the endpoint (e.g., `bucket-name.s3.amazonaws.com`), `_APP_STORAGE_S3_BUCKET` should be empty. For path-style requests, the endpoint should not include the bucket name and `_APP_STORAGE_S3_BUCKET` should be set. |
114114
| `_APP_STORAGE_DO_SPACES_ACCESS_KEY` | **version >= 0.13.0** DigitalOcean spaces access key. Required when the storage adapter is set to DOSpaces. You can get your access key from your DigitalOcean console. |
115115
| `_APP_STORAGE_DO_SPACES_SECRET` | **version >= 0.13.0** DigitalOcean spaces secret key. Required when the storage adapter is set to DOSpaces. You can get your secret key from your DigitalOcean console. |
116116
| `_APP_STORAGE_DO_SPACES_REGION` | **version >= 0.13.0** DigitalOcean spaces region. Required when storage adapter is set to DOSpaces. You can find your region info for your space from DigitalOcean console. |

src/routes/docs/products/auth/+layout.svelte

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@
9797
label: 'Multi-factor authentication',
9898
href: '/docs/products/auth/mfa'
9999
},
100+
{
101+
label: 'Auth status check',
102+
href: '/docs/products/auth/checking-auth-status'
103+
},
100104
{
101105
label: 'User verification',
102106
href: '/docs/products/auth/verify-user'
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
---
2+
layout: article
3+
title: Checking auth status
4+
description: Learn how to check a user's authentication status in your Appwrite application and handle authentication flow appropriately.
5+
---
6+
7+
One of the first things your application needs to do when starting up is to check if the user is authenticated. This is an important step in creating a great user experience, as it determines whether to show login screens or protected content.
8+
9+
# Check auth with `account.get()`
10+
11+
The recommended approach for checking authentication status is to use the `account.get()` method when your application starts:
12+
13+
{% multicode %}
14+
```client-web
15+
import { Client, Account } from "appwrite";
16+
17+
const client = new Client()
18+
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1')
19+
.setProject('<PROJECT_ID>');
20+
21+
const account = new Account(client);
22+
23+
// Check if user is logged in
24+
async function checkAuthStatus() {
25+
try {
26+
// If successful, user is authenticated
27+
const user = await account.get();
28+
console.log("User is authenticated:", user);
29+
// Proceed with your authenticated app flow
30+
return user;
31+
} catch (error) {
32+
console.error("User is not authenticated:", error);
33+
// Redirect to login page or show login UI
34+
// window.location.href = '/login';
35+
return null;
36+
}
37+
}
38+
39+
// Call this function when your app initializes
40+
checkAuthStatus();
41+
```
42+
```client-flutter
43+
import 'package:appwrite/appwrite.dart';
44+
45+
void checkAuthStatus() async {
46+
final client = Client()
47+
.setEndpoint('https://<REGION>.cloud.appwrite.io/v1')
48+
.setProject('<PROJECT_ID>');
49+
50+
final account = Account(client);
51+
52+
try {
53+
// If successful, user is authenticated
54+
final user = await account.get();
55+
print('User is authenticated: ${user.name}');
56+
// Proceed with your authenticated app flow
57+
} catch (e) {
58+
print('User is not authenticated: $e');
59+
// Redirect to login page or show login UI
60+
}
61+
}
62+
63+
// Call this function when your app initializes
64+
```
65+
```client-android-kotlin
66+
import io.appwrite.Client
67+
import io.appwrite.services.Account
68+
import io.appwrite.exceptions.AppwriteException
69+
70+
class AuthManager {
71+
private val client = Client(context)
72+
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
73+
.setProject("<PROJECT_ID>")
74+
75+
private val account = Account(client)
76+
77+
suspend fun checkAuthStatus(): Boolean {
78+
return try {
79+
val user = account.get()
80+
Log.d("Auth", "User is authenticated: ${user.name}")
81+
// Proceed with your authenticated app flow
82+
true
83+
} catch (e: AppwriteException) {
84+
Log.e("Auth", "User is not authenticated: ${e.message}")
85+
// Redirect to login page or show login UI
86+
false
87+
}
88+
}
89+
}
90+
91+
// Call this function when your app initializes
92+
```
93+
```client-apple
94+
import Appwrite
95+
96+
func checkAuthStatus() {
97+
let client = Client()
98+
.setEndpoint("https://<REGION>.cloud.appwrite.io/v1")
99+
.setProject("<PROJECT_ID>")
100+
101+
let account = Account(client)
102+
103+
Task {
104+
do {
105+
// If successful, user is authenticated
106+
let user = try await account.get()
107+
print("User is authenticated: \(user.name)")
108+
// Proceed with your authenticated app flow
109+
} catch {
110+
print("User is not authenticated: \(error)")
111+
// Redirect to login page or show login UI
112+
}
113+
}
114+
}
115+
116+
// Call this function when your app initializes
117+
```
118+
{% /multicode %}
119+
120+
# Missing scope error
121+
122+
When a user is not authenticated and you call `account.get()`, you might see an error message like:
123+
124+
```
125+
User (role: guests) missing scope (account)
126+
```
127+
128+
This error is telling you that:
129+
1. The current user has the role of "guest" (unauthenticated visitor)
130+
2. This guest user does not have the required permission scope to access account information
131+
3. This is the expected behavior when a user is not logged in
132+
133+
{% info title="Authentication flow" %}
134+
In a typical application flow:
135+
136+
1. Call `account.get()` when your app starts
137+
2. If successful → User is authenticated → Show the main app UI
138+
3. If error → User is not authenticated → Redirect to login screen
139+
{% /info %}
140+
141+
# Best practices
142+
143+
- Call `account.get()` early in your application lifecycle
144+
- Handle both authenticated and unauthenticated states gracefully
145+
- Show appropriate loading states while checking authentication
146+
- Implement proper error handling to avoid showing error messages to users

src/routes/integrations/storage-s3/+page.markdoc

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ isPartner: true
88
isNew: false
99
cover: /images/integrations/storage-s3/cover.png
1010
category: storage
11-
product:
11+
product:
1212
avatar: '/images/integrations/avatars/aws.png'
1313
vendor: AWS
1414
description: 'Amazon S3 is an object storage service that offers industry-leading scalability, data availability, security, and performance.'
15-
platform:
15+
platform:
1616
- 'Self-hosted'
17-
images:
17+
images:
1818
- /images/integrations/storage-s3/cover.png
1919
- /images/integrations/storage-s3/bucket.png
2020
- /images/integrations/storage-s3/access-key.png
@@ -50,10 +50,22 @@ Visit the `.env` file created for your Appwrite instance and update the followin
5050

5151
```bash
5252
_APP_STORAGE_DEVICE=s3
53-
_APP_STORAGE_S3_BUCKET=[BUCKET_NAME]
54-
_APP_STORAGE_S3_REGION=[AWS_REGION]
55-
_APP_STORAGE_S3_ACCESS_KEY=[ACCESS_KEY_ID]
56-
_APP_STORAGE_S3_SECRET=[SECRET_ACCESS_KEY]
53+
_APP_STORAGE_S3_BUCKET=<BUCKET_NAME>
54+
_APP_STORAGE_S3_REGION=<AWS_REGION>
55+
_APP_STORAGE_S3_ACCESS_KEY=<ACCESS_KEY_ID>
56+
_APP_STORAGE_S3_SECRET=<SECRET_ACCESS_KEY>
57+
```
58+
59+
Starting from version 1.7.0, you can also use S3-compatible providers by configuring the endpoint:
60+
61+
```bash
62+
# For path-style requests (bucket in the path)
63+
_APP_STORAGE_S3_ENDPOINT=<PROVIDER_ENDPOINT> # e.g., s3.amazonaws.com (without https://)
64+
_APP_STORAGE_S3_BUCKET=<BUCKET_NAME> # bucket name required here
65+
66+
# OR for virtual-hosted-style paths (bucket in the endpoint)
67+
_APP_STORAGE_S3_ENDPOINT=<BUCKET_NAME>.<PROVIDER_ENDPOINT> # e.g., bucket-name.s3.amazonaws.com
68+
_APP_STORAGE_S3_BUCKET= # leave this empty when bucket is in the endpoint
5769
```
5870

5971
After that, run the following Docker Compose commands in your terminal to restart your Appwrite containers and verify if the changes have been successfully applied:
467 KB
Loading

0 commit comments

Comments
 (0)