mirror of
https://github.com/LukeHagar/website.git
synced 2025-12-11 04:22:19 +00:00
fix: more ssr inconsistencies
This commit is contained in:
@@ -34,7 +34,7 @@ npm install node-appwrite
|
|||||||
|
|
||||||
## Create sessions server-side
|
## Create sessions server-side
|
||||||
|
|
||||||
To solve this issue, all existing server SDK methods that create a session now return a `secret` attribute. The following methods are:
|
To solve this issue, all existing server SDK methods that create a session now return a `secret` attribute. The following methods are:
|
||||||
|
|
||||||
- `account.createEmailPasswordSession(email, password)`
|
- `account.createEmailPasswordSession(email, password)`
|
||||||
- `account.createAnonymousSession()`
|
- `account.createAnonymousSession()`
|
||||||
@@ -50,9 +50,9 @@ console.log(session.secret) // Output: 'eyJpZCI...sdfahfkjjy'
|
|||||||
|
|
||||||
## Using session secrets
|
## Using session secrets
|
||||||
|
|
||||||
With a session cookie set, we can now authenticate users and protect routes.
|
With a session cookie set, we can now authenticate users and protect routes.
|
||||||
|
|
||||||
When using the Appwrite SDK, you can use the new `setSession` method to authenticate a user for any request.
|
When using the Appwrite SDK, you can use the new `setSession` method to authenticate a user for any request.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
client.setSession(session.secret)
|
client.setSession(session.secret)
|
||||||
@@ -65,7 +65,7 @@ It’s important to note that the client instance should be re-created for every
|
|||||||
|
|
||||||
## Admin and Session Clients
|
## Admin and Session Clients
|
||||||
|
|
||||||
With the new authentication patterns for SSR, you’ll need to create two different types of instances of an Appwrite client when initializing the SDK. An admin client for performing admin request, and a session client for performing authenticated request on behalf of an end user.
|
With the new authentication patterns for SSR, you’ll need to create two different types of instances of an Appwrite client when initializing the SDK. An admin client for performing admin request, and a session client for performing authenticated request on behalf of an end user.
|
||||||
|
|
||||||
### Admin Client
|
### Admin Client
|
||||||
|
|
||||||
@@ -82,7 +82,7 @@ const adminClient = new Client()
|
|||||||
|
|
||||||
### Session Client
|
### Session Client
|
||||||
|
|
||||||
A session client will allow us to make requests as an authenticated end-user with the `setSession` helper method.
|
A session client will allow us to make requests as an authenticated end-user with the `setSession` helper method.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
const sessionClient = new Client()
|
const sessionClient = new Client()
|
||||||
@@ -118,7 +118,7 @@ import { parseCookie } from "next/dist/compiled/@edge-runtime/cookies";
|
|||||||
export function createAdminClient() => {
|
export function createAdminClient() => {
|
||||||
const client = new Client()
|
const client = new Client()
|
||||||
.setEndpoint(process.env.PUBLIC_APPWRITE_ENDPOINT)
|
.setEndpoint(process.env.PUBLIC_APPWRITE_ENDPOINT)
|
||||||
.setProject(process.env.PUBLIC_APPWRITE_PROJECT_ID)
|
.setProject(process.env.PUBLIC_APPWRITE_PROJECT)
|
||||||
.setKey(process.env.APPWRITE_API_KEY)
|
.setKey(process.env.APPWRITE_API_KEY)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -131,7 +131,7 @@ export function createAdminClient() => {
|
|||||||
export function createSessionClient(headers) {
|
export function createSessionClient(headers) {
|
||||||
const client = new Client()
|
const client = new Client()
|
||||||
.setEndpoint(process.env.PUBLIC_APPWRITE_ENDPOINT)
|
.setEndpoint(process.env.PUBLIC_APPWRITE_ENDPOINT)
|
||||||
.setProject(process.env.PUBLIC_APPWRITE_PROJECT_ID)
|
.setProject(process.env.PUBLIC_APPWRITE_PROJECT)
|
||||||
|
|
||||||
const cookies = parseCookie(headers.get('cookie') ?? '')
|
const cookies = parseCookie(headers.get('cookie') ?? '')
|
||||||
const session = cookies.get('my-session-cookie') ?? ''
|
const session = cookies.get('my-session-cookie') ?? ''
|
||||||
@@ -149,7 +149,7 @@ export function createSessionClient(headers) {
|
|||||||
|
|
||||||
### **Creating a session**
|
### **Creating a session**
|
||||||
|
|
||||||
Now, in the `/signin` route, we can use the admin client to generate a session and set a cookie.
|
Now, in the `/signin` route, we can use the admin client to generate a session and set a cookie.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { createAdminClient } from "@/lib/appwrite"
|
import { createAdminClient } from "@/lib/appwrite"
|
||||||
@@ -175,7 +175,7 @@ export async function POST(request){
|
|||||||
|
|
||||||
### Authenticating requests
|
### Authenticating requests
|
||||||
|
|
||||||
With a session set, we can now use the session client to authenticate a user and return the user object. This session client can now be used on all requests that require an authenticated user.
|
With a session set, we can now use the session client to authenticate a user and return the user object. This session client can now be used on all requests that require an authenticated user.
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
import { createSessionClient } from "@/lib/appwrite"
|
import { createSessionClient } from "@/lib/appwrite"
|
||||||
@@ -194,7 +194,7 @@ export async function GET(request){
|
|||||||
|
|
||||||
# Resources
|
# Resources
|
||||||
|
|
||||||
Visit our documentation to learn more about SSR, join us on Discord to be part of the discussion, visit our blog and YouTube channel to learn more, or visit our GitHub repository to see our source code.
|
Visit our documentation to learn more about SSR, join us on Discord to be part of the discussion, visit our blog and YouTube channel to learn more, or visit our GitHub repository to see our source code.
|
||||||
|
|
||||||
- [Docs](https://appwrite.io/docs/products/auth/server-side-rendering)
|
- [Docs](https://appwrite.io/docs/products/auth/server-side-rendering)
|
||||||
- [Discord](https://appwrite.io/discord)
|
- [Discord](https://appwrite.io/discord)
|
||||||
@@ -202,6 +202,6 @@ Visit our documentation to learn more about SSR, join us on Discord to be part o
|
|||||||
- [YouTube](https://www.youtube.com/channel/UCtBJ1v69gm8NgbCju_03Fiw)
|
- [YouTube](https://www.youtube.com/channel/UCtBJ1v69gm8NgbCju_03Fiw)
|
||||||
- [GitHub repository](https://github.com/appwrite/appwrite)
|
- [GitHub repository](https://github.com/appwrite/appwrite)
|
||||||
|
|
||||||
SSR will be available as part of the Appwrite 1.5 release on [GitHub](https://github.com/appwrite/appwrite) and [Cloud](https://cloud.appwrite.io/register) in March 2024.
|
SSR will be available as part of the Appwrite 1.5 release on [GitHub](https://github.com/appwrite/appwrite) and [Cloud](https://cloud.appwrite.io/register) in March 2024.
|
||||||
|
|
||||||
[Go back to Init](http://appwrite.io/init)
|
[Go back to Init](http://appwrite.io/init)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ step: 4
|
|||||||
Astro middleware are functions that run on the server before a page is displayed to the user. Astro locals are a way to store data that is specific to the current request. We can use these features to store the user's account data, so that it is available to all pages.
|
Astro middleware are functions that run on the server before a page is displayed to the user. Astro locals are a way to store data that is specific to the current request. We can use these features to store the user's account data, so that it is available to all pages.
|
||||||
|
|
||||||
Create a new file in the `src/server` directory called `middleware.js`:
|
Create a new file in the `src/server` directory called `middleware.js`:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// src/server/middleware.js
|
// src/server/middleware.js
|
||||||
import { defineMiddleware } from "astro:middleware";
|
import { defineMiddleware } from "astro:middleware";
|
||||||
@@ -40,7 +41,7 @@ declare namespace App {
|
|||||||
|
|
||||||
interface ImportMetaEnv {
|
interface ImportMetaEnv {
|
||||||
readonly PUBLIC_APPWRITE_ENDPOINT: string;
|
readonly PUBLIC_APPWRITE_ENDPOINT: string;
|
||||||
readonly PUBLIC_APPWRITE_PROJECT_ID: string;
|
readonly PUBLIC_APPWRITE_PROJECT: string;
|
||||||
readonly APPWRITE_KEY: string;
|
readonly APPWRITE_KEY: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,8 +59,8 @@ if (user) {
|
|||||||
return Astro.redirect("/account");
|
return Astro.redirect("/account");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Astro.redirect("/signin");
|
return Astro.redirect("/signup");
|
||||||
---
|
---
|
||||||
```
|
```
|
||||||
|
|
||||||
When a user visits the home page, they will be redirected to the sign in page if they are not logged in, or to the account page if they are logged in.
|
When a user visits the home page, they will be redirected to the sign up page if they are not logged in, or to the account page if they are logged in.
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
---
|
---
|
||||||
layout: tutorial
|
layout: tutorial
|
||||||
title: Create sign in page
|
title: Create sign up page
|
||||||
description: Add authentication to a Astro project using Appwrite.
|
description: Add authentication to a Astro project using Appwrite.
|
||||||
step: 5
|
step: 5
|
||||||
---
|
---
|
||||||
|
|
||||||
We can now implement our sign in page. Create a `signin.astro` file in the `src/pages` directory:
|
We can now implement our sign up page. Create a `signin.astro` file in the `src/pages` directory:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ description: Add authentication to a Astro project using Appwrite.
|
|||||||
step: 6
|
step: 6
|
||||||
---
|
---
|
||||||
|
|
||||||
Now the end-user is able to sign in, we can create the account page. This page will display basic information about the user, and allow the user to log out. Create a new file in the `src/pages` directory called `account.astro` and add the following code:
|
Now the end-user is able to sign up, we can create the account page. This page will display basic information about the user, and allow the user to log out. Create a new file in the `src/pages` directory called `account.astro` and add the following code:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
---
|
---
|
||||||
@@ -14,7 +14,7 @@ import { SESSION_COOKIE, createSessionClient } from "../server/appwrite";
|
|||||||
// Redirect the user if not signed in
|
// Redirect the user if not signed in
|
||||||
const { user } = Astro.locals;
|
const { user } = Astro.locals;
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return Astro.redirect("/signin");
|
return Astro.redirect("/signup");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle form action
|
// Handle form action
|
||||||
@@ -28,8 +28,8 @@ if (Astro.request.method === "POST") {
|
|||||||
// Delete the session cookie
|
// Delete the session cookie
|
||||||
Astro.cookies.delete(SESSION_COOKIE);
|
Astro.cookies.delete(SESSION_COOKIE);
|
||||||
|
|
||||||
// Redirect the user to sign in page
|
// Redirect the user to sign up page
|
||||||
return Astro.redirect("/signin");
|
return Astro.redirect("/signup");
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
---
|
---
|
||||||
layout: tutorial
|
layout: tutorial
|
||||||
title: OAuth2 authentication with SSR
|
title: OAuth authentication with SSR
|
||||||
description: Add authentication to a Astro project using Appwrite.
|
description: Add authentication to a Astro project using Appwrite.
|
||||||
step: 7
|
step: 7
|
||||||
---
|
---
|
||||||
|
|
||||||
To support the OAuth2 flow, we first redirect the user to the OAuth2 provider, and then handle the callback from the OAuth2 provider.
|
To support the OAuth flow, we first redirect the user to the OAuth provider, and then handle the callback from the OAuth provider.
|
||||||
|
|
||||||
To redirect, add a button to our sign in page that redirects the user to the OAuth2 provider.
|
To redirect, add a button to our sign up page that redirects the user to the OAuth provider.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
<!-- src/pages/signin.astro -->
|
<!-- src/pages/signup.astro -->
|
||||||
|
|
||||||
<!-- ... existing sign in form -->
|
<!-- ... existing sign up form -->
|
||||||
|
|
||||||
<form action="/oauth2" method="post">
|
<form action="/oauth2" method="post">
|
||||||
<input type="hidden" name="provider" value="github" />
|
<input type="hidden" name="provider" value="github" />
|
||||||
@@ -31,11 +31,11 @@ export const POST = async ({ redirect, url }) => {
|
|||||||
// Create the Appwrite client
|
// Create the Appwrite client
|
||||||
const { account } = createAdminClient();
|
const { account } = createAdminClient();
|
||||||
|
|
||||||
// Create an OAuth2 token
|
// Create an OAuth token
|
||||||
const redirectUrl = await account.createOAuth2Token(
|
const redirectUrl = await account.createOAuth2Token(
|
||||||
OAuthProvider.Github,
|
OAuthProvider.Github,
|
||||||
`${url.protocol}//${url.hostname}/oauth`,
|
`${url.protocol}//${url.hostname}/oauth`,
|
||||||
`${url.protocol}//${url.hostname}/signin`
|
`${url.protocol}//${url.hostname}/signup`
|
||||||
);
|
);
|
||||||
|
|
||||||
// Redirect the end-user to the OAuth2 provider authentication
|
// Redirect the end-user to the OAuth2 provider authentication
|
||||||
@@ -43,7 +43,7 @@ export const POST = async ({ redirect, url }) => {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
The `createOAuth2Token` method returns a URL to the OAuth2 provider. After authentication the OAuth2 provider redirects the user back to the `/oauth2` route with the `userId` and `secret` URL query parameters.
|
The `createOAuth2Token` method returns a URL to the OAuth provider. After authentication the OAuth provider redirects the user back to the `/oauth2` route with the `userId` and `secret` URL query parameters.
|
||||||
|
|
||||||
Create a new `GET` route to handle the callback and create a session for the user.
|
Create a new `GET` route to handle the callback and create a session for the user.
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ description: Add authentication to a Next.js project using Appwrite.
|
|||||||
step: 5
|
step: 5
|
||||||
---
|
---
|
||||||
|
|
||||||
We can now implement our sign in page. Create a `page.jsx` file in the `src/app/signup` directory:
|
We can now implement our sign up page. Create a `page.jsx` file in the `src/app/signup` directory:
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
// src/app/signup/page.jsx
|
// src/app/signup/page.jsx
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ description: Add authentication to a Next.js project using Appwrite.
|
|||||||
step: 6
|
step: 6
|
||||||
---
|
---
|
||||||
|
|
||||||
Now the end-user is able to sign in, we can create the account page. This page will display basic information about the user, and allow the user to log out. Create a new file in the `src/app/account` directory called `page.jsx` and add the following code:
|
Now the end-user is able to sign up, we can create the account page. This page will display basic information about the user, and allow the user to log out. Create a new file in the `src/app/account` directory called `page.jsx` and add the following code:
|
||||||
|
|
||||||
```jsx
|
```jsx
|
||||||
// src/app/account/page.jsx
|
// src/app/account/page.jsx
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ step: 7
|
|||||||
|
|
||||||
# Enable OAuth provider {% #enable-oauth-provider %}
|
# Enable OAuth provider {% #enable-oauth-provider %}
|
||||||
|
|
||||||
To enable the GitHub OAuth2 provider, navigate to your Appwrite Console > Auth > Settings > OAuth2 Providers > GitHub
|
To enable the GitHub OAuth provider, navigate to your Appwrite Console > Auth > Settings > OAuth2 Providers > GitHub
|
||||||
|
|
||||||
To support the OAuth flow, we first redirect the user to the OAuth provider, and then handle the callback from the OAuth provider.
|
To support the OAuth flow, we first redirect the user to the OAuth provider, and then handle the callback from the OAuth provider.
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ title: Initialize SDK
|
|||||||
description: Add authentication to a Nuxt project using Appwrite.
|
description: Add authentication to a Nuxt project using Appwrite.
|
||||||
step: 3
|
step: 3
|
||||||
---
|
---
|
||||||
Before you can use Appwrite, you need to create the Appwrite `Client` and set the project ID and endpoint.
|
Before you can use Appwrite, you need to create the Appwrite `Client` and set the project ID and endpoint.
|
||||||
The client is then used to create services like `Databases` and `Account`, so they all point to the same Appwrite project.
|
The client is then used to create services like `Databases` and `Account`, so they all point to the same Appwrite project.
|
||||||
|
|
||||||
Create a function to build services you need in a file like `src/lib/server/appwrite.js` and **exporting the instances**.
|
Create a function to build services you need in a file like `src/lib/server/appwrite.js` and **exporting the instances**.
|
||||||
@@ -26,7 +26,7 @@ export const SESSION_COOKIE = "my-custom-session";
|
|||||||
export function createAdminClient() {
|
export function createAdminClient() {
|
||||||
const client = new Client()
|
const client = new Client()
|
||||||
.setEndpoint(process.env.APPWRITE_ENDPOINT!)
|
.setEndpoint(process.env.APPWRITE_ENDPOINT!)
|
||||||
.setProject(process.env.APPWRITE_PROJECT_ID!)
|
.setProject(process.env.APPWRITE_PROJECT!)
|
||||||
.setKey(process.env.APPWRITE_KEY!);
|
.setKey(process.env.APPWRITE_KEY!);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -64,19 +64,21 @@ export default defineNuxtConfig({
|
|||||||
appwriteKey: process.env.APPWRITE_KEY,
|
appwriteKey: process.env.APPWRITE_KEY,
|
||||||
public: {
|
public: {
|
||||||
appwriteEndpoint: process.env.PUBLIC_APPWRITE_ENDPOINT,
|
appwriteEndpoint: process.env.PUBLIC_APPWRITE_ENDPOINT,
|
||||||
appwriteProjectId: process.env.PUBLIC_APPWRITE_PROJECT_ID,
|
appwriteProjectId: process.env.PUBLIC_APPWRITE_PROJECT,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
Now you can use `.env` files to set the environment variables for your project. Retrieve the values for these variables from the Appwrite console.
|
Now you can use `.env` files to set the environment variables for your project. Retrieve the values for these variables from the Appwrite console.
|
||||||
|
|
||||||
|
The `PUBLIC_APPWRITE_ENDPOINT` is the endpoint of your Appwrite project, and the `PUBLIC_APPWRITE_PROJECT` is the ID of the project you want to use.
|
||||||
|
You can get the values for these variables from the Appwrite console.
|
||||||
|
|
||||||
The `PUBLIC_APPWRITE_ENDPOINT` is the endpoint of your Appwrite project, and the `PUBLIC_APPWRITE_PROJECT` is the ID of the project you want to use.
|
|
||||||
You can get the values for these variables from the Appwrite console.
|
|
||||||
{% only_dark %}
|
{% only_dark %}
|
||||||

|

|
||||||
{% /only_dark %}
|
{% /only_dark %}
|
||||||
|
|
||||||
{% only_light %}
|
{% only_light %}
|
||||||

|

|
||||||
{% /only_light %}
|
{% /only_light %}
|
||||||
@@ -85,13 +87,14 @@ The `APPWRITE_KEY` is an Appwrite API key with the necessary permissions to read
|
|||||||
|
|
||||||
For this tutorial you'll need an API key with the following scopes:
|
For this tutorial you'll need an API key with the following scopes:
|
||||||
|
|
||||||
| Category {% width=120 %} | Required scopes | Purpose |
|
| Category {% width=120 %} | Required scopes | Purpose |
|
||||||
|-----------|---------------------|---------|
|
| ------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------ |
|
||||||
| Sessions | `sessions.write` | Allows API key to create, update, and delete sessions. |
|
| Sessions | `sessions.write` | Allows API key to create, update, and delete sessions. |
|
||||||
|
|
||||||
{% only_dark %}
|
{% only_dark %}
|
||||||

|

|
||||||
{% /only_dark %}
|
{% /only_dark %}
|
||||||
|
|
||||||
{% only_light %}
|
{% only_light %}
|
||||||

|

|
||||||
{% /only_light %}
|
{% /only_light %}
|
||||||
@@ -102,4 +105,4 @@ For example, your `.env` might look something similar to this.
|
|||||||
APPWRITE_KEY=<YOUR_API_KEY>
|
APPWRITE_KEY=<YOUR_API_KEY>
|
||||||
PUBLIC_APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1
|
PUBLIC_APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1
|
||||||
PUBLIC_APPWRITE_PROJECT=<YOUR_PROJECT_ID>
|
PUBLIC_APPWRITE_PROJECT=<YOUR_PROJECT_ID>
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ export default defineEventHandler(async (event) => {
|
|||||||
await sendRedirect(event, "/account");
|
await sendRedirect(event, "/account");
|
||||||
}
|
}
|
||||||
|
|
||||||
await sendRedirect(event, "/signin");
|
await sendRedirect(event, "/signup");
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
When a user visits the home page, they will be redirected to the sign in page if they are not logged in, or to the account page if they are logged in.
|
When a user visits the home page, they will be redirected to the sign up page if they are not logged in, or to the account page if they are logged in.
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
---
|
---
|
||||||
layout: tutorial
|
layout: tutorial
|
||||||
title: Create sign in page
|
title: Create sign up page
|
||||||
description: Add authentication to a Nuxt project using Appwrite.
|
description: Add authentication to a Nuxt project using Appwrite.
|
||||||
step: 5
|
step: 5
|
||||||
---
|
---
|
||||||
|
|
||||||
We can now implement our sign in page. Create a `signin.vue` file in the `pages` directory.
|
We can now implement our sign up page. Create a `signin.vue` file in the `pages` directory.
|
||||||
|
|
||||||
```vue
|
```vue
|
||||||
<!-- pages/signin.vue -->
|
<!-- pages/signup.vue -->
|
||||||
<template>
|
<template>
|
||||||
<form method="post" action="/api/signin">
|
<form method="post" action="/api/signup">
|
||||||
<input id="email" name="email" placeholder="Email" type="email" />
|
<input id="email" name="email" placeholder="Email" type="email" />
|
||||||
<input
|
<input
|
||||||
id="password"
|
id="password"
|
||||||
@@ -26,7 +26,7 @@ We can now implement our sign in page. Create a `signin.vue` file in the `pages`
|
|||||||
This is an HTML form with an email and password input. When the form is submitted, we want to send the email and password to Appwrite to authenticate the user. To use Nuxt form actions we create a `signin.post.js` file in the `server/api` directory:
|
This is an HTML form with an email and password input. When the form is submitted, we want to send the email and password to Appwrite to authenticate the user. To use Nuxt form actions we create a `signin.post.js` file in the `server/api` directory:
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
// server/api/signin.post.js
|
// server/api/signup.post.js
|
||||||
import { SESSION_COOKIE, createAdminClient } from "~/server/lib/appwrite";
|
import { SESSION_COOKIE, createAdminClient } from "~/server/lib/appwrite";
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ description: Add authentication to a Nuxt project using Appwrite.
|
|||||||
step: 6
|
step: 6
|
||||||
---
|
---
|
||||||
|
|
||||||
Now the end-user is able to sign in, we can create the account page. This page will display basic information about the user, and allow the user to log out. Create a new file in the `pages` directory called `account.vue` and add the following code:
|
Now the end-user is able to sign up, we can create the account page. This page will display basic information about the user, and allow the user to log out. Create a new file in the `pages` directory called `account.vue` and add the following code:
|
||||||
|
|
||||||
```vue
|
```vue
|
||||||
<!-- pages/account.vue -->
|
<!-- pages/account.vue -->
|
||||||
@@ -44,6 +44,6 @@ export default defineEventHandler(async (event) => {
|
|||||||
await account.deleteSession("current");
|
await account.deleteSession("current");
|
||||||
deleteCookie(event, SESSION_COOKIE);
|
deleteCookie(event, SESSION_COOKIE);
|
||||||
|
|
||||||
await sendRedirect(event, "/signin");
|
await sendRedirect(event, "/signup");
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
---
|
---
|
||||||
layout: tutorial
|
layout: tutorial
|
||||||
title: OAuth2 authentication with SSR
|
title: OAuth authentication with SSR
|
||||||
description: Add authentication to a Nuxt project using Appwrite.
|
description: Add authentication to a Nuxt project using Appwrite.
|
||||||
step: 7
|
step: 7
|
||||||
---
|
---
|
||||||
|
|
||||||
To support the OAuth2 flow, we first redirect the user to the OAuth2 provider, and then handle the callback from the OAuth2 provider.
|
To support the OAuth flow, we first redirect the user to the OAuth provider, and then handle the callback from the OAuth provider.
|
||||||
|
|
||||||
To redirect, add a button to our sign in page that redirects the user to the OAuth2 provider.
|
To redirect, add a button to our sign up page that redirects the user to the OAuth provider.
|
||||||
|
|
||||||
```vue
|
```vue
|
||||||
<!-- pages/signin.vue -->
|
<!-- pages/signup.vue -->
|
||||||
|
|
||||||
<!-- ... existing sign in form -->
|
<!-- ... existing sign up form -->
|
||||||
|
|
||||||
<form action="/api/oauth2" method="post">
|
<form action="/api/oauth2" method="post">
|
||||||
<input type="hidden" name="provider" value="github" />
|
<input type="hidden" name="provider" value="github" />
|
||||||
@@ -31,17 +31,17 @@ export default defineEventHandler(async (event) => {
|
|||||||
const { account } = createAdminClient();
|
const { account } = createAdminClient();
|
||||||
|
|
||||||
const redirectUrl = await account.createOAuth2Token(
|
const redirectUrl = await account.createOAuth2Token(
|
||||||
"github", // OAuth2 provider
|
"github", // OAuth provider
|
||||||
`${config.public.appwriteEndpoint}/api/oauth2`, // Success URL: redirect back to the /oauth2 route
|
`${config.public.appwriteEndpoint}/api/oauth2`, // Success URL: redirect back to the /oauth2 route
|
||||||
`${config.public.appwriteEndpoint}/signin` // Failure URL: redirect to the sign in page
|
`${config.public.appwriteEndpoint}/signup` // Failure URL: redirect to the sign up page
|
||||||
);
|
);
|
||||||
|
|
||||||
// Redirect the user to the OAuth2 provider authorization page
|
// Redirect the user to the OAuth provider authorization page
|
||||||
await sendRedirect(event, redirectUrl);
|
await sendRedirect(event, redirectUrl);
|
||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
The `createOAuth2Token` method redirects the user to the OAuth2 provider, and then the OAuth2 provider redirects the user back to the `/oauth2` route with the `userId` and `secret` URL query parameters.
|
The `createOAuth2Token` method redirects the user to the OAuth provider, and then the OAuth provider redirects the user back to the `/oauth2` route with the `userId` and `secret` URL query parameters.
|
||||||
|
|
||||||
Handle the callback and create a session for the user. Create a new server route at `server/routes/api/oauth2.get.js`.
|
Handle the callback and create a session for the user. Create a new server route at `server/routes/api/oauth2.get.js`.
|
||||||
|
|
||||||
@@ -53,7 +53,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
// Extract the userId and secret from the URL query parameters
|
// Extract the userId and secret from the URL query parameters
|
||||||
const { userId, secret } = getQuery(event);
|
const { userId, secret } = getQuery(event);
|
||||||
if (!userId || !secret) {
|
if (!userId || !secret) {
|
||||||
return sendRedirect(event, "/signin");
|
return sendRedirect(event, "/signup");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the Appwrite client
|
// Create the Appwrite client
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ title: Initialize SDK
|
|||||||
description: Add authentication to a SvelteKit project using Appwrite.
|
description: Add authentication to a SvelteKit project using Appwrite.
|
||||||
step: 3
|
step: 3
|
||||||
---
|
---
|
||||||
Before you can use Appwrite, you need to create the Appwrite `Client` and set the project ID and endpoint.
|
|
||||||
|
Before you can use Appwrite, you need to create the Appwrite `Client` and set the project ID and endpoint.
|
||||||
The client is then used to create services like `Databases` and `Account`, so they all point to the same Appwrite project.
|
The client is then used to create services like `Databases` and `Account`, so they all point to the same Appwrite project.
|
||||||
|
|
||||||
Create a function to build services you need in a file like `src/lib/server/appwrite.js` and **exporting the instances**.
|
Create a function to build services you need in a file like `src/lib/server/appwrite.js` and **exporting the instances**.
|
||||||
@@ -21,14 +22,14 @@ Doing so could create security vulnerabilities.
|
|||||||
// src/lib/server/appwrite.js
|
// src/lib/server/appwrite.js
|
||||||
import { Client, Account } from 'node-appwrite';
|
import { Client, Account } from 'node-appwrite';
|
||||||
import { APPWRITE_KEY } from '$env/static/private';
|
import { APPWRITE_KEY } from '$env/static/private';
|
||||||
import { PUBLIC_APPWRITE_ENDPOINT, PUBLIC_APPWRITE_PROJECT_ID } from '$env/static/public';
|
import { PUBLIC_APPWRITE_ENDPOINT, PUBLIC_APPWRITE_PROJECT } from '$env/static/public';
|
||||||
|
|
||||||
export const SESSION_COOKIE = 'my-custom-session';
|
export const SESSION_COOKIE = 'my-custom-session';
|
||||||
|
|
||||||
export function createAdminClient() {
|
export function createAdminClient() {
|
||||||
const client = new Client()
|
const client = new Client()
|
||||||
.setEndpoint(PUBLIC_APPWRITE_ENDPOINT)
|
.setEndpoint(PUBLIC_APPWRITE_ENDPOINT)
|
||||||
.setProject(PUBLIC_APPWRITE_PROJECT_ID)
|
.setProject(PUBLIC_APPWRITE_PROJECT)
|
||||||
.setKey(APPWRITE_KEY); // Set the Appwrite API key!
|
.setKey(APPWRITE_KEY); // Set the Appwrite API key!
|
||||||
|
|
||||||
// Return the services we want to use.
|
// Return the services we want to use.
|
||||||
@@ -42,11 +43,15 @@ export function createAdminClient() {
|
|||||||
export function createSessionClient(event) {
|
export function createSessionClient(event) {
|
||||||
const client = new Client()
|
const client = new Client()
|
||||||
.setEndpoint(PUBLIC_APPWRITE_ENDPOINT)
|
.setEndpoint(PUBLIC_APPWRITE_ENDPOINT)
|
||||||
.setProject(PUBLIC_APPWRITE_PROJECT_ID);
|
.setProject(PUBLIC_APPWRITE_PROJECT);
|
||||||
|
|
||||||
// Extract our custom domain's session cookie from the request
|
// Extract our custom domain's session cookie from the request
|
||||||
const session = event.cookies.get(SESSION_COOKIE);
|
const session = event.cookies.get(SESSION_COOKIE);
|
||||||
if (session) client.setSession(session);
|
if (!session) {
|
||||||
|
throw new Error('Session cookie not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
client.setSession(session);
|
||||||
|
|
||||||
// Return the services we want to use.
|
// Return the services we want to use.
|
||||||
return {
|
return {
|
||||||
@@ -57,15 +62,21 @@ export function createSessionClient(event) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
`APPWRITE_KEY`, `PUBLIC_APPWRITE_ENDPOINT` and `PUBLIC_APPWRITE_PROJECT_ID` are environment variables that are exported in your project's [.env file](https://kit.svelte.dev/docs/modules#$env-dynamic-public).
|
For example, your `.env` might look something similar to this.
|
||||||
|
|
||||||
You can get the values for these variables from the Appwrite console.
|
```text
|
||||||
|
APPWRITE_KEY=<YOUR_API_KEY>
|
||||||
|
PUBLIC_APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1
|
||||||
|
PUBLIC_APPWRITE_PROJECT=<YOUR_PROJECT_ID>
|
||||||
|
```
|
||||||
|
|
||||||
|
The `PUBLIC_APPWRITE_ENDPOINT` is the endpoint of your Appwrite project, and the `PUBLIC_APPWRITE_PROJECT` is the ID of the project you want to use.
|
||||||
|
You can get the values for these variables from the Appwrite console.
|
||||||
|
|
||||||
The `PUBLIC_APPWRITE_ENDPOINT` is the endpoint of your Appwrite project, and the `PUBLIC_APPWRITE_PROJECT` is the ID of the project you want to use.
|
|
||||||
You can get the values for these variables from the Appwrite console.
|
|
||||||
{% only_dark %}
|
{% only_dark %}
|
||||||

|

|
||||||
{% /only_dark %}
|
{% /only_dark %}
|
||||||
|
|
||||||
{% only_light %}
|
{% only_light %}
|
||||||

|

|
||||||
{% /only_light %}
|
{% /only_light %}
|
||||||
@@ -74,21 +85,14 @@ The `APPWRITE_KEY` is an Appwrite API key with the necessary permissions to read
|
|||||||
|
|
||||||
For this tutorial you'll need an API key with the following scopes:
|
For this tutorial you'll need an API key with the following scopes:
|
||||||
|
|
||||||
| Category {% width=120 %} | Required scopes | Purpose |
|
| Category {% width=120 %} | Required scopes | Purpose |
|
||||||
|-----------|---------------------|---------|
|
| ------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------ |
|
||||||
| Sessions | `sessions.write` | Allows API key to create, update, and delete sessions. |
|
| Sessions | `sessions.write` | Allows API key to create, update, and delete sessions. |
|
||||||
|
|
||||||
{% only_dark %}
|
{% only_dark %}
|
||||||

|

|
||||||
{% /only_dark %}
|
{% /only_dark %}
|
||||||
|
|
||||||
{% only_light %}
|
{% only_light %}
|
||||||

|

|
||||||
{% /only_light %}
|
{% /only_light %}
|
||||||
|
|
||||||
For example, your `.env` might look something similar to this.
|
|
||||||
|
|
||||||
```text
|
|
||||||
APPWRITE_KEY=<YOUR_API_KEY>
|
|
||||||
PUBLIC_APPWRITE_ENDPOINT=https://cloud.appwrite.io/v1
|
|
||||||
PUBLIC_APPWRITE_PROJECT=<YOUR_PROJECT_ID>
|
|
||||||
```
|
|
||||||
@@ -13,12 +13,12 @@ Create a new file in the `src/hooks` directory called `server.js`:
|
|||||||
import { createSessionClient } from '$lib/server/appwrite';
|
import { createSessionClient } from '$lib/server/appwrite';
|
||||||
|
|
||||||
export async function handle({ event, resolve }) {
|
export async function handle({ event, resolve }) {
|
||||||
// Use our helper function to create the Appwrite client.
|
|
||||||
const { account } = createSessionClient(event);
|
|
||||||
|
|
||||||
// Let's store the current logged in user in locals,
|
|
||||||
// for easy access in our other routes.
|
|
||||||
try {
|
try {
|
||||||
|
// Use our helper function to create the Appwrite client.
|
||||||
|
const { account } = createSessionClient(event);
|
||||||
|
|
||||||
|
// Store the current logged in user in locals,
|
||||||
|
// for easy access in our other routes.
|
||||||
event.locals.user = await account.get();
|
event.locals.user = await account.get();
|
||||||
} catch {}
|
} catch {}
|
||||||
|
|
||||||
@@ -57,8 +57,8 @@ import { redirect } from '@sveltejs/kit';
|
|||||||
export async function load({ locals }) {
|
export async function load({ locals }) {
|
||||||
// Access our user from locals.
|
// Access our user from locals.
|
||||||
if (!locals.user) {
|
if (!locals.user) {
|
||||||
// If no user is logged in, redirect to the sign in page.
|
// If no user is logged in, redirect to the sign up page.
|
||||||
throw redirect(301, '/signin');
|
throw redirect(301, '/signup');
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user is logged in, redirect to the account page.
|
// If the user is logged in, redirect to the account page.
|
||||||
@@ -66,4 +66,4 @@ export async function load({ locals }) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
When a user visits the home page, they will be redirected to the sign in page if they are not logged in, or to the account page if they are logged in.
|
When a user visits the home page, they will be redirected to the sign up page if they are not logged in, or to the account page if they are logged in.
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
---
|
---
|
||||||
layout: tutorial
|
layout: tutorial
|
||||||
title: Create sign in page
|
title: Create sign up page
|
||||||
description: Add authentication to a SvelteKit project using Appwrite.
|
description: Add authentication to a SvelteKit project using Appwrite.
|
||||||
step: 5
|
step: 5
|
||||||
---
|
---
|
||||||
|
|
||||||
We can now implement our sign in page. Create a `+page.svelte` file in the `src/routes/signin` directory:
|
We can now implement our sign up page. Create a `+page.svelte` file in the `src/routes/signup` directory:
|
||||||
|
|
||||||
```svelte
|
```svelte
|
||||||
<!-- src/routes/signin/+page.svelte -->
|
<!-- src/routes/signup/+page.svelte -->
|
||||||
<form method="post">
|
<form method="post">
|
||||||
<input id="email" placeholder="Email" type="email" />
|
<input id="email" placeholder="Email" type="email" />
|
||||||
<input id="password" placeholder="Password" type="password" />
|
<input id="password" placeholder="Password" type="password" />
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ description: Add authentication to a SvelteKit project using Appwrite.
|
|||||||
step: 6
|
step: 6
|
||||||
---
|
---
|
||||||
|
|
||||||
Now the end-user is able to sign in, we can create the account page. This page will display basic information about the user, and allow the user to log out. Create a new file in the `src/routes/account` directory called `+page.server.js` and add the following code:
|
Now the end-user is able to sign up, we can create the account page. This page will display basic information about the user, and allow the user to log out. Create a new file in the `src/routes/account` directory called `+page.server.js` and add the following code:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// src/routes/account/+page.server.js
|
// src/routes/account/+page.server.js
|
||||||
@@ -14,7 +14,7 @@ import { redirect } from '@sveltejs/kit';
|
|||||||
|
|
||||||
export async function load({ locals }) {
|
export async function load({ locals }) {
|
||||||
// Logged out users can't access this page.
|
// Logged out users can't access this page.
|
||||||
if (!locals.user) throw redirect(301, '/signin');
|
if (!locals.user) throw redirect(301, '/signup');
|
||||||
|
|
||||||
// Pass the stored user local to the page.
|
// Pass the stored user local to the page.
|
||||||
return {
|
return {
|
||||||
@@ -32,8 +32,8 @@ export const actions = {
|
|||||||
await account.deleteSession('current');
|
await account.deleteSession('current');
|
||||||
event.cookies.delete(SESSION_COOKIE);
|
event.cookies.delete(SESSION_COOKIE);
|
||||||
|
|
||||||
// Redirect to the sign in page.
|
// Redirect to the sign up page.
|
||||||
throw redirect(301, '/signin');
|
throw redirect(301, '/signup');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
---
|
---
|
||||||
layout: tutorial
|
layout: tutorial
|
||||||
title: OAuth2 authentication with SSR
|
title: OAuth authentication with SSR
|
||||||
description: Add authentication to a SvelteKit project using Appwrite.
|
description: Add authentication to a SvelteKit project using Appwrite.
|
||||||
step: 7
|
step: 7
|
||||||
---
|
---
|
||||||
|
|
||||||
To support the OAuth2 flow, we first redirect the user to the OAuth2 provider, and then handle the callback from the OAuth2 provider.
|
To support the OAuth flow, we first redirect the user to the OAuth provider, and then handle the callback from the OAuth provider.
|
||||||
|
|
||||||
To redirect, add a button to our sign in page that redirects the user to the OAuth2 provider.
|
To redirect, add a button to our sign up page that redirects the user to the OAuth provider.
|
||||||
|
|
||||||
```svelte
|
```svelte
|
||||||
<!-- src/routes/signin/+page.svelte -->
|
<!-- src/routes/signup/+page.svelte -->
|
||||||
|
|
||||||
<!-- ... existing sign in form -->
|
<!-- ... existing sign up form -->
|
||||||
|
|
||||||
<form action="/oauth2" method="post">
|
<form action="/oauth2" method="post">
|
||||||
<button type="submit">Sign in with GitHub</button>
|
<button type="submit">Sign in with GitHub</button>
|
||||||
@@ -22,7 +22,7 @@ To redirect, add a button to our sign in page that redirects the user to the OAu
|
|||||||
Add a new server route to handle the redirect.
|
Add a new server route to handle the redirect.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// src/routes/signin/+page.server.js
|
// src/routes/signup/+page.server.js
|
||||||
|
|
||||||
// ... existing imports
|
// ... existing imports
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ export const actions = {
|
|||||||
const redirectURL = account.createOAuth2Token(
|
const redirectURL = account.createOAuth2Token(
|
||||||
OAuthProvider.Github,
|
OAuthProvider.Github,
|
||||||
`${event.url.origin}/oauth2`,
|
`${event.url.origin}/oauth2`,
|
||||||
`${event.url.origin}/signin`
|
`${event.url.origin}/signup`
|
||||||
);
|
);
|
||||||
|
|
||||||
throw redirect(url);
|
throw redirect(url);
|
||||||
@@ -48,7 +48,7 @@ export const actions = {
|
|||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
The `createOAuth2Token` method redirects the user to the OAuth2 provider, and then the OAuth2 provider redirects the user back to the `/oauth2` route with the `userId` and `secret` URL query parameters.
|
The `createOAuth2Token` method redirects the user to the OAuth provider, and then the OAuth provider redirects the user back to the `/oauth2` route with the `userId` and `secret` URL query parameters.
|
||||||
|
|
||||||
Handle the callback and create a session for the user. Create a new server route at `src/routes/oauth2/+server.js`:
|
Handle the callback and create a session for the user. Create a new server route at `src/routes/oauth2/+server.js`:
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user