### Example: Setup OAuth Listeners Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/api-reference/typescript-oauth-api.md Demonstrates how to start the OAuth server and register a listener for valid URLs. Includes parsing the URL to extract the authorization code and state for further processing. This setup persists until explicitly stopped. ```typescript import { start, onUrl } from '@fabianlars/tauri-plugin-oauth'; async function setupOAuthListeners() { try { const port = await start(); // Register listener for valid URLs const unlisten = await onUrl((url) => { console.log('Received valid OAuth URL:', url); // Parse the URL to extract the authorization code const urlObj = new URL(url); const code = urlObj.searchParams.get('code'); const state = urlObj.searchParams.get('state'); if (code && state) { // Validate state and exchange code for token exchangeCodeForToken(code, state); } }); // Keep listening until OAuth flow completes or user cancels // To stop listening: // unlisten(); } catch (error) { console.error('Setup failed:', error); } } ``` -------------------------------- ### Example: Stopping an OAuth Server with cancel Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/api-reference/rust-oauth-module.md Demonstrates how to start an OAuth server using `start` and then later stop it using the `cancel` function. This example shows a typical use case for interrupting an OAuth flow. ```rust use tauri_plugin_oauth::{start, cancel}; async fn example_oauth_flow() -> Result<(), String> { // Start the server let port = start(|url| { println!("OAuth URL: {}", url); }) .map_err(|e| e.to_string())?; println!("Server started on port {}", port); // Later, cancel the server if OAuth flow is interrupted cancel(port) .map_err(|e| format!("Cancel failed: {}", e))?; println!("Server stopped"); Ok(()) } ``` -------------------------------- ### Complete OAuth Flow Example Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/api-reference/typescript-oauth-api.md Demonstrates setting up the OAuth flow by starting the server and registering listeners for both valid and invalid URLs. Includes cleanup logic to unregister listeners when no longer needed. ```typescript import { start, onUrl, onInvalidUrl } from '@fabianlars/tauri-plugin-oauth'; async function setupCompleteOAuthFlow() { try { const port = await start(); // Listen for valid URLs const unlistenValid = await onUrl((url) => { console.log('✓ Valid OAuth URL received:', url); // Process valid URL handleValidOAuthUrl(url); }); // Listen for invalid URLs const unlistenInvalid = await onInvalidUrl((error) => { console.error('✗ Invalid OAuth URL received:', error); // Handle error showErrorMessage(`OAuth error: ${error}`); }); // Clean up when done const cleanup = () => { unlistenValid(); unlistenInvalid(); }; } catch (error) { console.error('Failed to start OAuth server:', error); } } ``` -------------------------------- ### Configuration Hierarchy Example (TypeScript) Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/INDEX.md Illustrates the order of precedence for configuration parameters, starting from direct parameter settings, falling back to tauri.conf.json, and finally to library defaults. ```typescript Parameter config ↓ (if omitted) tauri.conf.json plugins.oauth.response ↓ (if missing) Library default HTML response ``` -------------------------------- ### Run Example App Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/plugin-architecture.md Instructions to set up and run the vanilla example application for manual testing of the OAuth plugin. ```bash cd examples/vanilla npm install npm run tauri dev ``` -------------------------------- ### Example Handler Closure Usage Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/types.md Demonstrates how to use the start function with a handler closure to process the OAuth redirect URL. ```rust use tauri_plugin_oauth::start; start(|url| { println!("Received: {}", url); // Process the OAuth URL }) ``` -------------------------------- ### Configuration Priority Example (TypeScript) Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/README.md Illustrates the order of precedence for server response configuration. The parameter passed to the `start` function takes the highest priority, followed by the `tauri.conf.json` setting, and finally the library's default HTML response. ```typescript start({ response: "..." }) ``` -------------------------------- ### Simple OAuth Flow Example (TypeScript) Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/MANIFEST.md A basic implementation of the OAuth flow using the Tauri plugin. This example demonstrates the core functionality with minimal setup. ```typescript import { OAuth } from "tauri-plugin-oauth"; async function simpleOAuthFlow() { const oauth = new OAuth(); oauth.onUrl(async (url) => { console.log("Received URL:", url); // Handle the redirect URL }); oauth.onInvalidUrl(async (error) => { console.error("OAuth Error:", error); // Handle errors }); try { await oauth.start({ provider: "google", clientId: "YOUR_GOOGLE_CLIENT_ID", scopes: ["profile", "email"] }); } catch (error) { console.error("OAuth start failed:", error); } } ``` -------------------------------- ### Start OAuth with Default Configuration (TypeScript) Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/configuration.md Call the `start` function without any arguments to use the default configuration. This will let the OS assign a free port and use the library's default response. ```typescript import { start } from '@fabianlars/tauri-plugin-oauth'; const port = await start(); // No config = use defaults ``` -------------------------------- ### start Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/api-reference/typescript-oauth-api.md Starts the OAuth server on the local machine, allowing it to listen for OAuth redirects. It can be configured with specific ports and custom response HTML. ```APIDOC ## Function: `start` Starts the OAuth server on the local machine. ```typescript export async function start(config?: OauthConfig): Promise ``` ### Parameters | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | config | `OauthConfig` | No | `undefined` | Configuration object specifying ports and custom response HTML. If not provided, uses OS-assigned port and default response. | ### Return Type `Promise` — A promise that resolves to the port number the server is listening on. ### Behavior - Invokes the Tauri command `plugin:oauth|start` with optional configuration - The command is bridged to the Rust backend - If `config.response` is not provided in TypeScript, falls back to: 1. Configuration in `tauri.conf.json` (under `plugins.oauth.response`) 2. Library default HTML response - Resolves immediately with the port number after successful startup - Server continues running until `cancel()` is called or an OAuth redirect is received ### Errors - Rejects with a `string` error message if server startup fails - Common failure reasons: unable to bind to specified ports, network error ### Example ```typescript import { start, onUrl } from '@fabianlars/tauri-plugin-oauth'; async function initializeOAuth() { try { // Start with default settings (OS-assigned port) const port = await start(); console.log(`OAuth server started on port ${port}`); // Set up listener for successful OAuth redirect const unlisten = await onUrl((url) => { console.log('OAuth URL received:', url); // Handle the OAuth redirect URL }); // Redirect user to OAuth provider const authUrl = `https://oauth.example.com/authorize?redirect_uri=http://localhost:${port}/cb`; window.location.href = authUrl; } catch (error) { console.error('Failed to start OAuth server:', error); } } async function initializeWithCustomConfig() { const port = await start({ ports: [8000, 8001, 8002], response: '

