tauri-plugin-oauth

repository·v2·Indexed 42 days ago

https://github.com/fabianlars/tauri-plugin-oauth

A minimalistic Rust library and Tauri plugin for handling browser-based OAuth flows in desktop applications by spawning a temporary localhost server to capture redirects. Version 2.1.0 provides Rust and TypeScript APIs to start the server, listen for valid or invalid URLs, and configure server behavior via OauthConfig, including custom ports and redirect URIs.

Tokens
3.7K
Snippets
13
Records
18
Agent score
51%

What's inside tauri-plugin-oauth

  1. Redirect the browser after the OAuth callback

    v2

    By setting the redirect_uri field in OauthConfig, the plugin will respond to the OAuth callback with a 302 Found status code to that URL instead of serving an inline HTML response. This is useful for landing the user on a specific page within your application (e.g., a Tauri window URL).

    Important Limitation: When redirect_uri is used, the handler closure receives the localhost URL hit by the provider (e.g., http://127.0.0.1:<port>/?code=...), but it does not receive the URL fragment (#...). If your OAuth flow uses an implicit flow where the token is in the fragment, you must parse window.location on the redirected page and manually forward the result back to your app.

    let config = OauthConfig {
        redirect_uri: Some("http://tauri.localhost/oauth/done".into()),
        ..Default::default()
    };
  2. Use the OAuth plugin in TypeScript

    v2

    The TypeScript API allows you to start the OAuth server, listen for the resulting URL, and cancel the server when finished.

    Key functions:

    • start(): Starts the server and returns the port number.
    • onUrl(callback): Sets up a listener that triggers when an OAuth redirect is captured.
    • onInvalidUrl(callback): Sets up a listener for invalid URLs.
    • cancel(port): Stops the server running on the specified port.
    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);
      }
    }
    
    async function stopOAuthServer(port: number) {
      try {
        await cancel(port);
        console.log("OAuth server stopped");
      } catch (error) {
        console.error("Error stopping OAuth server:", error);
      }
    }
  3. Use the OAuth plugin in Rust

    v2

    To use the plugin in your Rust backend, you must initialize it in your Tauri builder and use the start function to spawn a temporary localhost server that captures OAuth redirects.

    Note on Security: Because the localhost port is unprotected, you should validate the received URL within the closure. It is recommended to only emit the token or specific data back to the frontend rather than the full URL.

    use tauri::{command, Emitter, Window};
    use tauri_plugin_oauth::start;
    
    #[command]
    async fn start_server(window: Window) -> Result<u16, String> {
        start(move |url| {
            // Validate the URL here and emit only necessary data
            let _ = window.emit("redirect_uri", url);
        })
            .map_err(|err| err.to_string())
    }
    
    #[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");
    }
  4. Install tauri-plugin-oauth

    v2

    To use this plugin in your Tauri project, add the dependency to your Rust backend and the corresponding package to your frontend.

    Rust (Cargo.toml):

    [dependencies]
    tauri-plugin-oauth = "2"

    TypeScript (npm/yarn):

    npm install @fabianlars/tauri-plugin-oauth@2
    # or
    yarn add @fabianlars/tauri-plugin-oauth@2
  5. Configure the OAuth server with OauthConfig

    v2

    You can customize the behavior of the OAuth server using the OauthConfig struct in Rust. This allows you to specify preferred ports, a custom response message, or a redirect URI.

    Configuration Options:

    • ports: Option<Vec<u16>> - A list of preferred ports to attempt to bind to.
    • response: Option<String> - A custom HTML response message to serve to the browser.
    • redirect_uri: Option<String> - A URL to which the plugin will issue a 302 Found response after capturing the callback.
    use tauri_plugin_oauth::OauthConfig;
    use tauri_plugin_oauth::start_with_config;
    
    let config = OauthConfig {
        ports: Some(vec![8000, 8001, 8002]),
        response: Some("OAuth process completed. You can close this window.".into()),
        ..Default::default()
    };
    
    start_with_config(config, |url| {
        // Handle OAuth URL
    })
    .expect("Failed to start OAuth server");
  6. Security considerations for OAuth flows

    v2

    When implementing OAuth with this plugin, follow these security best practices:

    1. Validate URLs: Always validate the received OAuth URL on your server-side (the Rust handler) before treating it as authentic.
    2. Use HTTPS: Ensure your OAuth flow uses HTTPS to prevent man-in-the-middle attacks.
    3. Secure Storage: Implement robust token storage and refresh mechanisms within your application.
  7. Configure `OauthConfig`

    v2

    The OauthConfig struct allows you to customize the OAuth listener server:

    FieldTypeDefaultDescription
    portsOption<Vec<u16>>NoneAn array of hard-coded ports the server should try to bind to. Use this if your provider doesn't accept wildcard localhost addresses. If None, the system picks a free port.
    responseOption<Cow<'static, str>>"<html><body..."An optional static HTML string sent to the user after redirection. Keep it small and self-contained.
    redirect_uriOption<Cow<'static, str>>NoneAn optional URL the server redirects the browser to after receiving the callback. Note: The handler receives the URL (path + query) but not the fragment (#...). If using implicit flow (token in fragment), you must parse window.location on the redirected page yourself.
  8. Configure OAuth plugin permissions

    v2

    When using tauri-plugin-oauth, you must explicitly grant permissions for the plugin's commands in your Tauri permission configuration. The plugin uses specific identifiers to control access to the start and cancel commands.

    Use the allow identifiers to enable functionality and the deny identifiers to restrict it. If no permission is granted, the commands will be inaccessible to the frontend.

    | Identifier | Description |
    | --- | --- |
    | `oauth:allow-cancel` | Enables the cancel command without any pre-configured scope |
    | `oauth:deny-cancel` | Denies the cancel command without any pre-configured scope |
    | `oauth:allow-start` | Enables the start command without any pre-configured scope |
    | `oauth:deny-start` | Denies the start command without any pre-configured scope |
  9. Stop the OAuth server with `cancel()`

    v2

    Use the cancel function to stop a running server on a specific port. This sends a special exit signal to the server thread.

    Returns Ok(()) if successful, or a std::io::Error if the server could not be reached.

    use tauri_plugin_oauth::cancel;
    
    // Stop the server running on port 8080
    cancel(8080).expect("Failed to cancel server");
  10. Start the OAuth server with `start()`

    v2

    Use the start function to launch a localhost server (binding to 127.0.0.1) to listen for OAuth callbacks. You must provide a closure (handler) that will be executed when a successful connection is made. The handler receives the full URL as a String.

    Security Warning: Because the localhost port is unprotected, you must verify the URL inside your handler function to ensure it is the expected callback.

    Returns the port number the server is listening on, or a std::io::Error if creation fails.

    use tauri_plugin_oauth::start;
    
    // Example usage in Rust
    let port = start(|url| {
        println!("Received OAuth callback URL: {}", url);
        // TODO: Verify the URL here for security!
    }).expect("Failed to start OAuth server");
    
    println!("Server listening on port: {}", port);
  11. Configure the OAuth server with `start_with_config()`

    v2

    Use start_with_config when you need to customize the server behavior beyond the defaults. You can specify preferred ports, a custom HTML response, or a redirect URI.

    Returns the port number the server is listening on, or a std::io::Error if creation fails.

    use tauri_plugin_oauth::{start_with_config, OauthConfig};
    use std::borrow::Cow;
    
    let config = OauthConfig {
        ports: Some(vec![8080, 8081]),
        response: Some(Cow::Borrowed("<html><body>Auth successful!</body></html>")),
        redirect_uri: Some(Cow::Borrowed("https://myapp.com/callback")),
    };
    
    let port = start_with_config(config, |url| {
        println!("Callback URL: {}", url);
    }).expect("Failed to start server");