Skip to content
Open
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
21 changes: 14 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,12 @@ pub fn run() {
### TypeScript

```typescript
import { start, cancel, onUrl, onInvalidUrl } from '@fabianlars/tauri-plugin-oauth';
import {
start,
cancel,
onUrl,
onInvalidUrl,
} from "@fabianlars/tauri-plugin-oauth";

async function startOAuthFlow() {
try {
Expand All @@ -75,25 +80,24 @@ async function startOAuthFlow() {

// Set up listeners for OAuth results
await onUrl((url) => {
console.log('Received OAuth URL:', 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);
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');
console.log("OAuth server stopped");
} catch (error) {
console.error('Error stopping OAuth server:', error);
console.error("Error stopping OAuth server:", error);
}
}
```
Expand All @@ -102,12 +106,15 @@ async function stopOAuthServer() {

You can configure the plugin behavior using the `OauthConfig` struct:

If you set the `redirect_uri` field, the plugin will redirect to the provided URL after the OAuth process is complete instead of returning the `response` content.

```rust
use tauri_plugin_oauth::OauthConfig;

let config = OauthConfig {
ports: Some(vec![8000, 8001, 8002]),
response: Some("OAuth process completed. You can close this window.".into()),
redirect_uri: Some("http://tauri.localhost/homepage".into()),
};

start_with_config(config, |url| {
Expand All @@ -125,7 +132,7 @@ start_with_config(config, |url| {

## Contributing

Contributions are always welcome! Please feel free to submit a Pull Request.
Contributions are always welcome! Please feel free to submit a Pull Request.

## License

Expand Down
54 changes: 53 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,45 @@ pub struct OauthConfig {
///
/// Default: `"<html><body>Please return to the app.</body></html>"`.
pub response: Option<Cow<'static, str>>,

/// The redirect uri to use for the oauth provider.
/// If this argument is provided, the server will redirect to the provided uri instead of return a htpp 200 response.
///
/// Default: None
pub redirect_uri: Option<Cow<'static, str>>,
}

fn handle_connection_with_redirect(
mut conn: TcpStream,
redirect_uri: &str,
port: u16,
) -> Option<String> {
let mut buffer = [0; 4048];
if let Err(io_err) = conn.read(&mut buffer) {
log::error!("Error reading incoming connection: {}", io_err.to_string());
};
if buffer[..4] == EXIT {
return Some(String::new());
}

let mut headers = [httparse::EMPTY_HEADER; 32];
let mut request = httparse::Request::new(&mut headers);
request.parse(&buffer).ok()?;

let path = request.path.unwrap_or_default();

// TODO: Test if unwrapping here is safe (enough).
conn.write_all(
format!(
"HTTP/1.1 302 Found\r\nLocation: {}\r\nContent-Length: 0\r\n\r\n",
redirect_uri
)
.as_bytes(),
)
.unwrap();
conn.flush().unwrap();
let url = format!("http://{}:{}{}", "127.0.0.1", port, path);
return Some(url);
}

/// Starts the localhost (using 127.0.0.1) server. Returns the port its listening on.
Expand Down Expand Up @@ -83,7 +122,20 @@ pub fn start_with_config<F: FnMut(String) + Send + 'static>(
for conn in listener.incoming() {
match conn {
Ok(conn) => {
if let Some(url) = handle_connection(conn, config.response.as_deref(), port) {
if let Some(redirect_uri) = &config.redirect_uri {
if let Some(url) =
handle_connection_with_redirect(conn, redirect_uri.as_ref(), port)
{
// Using an empty string to communicate that a shutdown was requested.
if !url.is_empty() {
handler(url);
}
// TODO: Check if exiting here is always okay.
break;
}
} else if let Some(url) =
handle_connection(conn, config.response.as_deref(), port)
{
// Using an empty string to communicate that a shutdown was requested.
if !url.is_empty() {
handler(url);
Expand Down