Skip to content

Commit

Permalink
Feature/apple oauth provider (#657)
Browse files Browse the repository at this point in the history
Co-authored-by: pilcrowOnPaper <[email protected]>
  • Loading branch information
luccasr73 and pilcrowonpaper authored Aug 1, 2023
1 parent 2be3cc7 commit cb64343
Show file tree
Hide file tree
Showing 37 changed files with 999 additions and 26 deletions.
6 changes: 6 additions & 0 deletions .auri/$ertjjenl.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
package: "@lucia-auth/oauth" # package name
type: "minor" # "major", "minor", "patch"
---

Add Apple provider
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ node_modules
pnpm-lock.yaml
.vscode
.idea
*.p8
164 changes: 164 additions & 0 deletions documentation/content/oauth/providers/apple.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
---
order: 0
title: "Apple"
description: "Learn about using the Apple provider in Lucia OAuth integration"
---

**Before starting make sure you have an paid apple dev account.**

OAuth integration for Apple. Refer to Apple Docs:

- [Creating App ID](https://developer.apple.com/help/account/manage-identifiers/register-an-app-id/)
- [Creating Service ID](https://developer.apple.com/help/account/manage-identifiers/register-a-services-id)
- [Enable "Sign In with Apple" Capability](https://developer.apple.com/help/account/manage-identifiers/enable-app-capabilities)
- [Creating Private Key](https://developer.apple.com/help/account/manage-keys/create-a-private-key)
- [Locate the keyId](https://developer.apple.com/help/account/manage-keys/get-a-key-identifier)
- [How to locate your teamId](https://developer.apple.com/help/account/manage-your-team/locate-your-team-id)
- [Requesting Access Token](https://developer.apple.com/documentation/sign_in_with_apple/request_an_authorization_to_the_sign_in_with_apple_server)
- [How to validate tokens](https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens)

Provider id is `apple`.

```ts
import { apple } from "@lucia-auth/oauth/providers";
import { auth } from "./auth.js";

const appleAuth = apple(auth, configs);
```

## `apple()`

```ts
const apple: (
auth: Auth,
config: {
clientId: string;
redirectUri: string;
teamId: string;
keyId: string;
certificate: string;
}
) => AppleProvider;
```

##### Parameters

| name | type | description |
| ------------------ | ------------------------------------------ | -------------------------------------------------------------- |
| `auth` | [`Auth`](/reference/lucia/interfaces/auth) | Lucia instance |
| config.clientId | `string` | Apple service identifier |
| config.redirectUri | `string` | an authorized redirect URI |
| config.teamId | `string` | Apple teamId |
| config.keyId | `string` | Apple private keyId |
| config.certificate | `string` | p8 certificate as string [See how](#how-to-import-certificate) |

##### Returns

| type | description |
| --------------------------------- | -------------- |
| [`AppleProvider`](#appleprovider) | Apple provider |

### Import certificate

Example using Node.js:

```ts
import fs from "fs";
import path from "path";

const certificatePath = path.join(
process.cwd(),
process.env.APPLE_CERT_PATH ?? ""
);

const certificate = fs.readFileSync(certificatePath, "utf-8");

export const appleAuth = apple(auth, {
teamId: process.env.APPLE_TEAM_ID ?? "",
keyId: process.env.APPLE_KEY_ID ?? "",
certificate: certificate,
redirectUri: process.env.APPLE_REDIRECT_URI ?? "",
clientId: process.env.APPLE_CLIENT_ID ?? ""
});
```

## Interfaces

### `AppleProvider`

Satisfies [`OAuthProvider`](/reference/oauth/interfaces#oauthprovider).

#### `getAuthorizationUrl()`

Returns the authorization url for user redirection and a state for storage. The state should be stored in a cookie and validated on callback.

```ts
const getAuthorizationUrl: () => Promise<[url: URL, state: string]>;
```

##### Returns

| name | type | description |
| ------- | -------- | -------------------- |
| `url` | `URL` | authorize url |
| `state` | `string` | state parameter used |

#### `validateCallback()`

Validates the callback code.

```ts
const validateCallback: (code: string) => Promise<AppleUserAuth>;
```

##### Parameters

| name | type | description |
| ------ | -------- | ------------------------------------ |
| `code` | `string` | The authorization code from callback |

##### Returns

| type |
| --------------------------------- |
| [`AppleUserAuth`](#appleuserauth) |

##### Errors

Request errors are thrown as [`OAuthRequestError`](/reference/oauth/interfaces#oauthrequesterror).

### `AppleUserAuth`

```ts
type Auth0UserAuth = ProviderUserAuth & {
appleUser: AppleUser;
appleTokens: AppleTokens;
};
```

| type |
| ------------------------------------------------------------------ |
| [`ProviderUserAuth`](/reference/oauth/interfaces#provideruserauth) |
| [`AppleUser`](#appleuser) |
| [`AppleTokens`](#appletokens) |

### `AppleTokens`

```ts
type AppleTokens = {
accessToken: string;
refreshToken: string | null;
accessTokenExpiresIn: number;
idToken: string;
};
```

### `AppleUser`

```ts
type AppleUser = {
email: string;
email_verified: boolean;
sub: string;
};
```
4 changes: 0 additions & 4 deletions documentation/content/oauth/providers/auth0.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,6 @@ type Auth0UserAuth = ProviderUserAuth & {
| [`Auth0User`](#auth0user) |
| [`Auth0Tokens`](#auth0tokens) |

```ts
import type { Auth0Tokens, Auth0User } from "@lucia-auth/oauth/providers";
```

### `Auth0Tokens`

```ts
Expand Down
8 changes: 4 additions & 4 deletions documentation/content/oauth/providers/google.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,9 @@ type GoogleUser = {
given_name: string;
family_name: string;
picture: string;
locale: string;
email?: string;
email_verified?: boolean;
hd?: string;
locale: string;
email?: string;
email_verified?: boolean;
hd?: string;
};
```
5 changes: 5 additions & 0 deletions examples/nextjs-app/apple-oauth/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
APPLE_CERT_PATH=
APPLE_TEAM_ID=
APPLE_KEY_ID=
APPLE_REDIRECT_URI=
APPLE_CLIENT_ID=
3 changes: 3 additions & 0 deletions examples/nextjs-app/apple-oauth/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}
39 changes: 39 additions & 0 deletions examples/nextjs-app/apple-oauth/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env*.local
.env

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts

main.db
*.p8
1 change: 1 addition & 0 deletions examples/nextjs-app/apple-oauth/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.next
57 changes: 57 additions & 0 deletions examples/nextjs-app/apple-oauth/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Apple OAuth example with Lucia and Next.js App Router

This example uses `better-sqlite3`.

```bash
# install dependencies
pnpm i

# setup .env
pnpm setup-env

# setup database
pnpm migrate

# run
pnpm dev
```

## Runtime

This example is built for Node.js 20. If you're using Node.js 16/18, un-comment the following lines in `auth/lucia.ts`:

```ts
// import "lucia/polyfill/node";
```

### Setup Apple ID OAuth

**Before starting make sure you have an paid apple dev account**

Setup the Apple App and copy-paste credentials into `.env`.

Refer to Apple Docs:

- [Creating App ID](https://developer.apple.com/help/account/manage-identifiers/register-an-app-id/)
- [Creating Service ID](https://developer.apple.com/help/account/manage-identifiers/register-a-services-id)
- [Enable "Sign In with Apple" Capability](https://developer.apple.com/help/account/manage-identifiers/enable-app-capabilities)
- [Creating Private Key](https://developer.apple.com/help/account/manage-keys/create-a-private-key)
- [Locate the keyId](https://developer.apple.com/help/account/manage-keys/get-a-key-identifier)
- [How to locate your teamId](https://developer.apple.com/help/account/manage-your-team/locate-your-team-id)
- [Requesting Access Token](https://developer.apple.com/documentation/sign_in_with_apple/request_an_authorization_to_the_sign_in_with_apple_server)
- [How to validate tokens](https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens)

```bash
APPLE_TEAM_ID=""
APPLE_KEY_ID=""
APPLE_CERT_PATH=""
APPLE_REDIRECT_URI=""
APPLE_CLIENT_ID=""
```

## User schema

| id | type | unique |
| ----------------- | -------- | :----: |
| `id` | `string` | |
| `email` | `string` | |
8 changes: 8 additions & 0 deletions examples/nextjs-app/apple-oauth/app.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// <reference types="lucia" />
declare namespace Lucia {
type Auth = import("@/auth/lucia").Auth;
type DatabaseUserAttributes = {
email: string;
};
type DatabaseSessionAttributes = {};
}
Binary file added examples/nextjs-app/apple-oauth/app/favicon.ico
Binary file not shown.
10 changes: 10 additions & 0 deletions examples/nextjs-app/apple-oauth/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
body {
padding: 2rem;
}
* {
margin-top: 0.5rem;
margin-bottom: 0.5rem;
}
.error {
color: red;
}
17 changes: 17 additions & 0 deletions examples/nextjs-app/apple-oauth/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import "./globals.css";

export const metadata = {
title: "Apple OAuth with Lucia"
};

export default function RootLayout({
children
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}
Loading

0 comments on commit cb64343

Please sign in to comment.