Success!

You may close this window.', }); console.log(`Server listening on port ${port}`); } ``` ### Security Note The server is unprotected on `127.0.0.1`. Always validate the URL received in `onUrl` callback before processing it. ### Related Functions - [`cancel`](#function-cancel) — Stop the server - [`onUrl`](#function-onurl) — Listen for valid OAuth URLs - [`onInvalidUrl`](#function-oninvalidurl) — Listen for invalid URLs ``` -------------------------------- ### Safely Start OAuth Server in TypeScript Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/errors.md Provides a safe wrapper for the `start()` function, catching potential promise rejections during server creation or port binding. Returns the port if successful, otherwise null. ```typescript async function safeStart() { try { const port = await start(); return port; } catch (error) { console.error('Failed to start OAuth server:', error); // error is a string message return null; } } ``` -------------------------------- ### Full OAuth Flow Cancellation Example (TypeScript) Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/endpoints.md Demonstrates initiating an OAuth flow with `start` and subsequently canceling it using `cancel` based on user interaction. This example requires a UI element with the ID 'cancel-button'. ```typescript import { start, cancel } from '@fabianlars/tauri-plugin-oauth'; let oauthPort: number; async function initiateOAuth() { oauthPort = await start(); console.log(`OAuth server started on port ${oauthPort}`); // Redirect to OAuth provider window.location.href = `https://oauth.example.com/authorize?redirect_uri=http://localhost:${oauthPort}/cb`; } async function cancelOAuth() { if (oauthPort) { try { await cancel(oauthPort); console.log('OAuth flow cancelled'); } catch (error) { console.error('Cancel failed:', error); } } } // User clicks "Cancel" button document.getElementById('cancel-button').addEventListener('click', cancelOAuth); ``` -------------------------------- ### Start OAuth Flow with Configuration (Rust) Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/README.md Starts the OAuth flow with custom configuration and a handler. Returns the port used or an error. ```rust pub fn start_with_config(config: OauthConfig, handler: F) -> Result ``` -------------------------------- ### Start OAuth Server with Custom Configuration Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/INDEX.md Allows starting the OAuth server with custom configurations, such as specifying ports. Available in Rust and TypeScript. ```APIDOC ## Start OAuth Server with Custom Configuration ### Description Starts the OAuth server with a custom configuration, allowing you to specify parameters like the ports to listen on. A callback function can be provided to handle the incoming OAuth URL. ### Rust ```rust use tauri_plugin_oauth::{start_with_config, OauthConfig}; let config = OauthConfig { ports: Some(vec![8000, 8001, 8002]), response: None, }; let port = start_with_config(config, |url| {{}})?; ``` ### TypeScript ```typescript const port = await start({ ports: [8000, 8001, 8002], }); ``` ``` -------------------------------- ### Start OAuth Server in Rust Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/README.md Use the `start` function to initiate a local server for capturing OAuth redirects. Ensure you verify the received URL as it comes from an unprotected localhost port. The callback function handles the redirect URI. ```rust use tauri::{command, Emitter, Window}; use tauri_plugin_oauth::start; #[command] async fn start_server(window: Window) -> Result { start(move |url| { // Because of the unprotected localhost port, you must verify the URL here. // Preferebly send back only the token, or nothing at all if you can handle everything else in Rust. let _ = window.emit("redirect_uri", url); }) .map_err(|err| err.to_string()) } ``` ```rust #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() .plugin(tauri_plugin_oauth::init()) .invoke_handler(tauri::generate_handler![start_server]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } ``` -------------------------------- ### Start OAuth Server in TypeScript Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/README.md Initiate the OAuth server using the `start` function and set up listeners for URL redirects. Remember to stop the server using `cancel` when it's no longer needed. ```typescript import { start, cancel, onUrl, onInvalidUrl } from '@fabianlars/tauri-plugin-oauth'; async function startOAuthFlow() { try { const port = await start(); console.log(`OAuth server started on port ${port}`); // Set up listeners for OAuth results await onUrl((url) => { console.log('Received OAuth URL:', url); // Handle the OAuth redirect }); // Initiate your OAuth flow here // ... } catch (error) { console.error('Error starting OAuth server:', error); } } // Don't forget to stop the server when you're done async function stopOAuthServer() { try { await cancel(port); console.log('OAuth server stopped'); } catch (error) { console.error('Error stopping OAuth server:', error); } } ``` -------------------------------- ### Install Tauri Plugin OAuth (npm/yarn) Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/README.md Install the plugin using npm or yarn for Tauri projects. ```bash npm install @fabianlars/tauri-plugin-oauth@2 # or yarn add @fabianlars/tauri-plugin-oauth@2 ``` -------------------------------- ### start Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/api-reference/rust-oauth-module.md Starts an OAuth server on localhost (127.0.0.1) using a system-assigned port. It spawns a new thread to run the server and calls a provided handler closure once a valid OAuth redirect is received. ```APIDOC ## Function: `start` Starts an OAuth server on localhost (127.0.0.1) using a system-assigned port. ```rust pub fn start( handler: F ) -> Result ``` ### Parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | handler | `F: FnMut(String) + Send + 'static` | Yes | A closure that receives the full redirect URL as a String and executes when a valid OAuth callback is received. Must be `Send` and `'static` lifetime. | ### Return Type `Result` — Returns the port number the server is listening on, or an IO error if server creation fails. ### Behavior - Spawns a new thread to run the OAuth server - Listens on 127.0.0.1 with a system-assigned port (0 = let OS choose) - Calls the handler closure once when the first valid OAuth redirect is received - Server thread automatically terminates after handler execution or when `/exit` endpoint is called - **Security Note**: Because the server is unprotected on localhost, you must validate the received URL in the handler before trusting it ### Errors - `std::io::Error` — If the TCP listener cannot be created or the port cannot be bound - Server thread may panic if unable to send HTTP response (behavior may change after real-world testing) ### Example ```rust use tauri_plugin_oauth::start; #[command] async fn start_oauth_server(window: tauri::Window) -> Result { let port = start(move |url| { // IMPORTANT: Always validate the URL if let Err(e) = window.emit("oauth:redirect", &url) { eprintln!("Failed to emit redirect event: {}", e); } }) .map_err(|e| format!("Failed to start server: {}", e))?; Ok(port) } ``` ### Related Functions - [`start_with_config`](#function-start_with_config) — Start server with custom configuration - [`cancel`](#function-cancel) — Stop server without executing handler ``` -------------------------------- ### Tauri Configuration File: Full OAuth Example Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/configuration.md A complete example of the `tauri.conf.json` configuration for the OAuth plugin, specifying a custom HTML response. This demonstrates the structure for plugin-specific settings. ```json { "plugins": { "oauth": { "response": "

