Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs WIP #121

Merged
merged 26 commits into from
Jan 1, 2025
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<picture>
<source srcset="https://raw.githubusercontent.com/openauthjs/identity/main/assets/themes-dark.png" media="(prefers-color-scheme: dark)">
<source srcset="https://raw.githubusercontent.com/openauthjs/identity/main/assets/themes-light.png" media="(prefers-color-scheme: dark)">
<img src="https://raw.githubusercontent.com/openauthjs/identity/main/assets/themes-light.png" alt="OpenAuth logo">
<img src="https://raw.githubusercontent.com/openauthjs/identity/main/assets/themes-light.png" alt="OpenAuth themes">
</picture>

## Quick Start
Expand Down
67 changes: 63 additions & 4 deletions packages/openauth/src/client.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,43 @@
/**
* Use the OpenAuth client kick off your authorization flows, exchange tokens, refresh tokens,
* and verify tokens.
*
* First, create a client.
*
* ```ts
* import { createClient } from "@openauthjs/openauth/client"
*
* const client = createClient({
* clientID: "my-client",
* issuer: "https://auth.myserver.com"
* })
* ```
*
* Kick off the authorization flow by calling `authorize`.
*
* ```ts
* const redirect_uri = "https://myserver.com/callback"
*
* const { url } = await client.authorize(
* redirect_uri,
* "code",
* )
* ```
*
* When the user completes the flow, `exchange` the code for tokens.
*
* ```ts
* const tokens = await client.exchange(query.get("code"), redirect_uri)
* ```
*
* And `verify` the tokens.
*
* ```ts
* const verified = await client.verify(subjects, tokens.access)
* ```
*
* @packageDocumentation
*/
import {
createLocalJWKSet,
errors,
Expand Down Expand Up @@ -59,19 +99,38 @@ export type Challenge = {
}

/**
* The input object for the client.
* Configure the client.
*/
export interface ClientInput {
/**
* The client ID.
* The client ID. This is just a string to identify your app.
*
* If you have a web app and a mobile app, you want to use different client IDs both.
*
* @example
* ```ts
* {
* clientID: "my-client"
* }
* ```
*/
clientID: string
/**
* The issuer URL.
* The URL of your authorization server.
*
* @example
* ```ts
* {
* issuer: "https://auth.myserver.com"
* }
* ```
*/
issuer?: string
/**
* The fetch function to use.
* Optionally, override the internally used fetch function.
*
* This is useful if you are using a polyfilled fetch function in your application and you
* want the client to use it too.
*/
fetch?: FetchLike
}
Expand Down
27 changes: 27 additions & 0 deletions packages/openauth/src/storage/cloudflare.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,36 @@
/**
* Configure OpenAuth to use [Cloudflare KV](https://developers.cloudflare.com/kv/) as a
* storage adapter.
*
* ```ts
* import { CloudflareStorage } from "@openauthjs/openauth/storage/cloudflare";
*
* const storage = CloudflareStorage({
* namespace: "my-namespace"
* })
*
*
* export default authorizer({
* storage,
* // ...
* })
* ```
*
* @packageDocumentation
*/
import type { KVNamespace } from "@cloudflare/workers-types"
import { joinKey, splitKey, StorageAdapter } from "./storage.js"

/**
* Configure the DynamoDB table that's created.
*/
interface CloudflareStorageOptions {
namespace: KVNamespace
}
/**
* Creates a Cloudflare KV store.
* @param options - The config for the adapter.
*/
export function CloudflareStorage(
options: CloudflareStorageOptions,
): StorageAdapter {
Expand Down
26 changes: 20 additions & 6 deletions packages/openauth/src/storage/dynamo.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
/**
* This is the AWS DynamoDB storage adapter.
* Configure OpenAuth to use [DynamoDB](https://aws.amazon.com/dynamodb/) as a storage adapter.
*
* ```ts
* import { DynamoStorage } from "@openauthjs/openauth/storage/dynamo";
*
* DynamoStorage({
* const storage = DynamoStorage({
* table: "my-table",
* pk: "pk",
* sk: "sk",
* sk: "sk"
* })
*
* export default authorizer({
* storage,
* // ...
* })
* ```
*
Expand All @@ -18,7 +23,16 @@ import { client } from "./aws.js"
import { joinKey, StorageAdapter } from "./storage.js"

/**
* Configuration options for the Dynamo storage adapter.
* Configure the DynamoDB table that's created.
*
* @example
* ```ts
* {
* table: "my-table",
* pk: "pk",
* sk: "sk"
* }
* ```
*/
export interface DynamoStorageOptions {
/**
Expand All @@ -36,8 +50,8 @@ export interface DynamoStorageOptions {
}

/**
* Creates a Dynamo storage adapter.
* @param options - The configuration options for the adapter.
* Creates a DynamoDB store.
* @param options - The config for the adapter.
*/
export function DynamoStorage(options: DynamoStorageOptions): StorageAdapter {
const c = client()
Expand Down
43 changes: 43 additions & 0 deletions packages/openauth/src/storage/memory.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,51 @@
/**
* Configure OpenAuth to use a simple in-memory store.
*
* :::caution
* This is not meant to be used in production.
* :::
*
* This is useful for testing and development. It's not meant to be used in production.
*
* ```ts
* import { MemoryStorage } from "@openauthjs/openauth/storage/memory";
*
* const storage = MemoryStorage()
*
* export default authorizer({
* storage,
* // ...
* })
* ```
*
* Optionally, you can persist the store to a file.
*
* ```ts
* MemoryStorage({
* persist: "./persist.json"
* })
* ```
*
* @packageDocumentation
*/
import { joinKey, splitKey, StorageAdapter } from "./storage.js"
import { existsSync, readFileSync } from "node:fs"
import { writeFile } from "node:fs/promises"

/**
* Configure the memory store.
*/
export interface MemoryStorageOptions {
/**
* Optionally, backup the store to a file. So it'll be persisted when the authorizer restarts.
*
* @example
* ```ts
* {
* persist: "./persist.json"
* }
* ```
*/
persist?: string
}
export function MemoryStorage(input?: MemoryStorageOptions): StorageAdapter {
Expand Down
84 changes: 82 additions & 2 deletions packages/openauth/src/ui/code.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,27 @@
/**
* Configure the UI that's used by the Code provider.
*
* ```ts {1,7-12}
* import { CodeUI } from "@openauthjs/openauth/ui/code"
* import { CodeAdapter } from "@openauthjs/openauth/adapter/code"
*
* export default authorizer({
* providers: {
* code: CodeAdapter(
* CodeUI({
* copy: {
* code_info: "We'll send a pin code to your email"
* },
* sendCode: (claims, code) => console.log(claims.email, code)
* })
* )
* },
* // ...
* })
* ```
*
* @packageDocumentation
*/
/** @jsxImportSource hono/jsx */

import { CodeAdapterOptions } from "../adapter/code.js"
Expand All @@ -6,25 +30,81 @@ import { Layout } from "./base.js"
import { FormAlert } from "./form.js"

const DEFAULT_COPY = {
/**
* Copy for the email input.
*/
email_placeholder: "Email",
/**
* Error message when the email is invalid.
*/
email_invalid: "Email address is not valid",
/**
* Copy for the continue button.
*/
button_continue: "Continue",
/**
* Copy informing that the pin code will be emailed.
*/
code_info: "We'll send a pin code to your email",
/**
* Copy for the pin code input.
*/
code_placeholder: "Code",
/**
* Error message when the code is invalid.
*/
code_invalid: "Invalid code",
/**
* Copy for when the code was sent.
*/
code_sent: "Code sent to ",
/**
* Copy for when the code was resent.
*/
code_resent: "Code resent to ",
/**
* Copy for the link to resend the code.
*/
code_didnt_get: "Didn't get code?",
/**
* Copy for the resend button.
*/
code_resend: "Resend",
}

export type CodeUICopy = typeof DEFAULT_COPY

export function CodeUI(props: {
/**
* Configure the password UI.
*/
export interface CodeUIOptions {
/**
* Callback to send the confirmation code to the user.
*
* @example
* ```ts
* async (claims, code) => {
* // Send an email with the code
* }
* ```
*/
sendCode: (claims: Record<string, string>, code: string) => Promise<void>
/**
* Custom copy for the UI.
*/
copy?: Partial<CodeUICopy>
/**
* The mode to use for the input.
* @default "email"
*/
mode?: "email" | "phone"
}) {
}

/**
* Creates a UI for the Code provider flow.
* @param props - Configure the UI.
*/
export function CodeUI(props: CodeUIOptions) {
const copy = {
...DEFAULT_COPY,
...props.copy,
Expand Down
Loading
Loading