Skip to content

Commit

Permalink
add account linking guide
Browse files Browse the repository at this point in the history
  • Loading branch information
pilcrowOnPaper committed Jan 26, 2024
1 parent 039fbd5 commit 3899014
Showing 1 changed file with 85 additions and 1 deletion.
86 changes: 85 additions & 1 deletion docs/pages/guides/oauth/account-linking.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,90 @@ title: "Account linking"

# Account linking

This guide uses the database schema shown in the [Multiple OAuth providers](/guides/oauth/multiple-providers) guide.

## Automatic

In general, you'd want to link accounts with the same email. Keep in mind that the email can be not verified and you should always assume it isn't. Make sure to verify that the email has been verified.

```ts
import { generateId } from "lucia";

const tokens = await github.validateAuthorizationCode(code);
const userResponse = await fetch("https://api.github.com/user", {
headers: {
Authorization: `Bearer ${tokens.accessToken}`
}
});
const githubUser = await userResponse.json();

const emailsResponse = await fetch("https://api.github.com/user/emails", {
headers: {
Authorization: `Bearer ${tokens.accessToken}`
}
});
const emails = await emailsResponse.json();

const primaryEmail = emails.find((email) => email.primary) ?? null;
if (!primaryEmail) {
return new Response("No primary email address", {
status: 400
});
}
if (!primaryEmail.verified) {
return new Response("Unverified email", {
status: 400
});
}

const existingUser = await db.table("user").where("email", "=", primaryEmail.email).get();
if (existingUser) {
await db.table("oauth_account").insert({
provider_id: "github",
provider_user_id: githubUser.id,
user_id: existingUser.id
});
} else {
const userId = generateId();
await db.beginTransaction();
await db.table("user").insert({
id: userId,
email: primaryEmail.email
});
await db.table("oauth_account").insert({
provider_id: "github",
provider_user_id: githubUser.id,
user_id: userId
});
await db.commitTransaction();
}
```
still working on this one!

## Manual

Another approach is to let users manually add OAuth accounts from their profile/settings page. You'd want to setup another OAuth flow, and instead of creating a new user, add a new OAuth account tied to the authenticated user.

```ts
const { user } = await lucia.validateSession();
if (!user) {
return new Response(null, {
status: 401
});
}

const tokens = await github.validateAuthorizationCode(code);
const userResponse = await fetch("https://api.github.com/user", {
headers: {
Authorization: `Bearer ${tokens.accessToken}`
}
});
const githubUser = await userResponse.json();

// TODO: check if github account is already linked to a user

await db.table("oauth_account").insert({
provider_id: "github",
provider_user_id: githubUser.id,
user_id: user.id
});
```

0 comments on commit 3899014

Please sign in to comment.