Authentication Complete

You may close this window." } } } ``` -------------------------------- ### Tauri Command Definitions for OAuth Plugin Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/plugin-architecture.md Defines the `start` and `cancel` commands that will be exposed to the frontend via Tauri's IPC. The `start` command initiates the OAuth server and returns the bound port, while `cancel` stops it. ```rust #[tauri::command] pub(crate) fn start( window: Window, config: Option, ) -> Result #[tauri::command] pub(crate) fn cancel(port: u16) -> Result<(), String> ``` -------------------------------- ### start_with_config Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/api-reference/rust-oauth-module.md Starts an OAuth server on localhost with custom configuration options. This function allows for specifying ports, custom response HTML, and a callback handler for OAuth redirects. ```APIDOC ## Function: `start_with_config` Starts an OAuth server on localhost with custom configuration options. ```rust pub fn start_with_config( config: OauthConfig, handler: F ) -> Result ``` ### Parameters | Parameter | Type | Required | Description | |-----------|------|----------|-------------| | config | `OauthConfig` | Yes | Configuration struct specifying ports and response HTML. Use `OauthConfig::default()` for defaults. | | handler | `F: FnMut(String) + Send + 'static` | Yes | Closure receiving the full redirect URL. Executes when a valid OAuth callback is received. | ### Return Type `Result` — Returns the port number the server bound to, or an IO error if binding fails. ### Behavior - If `config.ports` is provided, attempts to bind to each port in order until one succeeds - If `config.ports` is empty or `None`, requests an OS-assigned port (port 0) - If `config.response` is provided, sends that HTML; otherwise uses default response - Handler called once on successful OAuth redirect, then server thread terminates - Server can be stopped early by sending request to `http://127.0.0.1:{port}/exit` ### Errors - `std::io::Error` — If no ports in the configured list can be bound - Server thread may panic if unable to send response (may change after real-world testing) ### Example ```rust use tauri_plugin_oauth::{start_with_config, OauthConfig}; async fn start_with_fixed_ports() -> Result<(), String> { let config = OauthConfig { ports: Some(vec![8000, 8001, 8002]), response: Some( "

