diff --git a/example/backend/server.js b/example/backend/server.js index 2a10971..80d888f 100644 --- a/example/backend/server.js +++ b/example/backend/server.js @@ -153,6 +153,37 @@ app.post('/api/challenge-token', async (req, res) => { } }); +app.post('/api/launch-url', async (req, res) => { + try { + const { userId } = req.body; + + if (!userId) { + return res.status(400).json({ error: 'userId is required' }); + } + + console.log(` Tracking 'launch' for user: ${userId}`); + + const trackResponse = await authsignal.track({ + userId, + action: 'launch', + }); + + console.log(` State: ${trackResponse.state}, URL: ${trackResponse.url}`); + + res.json({ + url: trackResponse.url, + token: trackResponse.token, + state: trackResponse.state, + }); + } catch (error) { + console.error(' Error:', error.message); + res.status(500).json({ + error: 'Failed to get launch URL', + details: error.message, + }); + } +}); + app.post('/api/validate', async (req, res) => { try { const { token } = req.body; diff --git a/example/package-lock.json b/example/package-lock.json index ca5f1f5..585731e 100644 --- a/example/package-lock.json +++ b/example/package-lock.json @@ -30,7 +30,7 @@ } }, "..": { - "version": "2.4.0", + "version": "2.6.1", "license": "MIT", "devDependencies": { "@authsignal/browser": "^1.13.1", diff --git a/example/src/screens/HomeScreen.tsx b/example/src/screens/HomeScreen.tsx index 292a511..e521a1b 100644 --- a/example/src/screens/HomeScreen.tsx +++ b/example/src/screens/HomeScreen.tsx @@ -77,6 +77,58 @@ export function HomeScreen() { } }; + // --- Launch Methods --- + + const launchPopup = async () => { + const authsignal = authsignalRef.current; + if (!authsignal) return; + + try { + addOutput('Getting launch URL from backend...'); + const response = await BackendService.getLaunchUrl(userId); + + if (!response?.url) { + addOutput('Failed to get launch URL'); + return; + } + + addOutput(`Launch URL received (state: ${response.state})`); + addOutput('Opening in popup mode...'); + + const token = await authsignal.launch(response.url); + + if (token) { + addOutput(`Popup completed! Token: ${token.substring(0, 20)}...`); + } else { + addOutput('Popup closed without completing.'); + } + } catch (e) { + addOutput(`Error: ${e}`); + } + }; + + const launchRedirect = async () => { + const authsignal = authsignalRef.current; + if (!authsignal) return; + + try { + addOutput('Getting launch URL from backend...'); + const response = await BackendService.getLaunchUrl(userId); + + if (!response?.url) { + addOutput('Failed to get launch URL'); + return; + } + + addOutput(`Launch URL received (state: ${response.state})`); + addOutput('Redirecting...'); + + await authsignal.launch(response.url, { mode: 'redirect' }); + } catch (e) { + addOutput(`Error: ${e}`); + } + }; + // --- Passkey Methods --- const registerPasskey = async () => { @@ -550,6 +602,23 @@ export function HomeScreen() { onInitialize={initializeSDK} /> + {/* Launch */} + + + + + {/* Passkeys */} { + try { + const response = await fetch(`${this.baseUrl}/api/launch-url`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ userId }), + }); + + if (response.ok) { + return await response.json(); + } + console.log(`Failed to get launch URL: ${response.status}`); + return null; + } catch (e) { + console.log(`Backend connection error: ${e}`); + return null; + } + } + async checkHealth(): Promise { try { const controller = new AbortController(); diff --git a/package-lock.json b/package-lock.json index dfc30f4..e81530e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "react-native-authsignal", - "version": "2.4.0", + "version": "2.6.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "react-native-authsignal", - "version": "2.4.0", + "version": "2.6.0", "license": "MIT", "devDependencies": { "@authsignal/browser": "^1.13.1", @@ -24,7 +24,7 @@ "typescript": "^4.5.2" }, "peerDependencies": { - "@authsignal/browser": ">=0.5.0", + "@authsignal/browser": ">=1.0.0", "react": "*", "react-native": "*" }, diff --git a/package.json b/package.json index 1c7e8c8..45d7f3e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-authsignal", - "version": "2.6.0", + "version": "2.6.1", "description": "The official Authsignal React Native library.", "main": "lib/commonjs/index", "module": "lib/module/index", diff --git a/src/index.tsx b/src/index.tsx index c21ef22..61ca245 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -71,10 +71,7 @@ export class Authsignal { await AuthsignalModule.setToken(token); } - async launch( - url: string, - _options?: LaunchOptions - ): Promise { + async launch(url: string, _options?: LaunchOptions): Promise { return await launch(url); } } diff --git a/src/index.web.tsx b/src/index.web.tsx index 13e21f1..5387e60 100644 --- a/src/index.web.tsx +++ b/src/index.web.tsx @@ -64,10 +64,7 @@ export class Authsignal { client.setToken(token); } - async launch( - url: string, - options?: LaunchOptions - ): Promise { + async launch(url: string, options?: LaunchOptions): Promise { return await launch(url, options); } } @@ -76,8 +73,6 @@ export function launch( url: string, options?: LaunchOptions ): Promise { - const mode = options?.mode ?? 'popup'; - if (_lastClient) { const client = getOrCreateWebClient({ tenantID: _lastClient.tenantID, @@ -85,7 +80,12 @@ export function launch( enableLogging: _lastClient.enableLogging, }); - return client.launch(url, { mode }).then((result) => { + if (options?.mode === 'redirect') { + client.launch(url, { mode: 'redirect' }); + return Promise.resolve(null); + } + + return client.launch(url, { mode: 'popup' }).then((result) => { return result?.token ?? null; }); } diff --git a/src/types.ts b/src/types.ts index 11f707f..86533da 100644 --- a/src/types.ts +++ b/src/types.ts @@ -131,10 +131,8 @@ export interface DeletePinInput { username: string; } -export type LaunchMode = 'popup' | 'redirect'; - export interface LaunchOptions { - mode?: LaunchMode; + mode?: 'popup' | 'redirect'; } export enum KeychainAccess {