From 6b01ab47972c5197ea29723efc0a5e9071836fce Mon Sep 17 00:00:00 2001 From: Hernan Alvarado Date: Mon, 5 Jan 2026 18:13:32 -0500 Subject: [PATCH 1/4] feat(oauth): add `Notion` OAuth provider --- packages/core/src/oauth/index.ts | 3 ++ packages/core/src/oauth/notion.ts | 52 +++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 packages/core/src/oauth/notion.ts diff --git a/packages/core/src/oauth/index.ts b/packages/core/src/oauth/index.ts index 64e0397d..96d751e4 100644 --- a/packages/core/src/oauth/index.ts +++ b/packages/core/src/oauth/index.ts @@ -12,6 +12,7 @@ import { gitlab } from "./gitlab.js" import { spotify } from "./spotify.js" import { x } from "./x.js" import { strava } from "./strava.js" +import { notion } from "./notion.js" export { github, type GitHubProfile } from "./github.js" export { bitbucket, type BitbucketProfile } from "./bitbucket.js" @@ -21,6 +22,7 @@ export { gitlab, type GitLabProfile } from "./gitlab.js" export { spotify, type SpotifyProfile } from "./spotify.js" export { x, type XProfile } from "./x.js" export { strava, type StravaProfile, type SummaryClub, type SummaryGear } from "./strava.js" +export { notion, type NotionProfile, type Bot, type Owner, type Person, type User } from "./notion.js" export const builtInOAuthProviders = { github, @@ -31,6 +33,7 @@ export const builtInOAuthProviders = { spotify, x, strava, + notion, } const defineOAuthEnvironment = (oauth: string) => { diff --git a/packages/core/src/oauth/notion.ts b/packages/core/src/oauth/notion.ts new file mode 100644 index 00000000..f9b50e61 --- /dev/null +++ b/packages/core/src/oauth/notion.ts @@ -0,0 +1,52 @@ +import { OAuthProviderConfig } from "@/@types/index.js" + +export interface Person { + email: string +} + +export interface User { + object: "user" + id: string + name: string + avatar_url: string | null + type: "person" + person: Person +} + +export interface Owner { + type: "user" + user: User +} + +export interface Bot { + owner: Owner +} + +/** + * @see [Notion - Retrieve your token's bot user](https://developers.notion.com/reference/get-self) + */ +export interface NotionProfile { + object: "user" + id: string + name: string + avatar_url: string | null + type: "bot" + bot: Bot +} + +/** + * @see [Notion - Developer Documentation](https://developers.notion.com/) + * @see [Notion - Authorization](https://developers.notion.com/docs/authorization) + * @see [Notion - Authentication](https://developers.notion.com/reference/authentication) + * @see [Notion - Retrieve your token's bot user](https://developers.notion.com/reference/get-self) + * @todo: It's required to pass the Notion-Version header to access the user info endpoint. + */ +export const notion: OAuthProviderConfig = { + id: "notion", + name: "Notion", + authorizeURL: "https://api.notion.com/v1/oauth/authorize?owner=user", + accessToken: "https://api.notion.com/v1/oauth/token", + userInfo: "https://api.notion.com/v1/users/me", + scope: "user:read", + responseType: "code", +} From d7a6f0e36e46ffcda559b3520d4baf59d30ca929 Mon Sep 17 00:00:00 2001 From: Hernan Alvarado Date: Mon, 5 Jan 2026 18:38:22 -0500 Subject: [PATCH 2/4] docs(notion): highlight future implementations --- packages/core/src/oauth/notion.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/packages/core/src/oauth/notion.ts b/packages/core/src/oauth/notion.ts index f9b50e61..9a9c1b88 100644 --- a/packages/core/src/oauth/notion.ts +++ b/packages/core/src/oauth/notion.ts @@ -40,6 +40,9 @@ export interface NotionProfile { * @see [Notion - Authentication](https://developers.notion.com/reference/authentication) * @see [Notion - Retrieve your token's bot user](https://developers.notion.com/reference/get-self) * @todo: It's required to pass the Notion-Version header to access the user info endpoint. + * headers: { Notion-Version: "2022-06-28" } + * @todo: It's required to add Basic headers for access token request. + * headers: { Authorization: "Basic base64(client_id:client_secret)" } */ export const notion: OAuthProviderConfig = { id: "notion", @@ -49,4 +52,12 @@ export const notion: OAuthProviderConfig = { userInfo: "https://api.notion.com/v1/users/me", scope: "user:read", responseType: "code", + profile(profile) { + return { + sub: profile.id, + name: profile.name, + image: profile.avatar_url ?? "", + email: profile?.bot?.owner?.user?.person?.email, + } + }, } From 854f5896f78d12ce8121fb9355a16fa354649db6 Mon Sep 17 00:00:00 2001 From: Hernan Alvarado Date: Mon, 2 Mar 2026 12:12:34 -0500 Subject: [PATCH 3/4] docs(notion): add `notion.mdx` file to document oauth provider --- docs/src/content/docs/oauth/notion.mdx | 157 +++++++++++++++++++++++++ packages/core/src/oauth/index.ts | 3 + packages/core/src/oauth/notion.ts | 60 ++++++---- 3 files changed, 199 insertions(+), 21 deletions(-) create mode 100644 docs/src/content/docs/oauth/notion.mdx diff --git a/docs/src/content/docs/oauth/notion.mdx b/docs/src/content/docs/oauth/notion.mdx new file mode 100644 index 00000000..7a3f2796 --- /dev/null +++ b/docs/src/content/docs/oauth/notion.mdx @@ -0,0 +1,157 @@ +--- +title: Notion Authorization Provider +description: Add Twitch authorization provider to Aura Auth to authenticate and authorize +--- + +## Notion + +Set up `Notion` authorization provider to the authentication instance to Aura Auth. + +--- + +## What you'll learn + +Through this quick start guide you are going to learn and understand the basics and how to set up `Notion` provider to Aura Auth. + +- [Notion OAuth App](#notion-oauth-app) + - [Creating an OAuth App](#creating-an-oauth-app) +- [Notion Aura Auth](#notion-aura-auth) + - [Installation](#installation) + - [Environment setup](#environment-setup) + - [Configure the provider](#configure-the-provider) + - [Get HTTP handlers](#get-http-handlers) +- [Resources](#resources) + +--- + + + + + +## Notion OAuth App + +### Creating an OAuth app + +The first step is create and register a [`Notion Integration`](https://www.notion.so/profile/integrations/public) to grant to have access to the user's accessible resources like `Retrieve the Bot User` (Used by Aura Auth), `Pages`, `Comments`, `Databases`, etc. For more detailed information read [Get Started Authorization](https://developers.notion.com/guides/get-started/authorization), [Notion Integrations](https://www.notion.so/profile/integrations/public) and [Get Self User](https://developers.notion.com/reference/get-self). + +Registering an Notion OAuth app includes: + +- `Integration name`: The application name showed when the user tries to grant to the app. +- `Associated workspace`: The workspace that the app belongs to, it can be changed later. +- `Company name`: The company name showed when the user tries to grant to the app. +- `Website`: The URL of the website, it can be changed later. +- `Tagline`: The tagline of the app, it can be changed later. +- `Privacy Policy URL`: The URL of the privacy policy, it can be changed later. +- `Terms of Use URL`: The URL of the terms of use, it can be changed later. +- `Email`: The email of the developer, it can be changed later. +- `Authorization URL`: The URL which the Notion will redirect, it should end in `/auth/callback/notion` for local and production environment. + - Local environment: `http://localhost:3000/auth/callback/notion` + - Production environment: production set the URL of the application. + + + + + +## Notion Aura Auth + +### Installation + +install the package using a package manager like `npm`, `pnpm` or `yarn` + +```npm +npm install @aura-stack/auth +``` + + + + + +### Environment setup + +Now, it's time to create and consume the Notion credentials required and used by Aura Auth, it include the `client Id` and `client Secret` and write them into a `.env` file. + +Additionally set the `secret` used by Aura Auth to sign and encrypt the user's session. + +```bash title=".env" lineNumbers +# Notion Credentials +AURA_AUTH_NOTION_CLIENT_ID="notion_client_id" +AURA_AUTH_NOTION_CLIENT_SECRET="notion_client_secret" + +# Aura Secret +AURA_AUTH_SECRET="32-bytes-secret" +``` + + + The `AURA_AUTH_SECRET` will recommended to be random and high antropy key to avoid attackers decifer the secret used by the Aura + Auth application. + + + + + + +### Configure the provider + +Set the `oauth` option of the `createAuth` instance. You can use the provider name as a string to use default settings, or use the `Notion` factory function to customize the configuration. + +#### Default configuration + +```ts title="@/auth" lineNumbers +import { createAuth } from "@aura-stack/auth" + +export const auth = createAuth({ + oauth: ["notion"], +}) + +export const { handlers } = auth +``` + +#### Custom configuration + +```ts title="@/auth" lineNumbers +import { createAuth } from "@aura-stack/auth" +import { Notion } from "@aura-stack/auth/oauth/Notion" + +export const auth = createAuth({ + oauth: [ + Notion({ + scope: "read:user user:email repo", + }), + ], +}) + +export const { handlers } = auth +``` + + + + + +### Get HTTP Handlers + +Use the HTTP handlers to consume the authentication logic and flow the Aura Auth library to be integrated into routers and frameworks. + +```ts title="backend.ts" lineNumbers +import { handlers } from "@/auth" + +export const { GET, POST } = handlers +``` + + + The returned handlers include pre-built routes used in OAuth flows (`/signIn/:oauth`, `/callback/:oauth`, `/session`, `/signOut` + and `/csrfToken`). You can mount them in Express, Hono, Next.js, or any runtime that supports native Request and Response APIs. + + + + + + +--- + +## Resources + +- [RFC - The OAuth 2.0 Authorization Framework](https://datatracker.ietf.org/doc/html/rfc6749) +- [Notion - Developer Documentation](https://developers.notion.com/) +- [Notion - Authorization](https://developers.notion.com/docs/authorization) +- [Notion - Authentication](https://developers.notion.com/reference/authentication) +- [Notion - Retrieve your token's bot user](https://developers.notion.com/reference/get-self) diff --git a/packages/core/src/oauth/index.ts b/packages/core/src/oauth/index.ts index f88d645d..5ec31f19 100644 --- a/packages/core/src/oauth/index.ts +++ b/packages/core/src/oauth/index.ts @@ -16,6 +16,7 @@ import { strava } from "./strava.ts" import { mailchimp } from "./mailchimp.ts" import { pinterest } from "./pinterest.ts" import { twitch } from "./twitch.ts" +import { notion } from "./notion.ts" import { OAuthEnvSchema, OAuthProviderCredentialsSchema } from "@/schemas.ts" import { AuthInternalError } from "@/errors.ts" import { formatZodError } from "@/utils.ts" @@ -31,6 +32,7 @@ export * from "./strava.ts" export * from "./mailchimp.ts" export * from "./pinterest.ts" export * from "./twitch.ts" +export * from "./notion.ts" export const builtInOAuthProviders = { github, @@ -44,6 +46,7 @@ export const builtInOAuthProviders = { mailchimp, pinterest, twitch, + notion, } as const /** diff --git a/packages/core/src/oauth/notion.ts b/packages/core/src/oauth/notion.ts index 9a9c1b88..dfff432a 100644 --- a/packages/core/src/oauth/notion.ts +++ b/packages/core/src/oauth/notion.ts @@ -1,4 +1,5 @@ -import { OAuthProviderConfig } from "@/@types/index.js" +import { createBasicAuthHeader } from "@/utils.ts" +import type { OAuthProviderCredentials } from "@/@types/index.ts" export interface Person { email: string @@ -39,25 +40,42 @@ export interface NotionProfile { * @see [Notion - Authorization](https://developers.notion.com/docs/authorization) * @see [Notion - Authentication](https://developers.notion.com/reference/authentication) * @see [Notion - Retrieve your token's bot user](https://developers.notion.com/reference/get-self) - * @todo: It's required to pass the Notion-Version header to access the user info endpoint. - * headers: { Notion-Version: "2022-06-28" } - * @todo: It's required to add Basic headers for access token request. - * headers: { Authorization: "Basic base64(client_id:client_secret)" } */ -export const notion: OAuthProviderConfig = { - id: "notion", - name: "Notion", - authorizeURL: "https://api.notion.com/v1/oauth/authorize?owner=user", - accessToken: "https://api.notion.com/v1/oauth/token", - userInfo: "https://api.notion.com/v1/users/me", - scope: "user:read", - responseType: "code", - profile(profile) { - return { - sub: profile.id, - name: profile.name, - image: profile.avatar_url ?? "", - email: profile?.bot?.owner?.user?.person?.email, - } - }, +export const notion = (options?: Partial>): OAuthProviderCredentials => { + return { + id: "notion", + name: "Notion", + authorize: { + url: "https://api.notion.com/v1/oauth/authorize", + params: { + owner: "user", + scope: "user:read", + responseType: "code", + }, + }, + accessToken: { + url: "https://api.notion.com/v1/oauth/token", + headers: { + Authorization: createBasicAuthHeader( + options?.clientId ?? "NOTION_CLIENT_ID", + options?.clientSecret ?? "NOTION_CLIENT_SECRET" + ), + }, + }, + userInfo: { + url: "https://api.notion.com/v1/users/me", + headers: { + "Notion-Version": "2022-06-28", + }, + }, + profile(profile) { + return { + sub: profile.id, + name: profile.name, + image: profile.avatar_url ?? "", + email: profile?.bot?.owner?.user?.person?.email, + } + }, + ...options, + } as OAuthProviderCredentials } From 0380fd9e9a44ba3c86c9248182f5146e4d2769bc Mon Sep 17 00:00:00 2001 From: Hernan Alvarado Date: Mon, 2 Mar 2026 13:13:54 -0500 Subject: [PATCH 4/4] docs(notion): fix notion comments --- docs/src/content/docs/oauth/notion.mdx | 8 ++++---- packages/core/CHANGELOG.md | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/src/content/docs/oauth/notion.mdx b/docs/src/content/docs/oauth/notion.mdx index 7a3f2796..e21653b5 100644 --- a/docs/src/content/docs/oauth/notion.mdx +++ b/docs/src/content/docs/oauth/notion.mdx @@ -1,6 +1,6 @@ --- title: Notion Authorization Provider -description: Add Twitch authorization provider to Aura Auth to authenticate and authorize +description: Add Notion authorization provider to Aura Auth to authenticate and authorize --- ## Notion @@ -92,7 +92,7 @@ AURA_AUTH_SECRET="32-bytes-secret" ### Configure the provider -Set the `oauth` option of the `createAuth` instance. You can use the provider name as a string to use default settings, or use the `Notion` factory function to customize the configuration. +Set the `oauth` option of the `createAuth` instance. You can use the provider name as a string to use default settings, or use the `notion` factory function to customize the configuration. #### Default configuration @@ -110,11 +110,11 @@ export const { handlers } = auth ```ts title="@/auth" lineNumbers import { createAuth } from "@aura-stack/auth" -import { Notion } from "@aura-stack/auth/oauth/Notion" +import { notion } from "@aura-stack/auth/oauth/notion" export const auth = createAuth({ oauth: [ - Notion({ + notion({ scope: "read:user user:email repo", }), ], diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index f19bedaf..0668e8f6 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -10,6 +10,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), ### Added +- Added the `Notion` OAuth provider to the supported integrations in Aura Auth. [#49](https://github.com/aura-stack-ts/auth/pull/49) + - Added the `Twitch` OAuth provider to the supported integrations in Aura Auth. [#47](https://github.com/aura-stack-ts/auth/pull/47) - Added support for loading authentication configuration from environment variables, including `DEBUG`, `LOG_LEVEL`, `TRUSTED_ORIGINS`, and `TRUSTED_PROXY_HEADERS`. Also updated automatic environment variable loading patterns. [#108](https://github.com/aura-stack-ts/auth/pull/108)