OAuth Complete

You can close this window.".into() ), }; let port = start_with_config(config, |url| { println!("Received OAuth URL: {}", url); }) .map_err(|e| format!("Server start failed: {}", e))?; println!("OAuth server listening on port {}", port); Ok(()) } ``` ### Related Functions - [`start`](#function-start) — Start server with default configuration - [`cancel`](#function-cancel) — Stop server without executing handler ``` -------------------------------- ### Start OAuth Server with Default Settings Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/INDEX.md Initiates the OAuth server using default configurations. The provided closure will be called with the generated OAuth URL. ```rust let port = tauri_plugin_oauth::start(|url| { println!("OAuth URL: {}", url); })?; ``` ```typescript const port = await start(); ``` -------------------------------- ### Start OAuth Server and Handle Redirects Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/api-reference/typescript-oauth-api.md Starts the OAuth server with default settings and sets up a listener for incoming OAuth redirect URLs. Redirects the user to the OAuth provider and logs the received URL. Ensure the received URL is validated before processing. ```typescript import { start, onUrl } from '@fabianlars/tauri-plugin-oauth'; async function initializeOAuth() { try { // Start with default settings (OS-assigned port) const port = await start(); console.log(`OAuth server started on port ${port}`); // Set up listener for successful OAuth redirect const unlisten = await onUrl((url) => { console.log('OAuth URL received:', url); // Handle the OAuth redirect URL }); // Redirect user to OAuth provider const authUrl = `https://oauth.example.com/authorize?redirect_uri=http://localhost:${port}/cb`; window.location.href = authUrl; } catch (error) { console.error('Failed to start OAuth server:', error); } } ``` -------------------------------- ### Start OAuth Flow with Custom Configuration (Rust) Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/MANIFEST.md Starts the OAuth flow with a specific configuration object. This allows for more granular control over the OAuth process. ```rust use tauri_plugin_oauth::{OauthConfig, OauthState}; use tauri::State; #[tauri::command] async fn start_oauth_custom( state: State<'_, OauthState>, config: OauthConfig, ) -> Result<(), String> { state.start(config).await.map_err(|e| e.to_string()) } ``` -------------------------------- ### Start OAuth Server with Handler Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/api-reference/rust-oauth-module.md Starts an OAuth server on localhost using a system-assigned port. The provided closure is executed once a valid OAuth callback is received. Ensure you validate the URL within the handler for security. ```rust pub fn start( handler: F ) -> Result ``` ```rust use tauri_plugin_oauth::start; #[command] async fn start_oauth_server(window: tauri::Window) -> Result { let port = start(move |url| { // IMPORTANT: Always validate the URL if let Err(e) = window.emit("oauth:redirect", &url) { eprintln!("Failed to emit redirect event: {}", e); } }) .map_err(|e| format!("Failed to start server: {}", e))?; Ok(port) } ``` -------------------------------- ### Start OAuth Server with Custom Configuration Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/api-reference/typescript-oauth-api.md Starts the OAuth server on specified ports with a custom HTML response for successful redirects. The server will listen on the provided ports and use the custom HTML for the success page. ```typescript import { start } from '@fabianlars/tauri-plugin-oauth'; async function initializeWithCustomConfig() { const port = await start({ ports: [8000, 8001, 8002], response: '

Success!

