diff --git a/src/controllers/api/oauth.ts b/src/controllers/api/oauth.ts index b1309bce..f4e68e1d 100644 --- a/src/controllers/api/oauth.ts +++ b/src/controllers/api/oauth.ts @@ -1,15 +1,13 @@ import { NConnectSigner, NSchema as n, NSecSigner } from '@nostrify/nostrify'; import { bech32 } from '@scure/base'; -import { encodeBase64 } from '@std/encoding/base64'; import { escape } from 'entities'; -import { generateSecretKey, getPublicKey, nip19 } from 'nostr-tools'; +import { generateSecretKey, getPublicKey } from 'nostr-tools'; import { z } from 'zod'; import { AppController } from '@/app.ts'; import { DittoDB } from '@/db/DittoDB.ts'; import { nostrNow } from '@/utils.ts'; import { parseBody } from '@/utils/api.ts'; -import { getClientConnectUri } from '@/utils/connect.ts'; import { Storages } from '@/storages.ts'; const passwordGrantSchema = z.object({ @@ -80,7 +78,9 @@ const createTokenController: AppController = async (c) => { } }; -async function getToken({ pubkey, secret, relays = [] }: z.infer): Promise<`token1${string}`> { +async function getToken( + { pubkey, secret, relays = [] }: { pubkey: string; secret?: string; relays?: string[] }, +): Promise<`token1${string}`> { const kysely = await DittoDB.getInstance(); const token = generateToken(); @@ -115,49 +115,26 @@ function generateToken(): `token1${string}` { } /** Display the OAuth form. */ -const oauthController: AppController = async (c) => { +const oauthController: AppController = (c) => { const encodedUri = c.req.query('redirect_uri'); if (!encodedUri) { return c.text('Missing `redirect_uri` query param.', 422); } const redirectUri = maybeDecodeUri(encodedUri); - const connectUri = await getClientConnectUri(c.req.raw.signal); - - const script = ` - window.addEventListener('load', function() { - if ('nostr' in window) { - nostr.getPublicKey().then(function(pubkey) { - document.getElementById('pubkey').value = pubkey; - document.getElementById('oauth_form').submit(); - }); - } - }); - `; - - const hash = encodeBase64(await crypto.subtle.digest('SHA-256', new TextEncoder().encode(script))); - - c.res.headers.set( - 'content-security-policy', - `default-src 'self' 'sha256-${hash}'`, - ); return c.html(` Log in with Ditto -
- - +
-
- Nostr Connect `); @@ -178,16 +155,8 @@ function maybeDecodeUri(uri: string): string { /** Schema for FormData POSTed to the OAuthController. */ const oauthAuthorizeSchema = z.object({ - pubkey: z.string().regex(/^[0-9a-f]{64}$/).optional().catch(undefined), - nip19: z.string().regex(new RegExp(`^${nip19.BECH32_REGEX.source}$`)).optional().catch(undefined), + bunker_uri: z.string().url().refine((v) => v.startsWith('bunker://')), redirect_uri: z.string().url(), -}).superRefine((data, ctx) => { - if (!data.pubkey && !data.nip19) { - ctx.addIssue({ - code: z.ZodIssueCode.custom, - message: 'Missing `pubkey` or `nip19`.', - }); - } }); /** Controller the OAuth form is POSTed to. */ @@ -200,18 +169,19 @@ const oauthAuthorizeController: AppController = async (c) => { } // Parsed FormData values. - const { pubkey, nip19: nip19id, redirect_uri: redirectUri } = result.data; + const { bunker_uri, redirect_uri: redirectUri } = result.data; - if (pubkey) { - const encoded = nip19.npubEncode(pubkey!); - const url = addCodeToRedirectUri(redirectUri, encoded); - return c.redirect(url); - } else if (nip19id) { - const url = addCodeToRedirectUri(redirectUri, nip19id); - return c.redirect(url); - } + const bunker = new URL(bunker_uri); - return c.text('The Nostr ID was not provided or invalid.', 422); + const token = await getToken({ + pubkey: bunker.hostname, + secret: bunker.searchParams.get('secret') || undefined, + relays: bunker.searchParams.getAll('relay'), + }); + + const url = addCodeToRedirectUri(redirectUri, token); + + return c.redirect(url); }; /** Append the given `code` as a query param to the `redirect_uri`. */