Skip to content
This repository was archived by the owner on Sep 29, 2023. It is now read-only.
Merged
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
95 changes: 69 additions & 26 deletions app/views/docs/authentication.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Accounts can be created in many different ways, such as through an anonymous session, email and password, OAuth authentication, magic URLs, and more.
</p>

<h2><a href="/docs/authentication#account-vs-user-service" id="account-vs-user-service">Account vs User Service</a></h2>
<h2><a href="/docs/authentication#account-vs-user-api" id="account-vs-user-api">Account vs Users API</a></h2>

<p>
The Account API operates in the scope of the currently logged-in account and is usually used in a frontend or mobile app. The Users API is used in backend integrations and operates in an admin scope using an API key with access to all your project users.
Expand Down Expand Up @@ -92,6 +92,10 @@ promise.then(function (response) {
OAuth is another way to authenticate a user using a multi-step process. When using OAuth to authenticate, the authentication request is initiated from the client application. The user is then redirected to an OAuth2 provider to complete the authentication step, and finally, the user is redirected back to the client application. This provides integration with many third-party services that provide their own OAuth integration as a more secure approach than providing a username/password directly.
</p>

<p>
In applications with first-party redirects, using OAuth2 for authentication is preferred.
</p>

<p>
The example below shows you how to authenticate with OAuth2 using the Web SDK and Amazon's OAuth system.
</p>
Expand Down Expand Up @@ -251,34 +255,73 @@ promise.then(function (response) {
Appwrite handles the persistence of the session in a consistent way across SDKs. After authenticating with an SDK, the SDK will persist the session so that the user will not need to log in again the next time they open the app. The mechanism for persistence depends on the SDK.
</p>

<ul>
<li class="margin-bottom-tiny">Web - Uses a session secure cookie and falls back to local storage when a session cookie is not available.</li>
<li class="margin-bottom-tiny">Flutter - Uses a session cookie stored in Application Documents through the path_provider package.</li>
<li class="margin-bottom-tiny">Apple - Uses a session cookie.</li>
<li class="margin-bottom-tiny">Android - Uses a session cookie stored in SharedPreferences.</li>
</ul>
<div class="notice">
<h2>Best Practice</h2>
<p>Only keep user sessions active as long as needed and only maintain <b>one</b> instance of the Client SDK in your app to avoid conflicting session data.</p>
</div>

<table cellspacing="0" cellpadding="0" border="0" class="full margin-bottom-large text-size-small vertical">
<thead>
<tr>
<th style="width: 80px"></th>
<th style="width: 120px">SDK</th>
<th>Persistence Method</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<img src="/images-ee/platforms/web.svg" alt="Logo" height="30" class="force-light sdk-logo margin-start margin-end" />
<img src="/images-ee/platforms/dark/web.svg" alt="Logo" height="30" class="force-dark sdk-logo margin-start margin-end" />
</td>
<td>
Web
</td>
<td>
Uses a session secure cookie and falls back to local storage when a session cookie is not available.
</td>
</tr>
<tr>
<td>
<img src="/images-ee/platforms/flutter.svg" alt="Logo" height="30" class="force-light sdk-logo margin-start margin-end" />
<img src="/images-ee/platforms/dark/flutter.svg" alt="Logo" height="30" class="force-dark sdk-logo margin-start margin-end" />
</td>
<td>
Flutter
</td>
<td>
Uses a session cookie stored in Application Documents through the <b>path_provider</b> package.
</td>
</tr>
<tr>
<td>
<img src="/images-ee/platforms/apple.svg" alt="Logo" height="30" class="force-light sdk-logo margin-start margin-end" />
<img src="/images-ee/platforms/dark/apple.svg" alt="Logo" height="30" class="force-dark sdk-logo margin-start margin-end" />
</td>
<td>
Apple
</td>
<td>
Uses a session cookie stored in <b>UserDefaults</b>.
</td>
</tr>
<tr>
<td>
<img src="/images-ee/platforms/android.svg" alt="Logo" height="30" class="force-light sdk-logo margin-start margin-end" />
<img src="/images-ee/platforms/dark/android.svg" alt="Logo" height="30" class="force-dark sdk-logo margin-start margin-end" />
</td>
<td>
Android
</td>
<td>
Uses a session cookie stored in <b>SharedPreferences</b>.
</td>
</tr>
</tbody>
</table>

<h2><a href="/docs/authentication#security" id="security">Security</a></h2>

<p>
Security is very important to protect users' data and privacy. Appwrite uses a <a href="/docs/permissions">permissions model</a> coupled with user sessions to ensure users only have access to certain information based on the permissions. With Appwrite services, including databases and storage, access is granted at the collection, bucket, document, or file level. This access is consistent across access to these items in relation to document access, file access, and real-time events.
</p>

<h2><a href="/docs/authentication#best-practices" id="best-practices">Best Practices</a></h2>

<p>
Here are some common best practices when handling sessions and keys used for authentication purposes.
</p>

<ol>
<li class="margin-bottom-tiny">Only keep user sessions active as long as needed.</li>
<li class="margin-bottom-tiny">Only grant scopes required for your use case for your APIs keys, and nothing more.</li>
<li class="margin-bottom-tiny">Access Appwrite via HTTPS to prevent any redirects from interfering with your requests.</li>
<li class="margin-bottom-tiny">Prefer using OAuth2 for authentication with first-party redirects.</li>
<li class="margin-bottom-tiny">Generate an SSL certification for the Appwrite instance.</li>
<li class="margin-bottom-tiny">Keep API keys private and out of client-side code.</li>
<li class="margin-bottom-tiny">Only maintain <b>1</b> instance of the Client SDK in your app to avoid conflicting session data.</li>
<li class="margin-bottom-tiny">When using the realtime service to get users' documents, clean up and resubscribe to the correct resources to maintain the correct app state.</li>
<li class="margin-bottom-tiny">Unsubscribing from old resources is also recommended to prevent possible race conditions.</li>
</ol>

8 changes: 4 additions & 4 deletions app/views/docs/index.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,20 @@ $cols = [
</div>

<ul class="margin-bottom">
<li><a href="/docs/authentication">Authentication</a></li>
<li><a href="/docs/realtime">Realtime</a></li>
<li><a href="/docs/databases">Databases</a></li>
<li><a href="/docs/storage">Storage</a></li>
<li><a href="/docs/authentication">Authentication</a></li>
<li><a href="/docs/functions">Functions</a></li>
<li><a href="/docs/keys">API Keys</a></li>
<li><a href="/docs/webhooks">Webhooks</a></li>
<li><a href="/docs/realtime">Realtime</a></li>
</ul>

<div class="margin-bottom-small">
<b class="text-size-small">Advanced</b>
</div>

<ul class="margin-bottom">
<li><a href="/docs/keys">API Keys</a></li>
<li><a href="/docs/webhooks">Webhooks</a></li>
<li><a href="/docs/pagination">Pagination</a></li>
<li><a href="/docs/custom-domains">Custom Domains</a></li>
<li><a href="/docs/permissions">Permissions</a></li>
Expand Down
7 changes: 5 additions & 2 deletions app/views/docs/keys.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ $scopes = $this->getParam('scopes', );

<p>Using your API Keys, you can access Appwrite services using the SDK of your choice. To create a new API key, go to your API keys tab in your project setting using your Appwrite console and click the 'Add API Key' button.</p>

<p>When adding a new API Key, you can choose which permission scope to grant your application. It is a best practice to allow only the permissions you need to meet your project goals.</p>
<p>When adding a new API Key, you can choose which scope to grant your application. If you need to replace your API Key, create a new key, update your app credentials and, once ready, delete your old key.</p>

<p>If you need to replace your API Key, create a new key, update your app credentials and, once ready, delete your old key.</p>
<div class="notice">
<h2>Best Practice</h2>
<p>It is a best practice to grant only the scopes you need to meet your project's goals to an API key. API keys should be treated as a secret. Never share the API key and keep API keys out of client applications.</p>
</div>

<h2 id="scopes">Scopes</h2>

Expand Down
5 changes: 5 additions & 0 deletions app/views/docs/production.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

<p>Make sure to keep this key in a safe place and never make it publicly accessible. There are many online resources with methods of keeping your secret keys safe in your servers.</p>

<div class="notice">
<h2>Best Practice</h2>
<p>You should always prefer <b>https</b> over http in production environments. This keeps your APIs secure and prevents any redirects from interfering with your requests.</p>
</div>

<h2><a href="/docs/production#limitConsoleAccess" id="limitConsoleAccess">Limit Console Access</a></h2>

<p>By default, anyone can signup for your Appwrite server, create projects, and use your computing power. While this is great for testing around or running your Appwrite service in a network isolated environment, it is highly not recommended for public production use.</p>
Expand Down
2 changes: 1 addition & 1 deletion app/views/docs/realtime.phtml
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ realtime.subscribe(channels: ["databases.A.collections.A.documents.A", "files"])

<h3><a href="/docs/realtime#unsubscribe" id="unsubscribe">Unsubscribe</a></h3>

<p>If you no longer want to receive updates from a subscription, you can unsubscribe so that your callbacks are no longer called.</p>
<p>If you no longer want to receive updates from a subscription, you can unsubscribe so that your callbacks are no longer called. Leaving old subscriptions alive and resubscribing can result in duplicate subscriptions and cause race conditions.</p>

<ul class="phases clear" data-ui-phases>
<li>
Expand Down