You may close this window.', }); console.log(`Server listening on port ${port}`); } ``` -------------------------------- ### Start OAuth Server with Default Settings Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/INDEX.md Initiates the OAuth server with default configurations. This function is available in both Rust and TypeScript. ```APIDOC ## Start OAuth Server with Default Settings ### Description Starts the OAuth server using default settings and returns the assigned port. A callback function is provided to handle the incoming OAuth URL. ### Rust ```rust let port = tauri_plugin_oauth::start(|url| { println!("OAuth URL: {}", url); })?; ``` ### TypeScript ```typescript const port = await start(); ``` ``` -------------------------------- ### Start OAuth Server with Custom Ports Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/INDEX.md Starts the OAuth server with a specified list of ports. This allows you to control which network ports the server listens on. ```rust use tauri_plugin_oauth::{start_with_config, OauthConfig}; let config = OauthConfig { ports: Some(vec![8000, 8001, 8002]), response: None, }; let port = start_with_config(config, |url| {})?; ``` ```typescript const port = await start({ ports: [8000, 8001, 8002], }); ``` -------------------------------- ### Start OAuth with Custom Ports (TypeScript) Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/configuration.md Provide an array of port numbers to the `ports` option in the `start` function. The server will attempt to bind to these ports in the order specified. If none are available, the OS will assign a free port. ```typescript const port = await start({ ports: [8000, 8001, 8002], }); ``` -------------------------------- ### OauthConfig Usage Examples Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/api-reference/rust-oauth-module.md Demonstrates how to create `OauthConfig` instances using default values, custom ports, custom HTML responses, and dynamically generated responses. ```rust use tauri_plugin_oauth::OauthConfig; use std::borrow::Cow; // Using the default configuration let config = OauthConfig::default(); // Custom configuration with specific ports let config_with_ports = OauthConfig { ports: Some(vec![8000, 8001, 8002]), response: None, }; // Custom HTML response let config_custom_response = OauthConfig { ports: None, response: Some(Cow::Borrowed( "OAuth successful! Please close this window." )), }; // Custom response with owned String let config_owned = OauthConfig { ports: Some(vec![3000]), response: Some(format!("Token received at {}", chrono::Local::now()).into()), }; ``` -------------------------------- ### TypeScript Port Fallback Example Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/configuration.md This TypeScript example demonstrates trying specific ports first and then falling back to an OS-assigned port if the fixed ports are unavailable. ```typescript async function startOAuthWithFallback() { try { // Try specific ports const port = await start({ ports: [8000, 8001, 8002], }); console.log(`Using port ${port}`); return port; } catch (error) { console.log('Fixed ports unavailable, letting OS choose'); // Fall back to OS-assigned port const port = await start(); return port; } } ``` -------------------------------- ### Example HTTP Response for /cb Endpoint Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/endpoints.md This is an example of a successful HTTP response from the /cb endpoint. It includes a 200 OK status and an HTML body with a message indicating the OAuth process completion. ```http HTTP/1.1 200 OK Content-Length: 245

OAuth process completed.

You can close this window.

``` -------------------------------- ### Example POST Request for /cb Endpoint Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/endpoints.md This is an example of a POST request to the /cb endpoint, including the required 'Full-Url' header which contains the complete OAuth redirect URL with the authorization code and state. ```http POST /cb HTTP/1.1 Host: 127.0.0.1:8000 Full-Url: http://127.0.0.1:8000/cb?code=4/0AY0e-g8Abc123_XyZ789...&state=RandomState123 Content-Length: 0 ``` -------------------------------- ### Start OAuth Flow (Rust) Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/README.md Initiates the OAuth flow using a provided handler. Returns the port used or an error. ```rust pub fn start(handler: F) -> Result ``` -------------------------------- ### OauthConfig Example Usage Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/api-reference/typescript-oauth-api.md Demonstrates how to create an OauthConfig object with specific ports and a custom response message. ```typescript import { OauthConfig } from '@fabianlars/tauri-plugin-oauth'; const config: OauthConfig = { ports: [8000, 8001, 8002], response: 'OAuth process completed. You can close this window.', }; ``` -------------------------------- ### Example: Advanced Cleanup for Listeners Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/api-reference/typescript-oauth-api.md Provides an example of how to manage listener cleanup, suitable for component unmounting in frameworks like React. It registers a listener and returns a cleanup function that calls the unlisten method. ```typescript // Advanced: Clean up listener when component unmounts async function initOAuthWithCleanup() { const unlisten = await onUrl((url) => { // Handle OAuth URL console.log(url); }); // Return cleanup function for React useEffect, etc. return () => { unlisten(); }; } ``` -------------------------------- ### Start OAuth with Custom Ports and Response (TypeScript) Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/configuration.md Combine custom ports and a custom response by providing both `ports` and `response` options to the `start` function. This allows for fine-grained control over the OAuth flow's network binding and user feedback. ```typescript const port = await start({ ports: [8000, 8001], response: ` Login

Login Successful

You can now close this window and return to the app.

`, }); ``` -------------------------------- ### plugin:oauth|start Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/endpoints.md Starts the OAuth flow. This command can optionally be provided with an OauthConfig object. It returns the port number the server is listening on. ```APIDOC ## Command: plugin:oauth|start ### Description Starts the OAuth flow. This command can optionally be provided with an OauthConfig object. It returns the port number the server is listening on. ### Parameters - **config** (OauthConfig) - Optional - Configuration for the OAuth flow. ### Returns - **port** (number) - The port number the server is listening on. ### Emits Events - `oauth://url` — When `/cb` receives valid OAuth URL - `oauth://invalid-url` — When URL validation fails ``` -------------------------------- ### Start OAuth Flow (TypeScript) Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/README.md Initiates the OAuth flow with optional configuration. Returns the port used by the OAuth server. ```typescript export async function start(config?: OauthConfig): Promise ``` -------------------------------- ### Start OAuth Flow (TypeScript) Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/MANIFEST.md Initiates the OAuth flow using the provided configuration. Ensure the necessary event listeners are set up before calling this function. ```typescript import { OAuth } from "tauri-plugin-oauth"; async function startOAuth() { const oauth = new OAuth(); await oauth.start({ provider: "github", clientId: "YOUR_CLIENT_ID", clientSecret: "YOUR_CLIENT_SECRET", scopes: ["read:user"] }); } ``` -------------------------------- ### TypeScript Configuration Priority Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/plugin-architecture.md Illustrates the order of configuration resolution for the TypeScript start() function. It checks the parameter config first, then tauri.conf.json, and finally uses library defaults. ```plaintext 1. Check parameter config config?.response config?.ports ↓ (if any missing) 2. Check tauri.conf.json plugins.oauth.response ↓ (if missing) 3. Use library defaults ports: OS-assigned response: "..." ``` -------------------------------- ### Install Tauri Plugin OAuth (TOML) Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/README.md Add the tauri-plugin-oauth dependency to your Cargo.toml file. ```toml # Cargo.toml [dependencies] tauri-plugin-oauth = "2" ``` -------------------------------- ### Integration Test OAuth Server Start Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/plugin-architecture.md Test the startup of the OAuth server by verifying that it returns a valid port number. Ensure the server is properly shut down afterwards. ```typescript describe('OAuth Plugin', () => { it('should start OAuth server', async () => { const port = await start({ ports: [9000, 9001] }); expect(port).toBeGreaterThan(0); await cancel(port); }); it('should handle valid URLs', async () => { const port = await start(); const urlPromise = new Promise((resolve) => { onUrl((url) => { resolve(url); }); }); // Simulate OAuth redirect // await sendOAuthRedirect(port); const url = await urlPromise; expect(url).toContain('code='); }); }); ``` -------------------------------- ### Example Flow: Cancellation Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/endpoints.md Demonstrates a typical flow for initiating an OAuth process and subsequently cancelling it using the provided TypeScript API. ```APIDOC ### Example Flow: Cancellation (TypeScript) #### Description This example illustrates how to initiate an OAuth flow and then cancel it using the tauri-plugin-oauth TypeScript API. #### Code ```typescript import { start, cancel } from '@fabianlars/tauri-plugin-oauth'; let oauthPort: number; async function initiateOAuth() { oauthPort = await start(); console.log(`OAuth server started on port ${oauthPort}`); // Redirect to OAuth provider window.location.href = `https://oauth.example.com/authorize?redirect_uri=http://localhost:${oauthPort}/cb`; } async function cancelOAuth() { if (oauthPort) { try { await cancel(oauthPort); console.log('OAuth flow cancelled'); } catch (error) { console.error('Cancel failed:', error); } } } // User clicks "Cancel" button document.getElementById('cancel-button').addEventListener('click', cancelOAuth); ``` ``` -------------------------------- ### Rust Backend OAuth Handler Example Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/MANIFEST.md Illustrates how to handle OAuth requests and responses on the Rust backend. This includes parsing URLs, validating codes, and performing the code exchange. ```rust use tauri_plugin_oauth::{OauthConfig, OauthState}; use tauri::State; use url::Url; #[tauri::command] async fn handle_oauth_callback( state: State<'_, OauthState>, url_str: String, ) -> Result { let url = Url::parse(&url_str).map_err(|e| format!("Failed to parse URL: {}", e))?; // Extract authorization code or error from the URL let code = url.query_pairs().find(|(k, _)| k == "code").map(|(_, v)| v.into_owned()); let error = url.query_pairs().find(|(k, _)| k == "error").map(|(_, v)| v.into_owned()); if let Some(auth_code) = code { // Perform code exchange with the OAuth provider // This typically involves making a POST request to the token endpoint // using the authorization code, client ID, client secret, and redirect URI. // The result of the code exchange (access token, refresh token, etc.) // should be returned or processed. Ok(format!("Received authorization code: {}", auth_code)) // Placeholder } else if let Some(error_msg) = error { Err(format!("OAuth error: {}", error_msg)) } else { Err("Invalid callback URL format.".to_string()) } } ``` -------------------------------- ### Minimal HTML Response Example Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/configuration.md A basic, self-contained HTML response for an OAuth redirect. It includes only the essential structure and a simple message. ```html Please return to the app. ``` -------------------------------- ### Rust API: Start OAuth Flow Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/00-START-HERE.md Initiates the OAuth flow using the Rust API. Requires a callback function to handle the OAuth URL. ```rust tauri_plugin_oauth::start(|url| { /* handle OAuth URL */ }) ``` -------------------------------- ### Enable Rust Logging with log and env_logger Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/errors.md Configure the `log` and `env_logger` crates in your `Cargo.toml` and initialize the logger in your Rust code to set the debug level and start logging. ```rust // In Cargo.toml [dependencies] log = "0.4" env_logger = "0.11" // In code fn main() { env_logger::builder() .filter_level(log::LevelFilter::Debug) .init(); start(|url| { log::info!("OAuth URL received: {}", url); }).expect("Failed to start server"); } ``` -------------------------------- ### React Hook Integration Example Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/MANIFEST.md Shows how to integrate the OAuth functionality into a React application using a custom hook. This pattern simplifies state management and lifecycle handling. ```typescript import { useState, useEffect, useCallback } from 'react'; import { OAuth } from 'tauri-plugin-oauth'; function useOAuth(config: OauthConfig) { const [token, setToken] = useState(null); const [error, setError] = useState(null); const [isLoading, setIsLoading] = useState(false); const oauth = new OAuth(); const startLogin = useCallback(async () => { setIsLoading(true); setError(null); setToken(null); const handleSuccess = (url: string) => { console.log('Login successful:', url); // Parse URL and set token setToken(url); // Placeholder setIsLoading(false); }; const handleError = (err: any) => { console.error('Login failed:', err); setError(err); setIsLoading(false); }; oauth.onUrl(handleSuccess); oauth.onInvalidUrl(handleError); try { await oauth.start(config); } catch (err) { handleError(err); } }, [config]); const logout = useCallback(() => { setToken(null); // Potentially clear tokens from storage and revoke session }, []); useEffect(() => { // Cleanup listeners on component unmount return () => { // Ideally, unregister listeners if the library provides a way }; }, []); return { token, error, isLoading, startLogin, logout }; } // Example usage in a component: // function MyComponent() { // const githubConfig = { provider: 'github', clientId: 'YOUR_GITHUB_CLIENT_ID' }; // const { token, error, isLoading, startLogin } = useOAuth(githubConfig); // // if (isLoading) return

Loading...

; // if (error) return

Error: {error.message}

; // if (token) return

Logged in!

; // // return ; // } ``` -------------------------------- ### Rust Plugin Configuration Priority Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/plugin-architecture.md Shows how the Rust plugin's start() command resolves configuration. It prioritizes provided config, then fetches from window.config() if the response is not set, falling back to library defaults. ```rust let mut config = config.unwrap_or_default(); if config.response.is_none() { config.response = window .config() .plugins .0 .get("oauth") .map(|v| v.as_str().unwrap().to_string().into()); } ``` -------------------------------- ### HTTP Request to Exit Endpoint Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/endpoints.md An example of an HTTP GET request to the /exit endpoint. This method is less preferred than the TCP signal for cancellation. ```http GET /exit HTTP/1.1 Host: 127.0.0.1:8000 Connection: close ``` -------------------------------- ### Handle AddrInUse Error in TypeScript Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/errors.md Catch and handle the `AddrInUse` error when starting the OAuth server in TypeScript. This example checks if the error message includes 'already in use' to identify the specific issue. ```typescript import { start } from '@fabianlars/tauri-plugin-oauth'; try { const port = await start({ ports: [8000, 8001, 8002] }); } catch (error) { if (error.includes('already in use')) { console.error('All configured ports are in use'); } } ``` -------------------------------- ### Start OAuth Server with Custom Configuration Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/api-reference/rust-oauth-module.md Use `start_with_config` to launch an OAuth server with specific ports and a custom response HTML. The handler closure is invoked with the redirect URL upon successful authentication. ```rust use tauri_plugin_oauth::{start_with_config, OauthConfig}; async fn start_with_fixed_ports() -> Result<(), String> { let config = OauthConfig { ports: Some(vec![8000, 8001, 8002]), response: Some( "

OAuth Complete

You can close this window.".into() ), }; let port = start_with_config(config, |url| { println!("Received OAuth URL: {}", url); }) .map_err(|e| format!("Server start failed: {}", e))?; println!("OAuth server listening on port {}", port); Ok(()) } ``` -------------------------------- ### Robust OAuth Error Handling in TypeScript Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/api-reference/usage-patterns.md This comprehensive example demonstrates how to implement robust error handling for the OAuth flow. It includes starting the server, setting up listeners for valid and invalid URLs, handling timeouts, and managing potential errors during the process. Ensure you have the necessary imports and helper functions like `showErrorDialog` and `exchangeCodeForTokens` defined. ```typescript import { start, cancel, onUrl, onInvalidUrl, OauthConfig } from '@fabianlars/tauri-plugin-oauth'; interface OAuthState { port: number | null; isActive: boolean; timeout: NodeJS.Timeout | null; } const oauthState: OAuthState = { port: null, isActive: false, timeout: null, }; async function startOAuthWithErrorHandling(): Promise { const config: OauthConfig = { ports: [8000, 8001, 8002, 8003], }; try { oauthState.port = await start(config); oauthState.isActive = true; console.log(`OAuth server started on port ${oauthState.port}`); // Set timeout to prevent hanging oauthState.timeout = setTimeout(() => { if (oauthState.isActive) { console.warn('OAuth flow timeout - canceling'); stopOAuth().catch(console.error); handleOAuthTimeout(); } }, 5 * 60 * 1000); // 5 minutes return oauthState.port; } catch (error) { console.error('Failed to start OAuth server:', error); handleOAuthStartError(error); return null; } } async function setupOAuthListeners(): Promise { try { // Listen for valid URLs const unlistenValid = await onUrl((url) => { clearTimeout(oauthState.timeout!) try { const urlObj = new URL(url); const code = urlObj.searchParams.get('code'); const state = urlObj.searchParams.get('state'); if (!code || !state) { handleOAuthError('Missing authorization code or state'); return; } // Validate state to prevent CSRF const storedState = sessionStorage.getItem('oauth_state'); if (state !== storedState) { handleOAuthError('State mismatch - possible CSRF attack'); return; } // Exchange code for tokens exchangeCodeForTokens(code); } catch (error) { handleOAuthError(`Failed to process URL: ${error}`); } }); // Listen for invalid URLs const unlistenInvalid = await onInvalidUrl((error) => { clearTimeout(oauthState.timeout!); handleOAuthError(`Invalid URL received: ${error}`); }); // Store unlisten functions for cleanup (window as any).__oauthCleanup = () => { unlistenValid(); unlistenInvalid(); }; } catch (error) { console.error('Failed to setup OAuth listeners:', error); } } async function stopOAuth(): Promise { if (oauthState.port === null) { return; } try { clearTimeout(oauthState.timeout!); await cancel(oauthState.port); oauthState.isActive = false; oauthState.port = null; console.log('OAuth server stopped'); } catch (error) { // Server might already be stopped - this is not necessarily an error console.debug('Error stopping OAuth server:', error); oauthState.port = null; } // Call cleanup functions (window as any).__oauthCleanup?.(); } // Error handlers function handleOAuthStartError(error: any): void { if (typeof error === 'string' && error.includes('already in use')) { // All configured ports are in use showErrorDialog('OAuth service unavailable - all ports in use. Try again later.'); } else { showErrorDialog(`OAuth initialization failed: ${error}`); } } function handleOAuthError(message: string): void { stopOAuth().catch(console.error); showErrorDialog(message); } function handleOAuthTimeout(): void { showErrorDialog('OAuth flow timed out. Please try again.'); } function showErrorDialog(message: string): void { // Implementation depends on your UI framework console.error(message); alert(message); } function exchangeCodeForTokens(code: string): void { // Implementation to exchange auth code for tokens console.log('Exchanging code for tokens:', code); } ``` -------------------------------- ### Example Logged Messages in Rust Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/errors.md These are examples of messages that may be logged by the Tauri Plugin OAuth when errors or warnings occur during operation. ```text [ERROR] Error reading incoming connection: ... [ERROR] Error emitting oauth://url event: ... [ERROR] Error emitting oauth://invalid-url event: ... [ERROR] Failed to write OAuth callback response: ... [ERROR] Failed to flush OAuth callback response: ... [WARN] `response` does not contain a body or head element. ... [ERROR] Client fetched callback path but didn't contain expected header. ``` -------------------------------- ### Server Lifecycle Flowchart Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/INDEX.md Illustrates the sequence of events from server startup to termination, including normal operation, cancellation, and exit conditions. ```text start() called ↓ Thread spawned, TcpListener created ↓ Port number returned immediately ↓ Server thread listens for connections ↓ OAuth redirect received ↓ Handler invoked with URL ↓ Server thread terminates OR cancel() called → server terminates OR /exit endpoint hit → server terminates ``` -------------------------------- ### Direct Rust Usage of Tauri OAuth Functions Source: https://github.com/fabianlars/tauri-plugin-oauth/blob/v2/_autodocs/configuration.md Demonstrates direct usage of the `start` and `start_with_config` functions from the tauri-plugin-oauth library in Rust, without using the Tauri plugin system. ```rust use tauri_plugin_oauth::{start, start_with_config, OauthConfig}; // Simple usage let port = start(|url| { println!("OAuth URL: {}", url); })?; // With config let config = OauthConfig { ports: Some(vec![3000, 3001]), response: Some("Custom HTML".into()), }; let port = start_with_config(config, |url| { // Handle OAuth URL })?; ```