Add deeplink to parse oauth callback url in tauri apps (#92)

This commit is contained in:
Huang Xin
2025-01-03 23:24:30 +01:00
committed by GitHub
parent 3ad26d9d8f
commit e885d22631
8 changed files with 184 additions and 28 deletions
+1
View File
@@ -35,6 +35,7 @@
"@supabase/supabase-js": "^2.47.7",
"@tauri-apps/api": "2.1.1",
"@tauri-apps/plugin-cli": "^2.2.0",
"@tauri-apps/plugin-deep-link": "^2.2.0",
"@tauri-apps/plugin-dialog": "^2.2.0",
"@tauri-apps/plugin-fs": "^2.2.0",
"@tauri-apps/plugin-http": "^2.2.0",
+121 -3
View File
@@ -15,6 +15,7 @@ dependencies = [
"tauri",
"tauri-build 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"tauri-plugin-cli",
"tauri-plugin-deep-link",
"tauri-plugin-devtools",
"tauri-plugin-dialog",
"tauri-plugin-fs",
@@ -891,6 +892,26 @@ dependencies = [
"crossbeam-utils",
]
[[package]]
name = "const-random"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359"
dependencies = [
"const-random-macro",
]
[[package]]
name = "const-random-macro"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e"
dependencies = [
"getrandom 0.2.15",
"once_cell",
"tiny-keccak",
]
[[package]]
name = "convert_case"
version = "0.4.0"
@@ -1033,6 +1054,12 @@ version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "crunchy"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "crypto-common"
version = "0.1.6"
@@ -1277,6 +1304,15 @@ dependencies = [
"syn 2.0.91",
]
[[package]]
name = "dlv-list"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f"
dependencies = [
"const-random",
]
[[package]]
name = "document-features"
version = "0.2.10"
@@ -2016,6 +2052,12 @@ dependencies = [
"ahash",
]
[[package]]
name = "hashbrown"
version = "0.14.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
[[package]]
name = "hashbrown"
version = "0.15.2"
@@ -3224,6 +3266,16 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "ordered-multimap"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79"
dependencies = [
"dlv-list",
"hashbrown 0.14.5",
]
[[package]]
name = "ordered-stream"
version = "0.2.0"
@@ -4004,7 +4056,7 @@ dependencies = [
"wasm-streams",
"web-sys",
"webpki-roots",
"windows-registry",
"windows-registry 0.2.0",
]
[[package]]
@@ -4084,6 +4136,17 @@ dependencies = [
"syn 1.0.109",
]
[[package]]
name = "rust-ini"
version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e310ef0e1b6eeb79169a1171daf9abcb87a2e17c03bee2c4bb100b55c75409f"
dependencies = [
"cfg-if",
"ordered-multimap",
"trim-in-place",
]
[[package]]
name = "rust_decimal"
version = "1.36.0"
@@ -4958,6 +5021,26 @@ dependencies = [
"thiserror 2.0.9",
]
[[package]]
name = "tauri-plugin-deep-link"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35d51ffd286073414d26353bcfc9e83e3cd63f96fa7f7a912f92f2118e5de5a6"
dependencies = [
"dunce",
"rust-ini",
"serde",
"serde_json",
"tauri",
"tauri-plugin",
"tauri-utils 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"thiserror 2.0.9",
"tracing",
"url",
"windows-registry 0.3.0",
"windows-result",
]
[[package]]
name = "tauri-plugin-devtools"
version = "2.0.0"
@@ -5422,6 +5505,15 @@ dependencies = [
"time-core",
]
[[package]]
name = "tiny-keccak"
version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237"
dependencies = [
"crunchy",
]
[[package]]
name = "tinystr"
version = "0.7.6"
@@ -5783,6 +5875,12 @@ dependencies = [
"windows-sys 0.59.0",
]
[[package]]
name = "trim-in-place"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "343e926fc669bc8cde4fa3129ab681c63671bae288b1f1081ceee6d9d37904fc"
[[package]]
name = "try-lock"
version = "0.2.5"
@@ -6332,7 +6430,7 @@ dependencies = [
"windows-implement",
"windows-interface",
"windows-result",
"windows-strings",
"windows-strings 0.1.0",
"windows-targets 0.52.6",
]
@@ -6365,7 +6463,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0"
dependencies = [
"windows-result",
"windows-strings",
"windows-strings 0.1.0",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-registry"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bafa604f2104cf5ae2cc2db1dee84b7e6a5d11b05f737b60def0ffdc398cbc0a"
dependencies = [
"windows-result",
"windows-strings 0.2.0",
"windows-targets 0.52.6",
]
@@ -6388,6 +6497,15 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-strings"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "978d65aedf914c664c510d9de43c8fd85ca745eaff1ed53edf409b479e441663"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.45.0"
+1
View File
@@ -34,6 +34,7 @@ tauri-plugin-shell = "2"
tauri-plugin-process = "2"
tauri-plugin-oauth = "2"
tauri-plugin-opener = "2.2.2"
tauri-plugin-deep-link = "2"
[patch.crates-io]
tauri = { path = "../../../packages/tauri/crates/tauri" }
@@ -60,6 +60,7 @@
"process:allow-restart",
"oauth:allow-start",
"oauth:allow-cancel",
"opener:default"
"opener:default",
"deep-link:default"
]
}
+1
View File
@@ -74,6 +74,7 @@ async fn start_server(window: Window) -> Result<u16, String> {
pub fn run() {
let builder = tauri::Builder::default()
.plugin(tauri_plugin_process::init())
.plugin(tauri_plugin_deep_link::init())
.plugin(tauri_plugin_oauth::init())
.invoke_handler(tauri::generate_handler![start_server])
.plugin(tauri_plugin_shell::init())
@@ -130,6 +130,12 @@
}
]
},
"deep-link": {
"mobile": [{ "host": "web.readest.com" }],
"desktop": {
"schemes": ["readest"]
}
},
"updater": {
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEU0OTAxMURGQkUzQjFENTQKUldSVUhUdSszeEdRNUExdmFkWnlvYWNYNG5wamkxMmUxRk5SejlMOTJVd28yNXlVTDh6Wld4OC8K",
"endpoints": ["https://github.com/readest/readest/releases/latest/download/latest.json"]
+42 -24
View File
@@ -17,6 +17,7 @@ import { useTheme } from '@/hooks/useTheme';
import { useEnv } from '@/context/EnvContext';
import { useSettingsStore } from '@/store/settingsStore';
import { isTauriAppPlatform } from '@/services/environment';
import { onOpenUrl } from '@tauri-apps/plugin-deep-link';
import { start, cancel, onUrl, onInvalidUrl } from '@fabianlars/tauri-plugin-oauth';
import { openUrl } from '@tauri-apps/plugin-opener';
import { handleAuthCallback } from '@/helpers/auth';
@@ -64,7 +65,10 @@ export default function AuthPage() {
provider,
options: {
skipBrowserRedirect: true,
redirectTo: `http://localhost:${port}`,
redirectTo:
process.env.NODE_ENV === 'production'
? 'readest://auth/callback'
: `http://localhost:${port}`,
},
});
@@ -75,34 +79,45 @@ export default function AuthPage() {
openUrl(data.url);
};
const startOAuthServer = async () => {
const handleOAuthUrl = async (url: string) => {
console.log('Received OAuth URL:', url);
const hashMatch = url.match(/#(.*)/);
if (hashMatch) {
const hash = hashMatch[1];
const params = new URLSearchParams(hash);
const accessToken = params.get('access_token');
const refreshToken = params.get('refresh_token');
const next = params.get('next') ?? '/';
if (accessToken) {
handleAuthCallback({ accessToken, refreshToken, next, login, navigate: router.push });
}
}
};
const startTauriOAuth = async () => {
try {
const port = await start();
setPort(port);
console.log(`OAuth server started on port ${port}`);
if (process.env.NODE_ENV === 'production') {
await onOpenUrl((urls) => {
urls.forEach((url) => {
handleOAuthUrl(url);
});
});
} else {
const port = await start();
setPort(port);
console.log(`OAuth server started on port ${port}`);
await onUrl((url) => {
console.log('Received OAuth URL:', url);
const hashMatch = url.match(/#(.*)/);
if (hashMatch) {
const hash = hashMatch[1];
const params = new URLSearchParams(hash);
const accessToken = params.get('access_token');
const refreshToken = params.get('refresh_token');
const next = params.get('next') ?? '/';
handleAuthCallback({ accessToken, refreshToken, next, login, navigate: router.push });
}
});
await onInvalidUrl((url) => {
console.log('Received invalid OAuth URL:', url);
});
await onUrl(handleOAuthUrl);
await onInvalidUrl((url) => {
console.log('Received invalid OAuth URL:', url);
});
}
} catch (error) {
console.error('Error starting OAuth server:', error);
}
};
const stopOAuthServer = async () => {
const stopTauriOAuth = async () => {
try {
if (port) {
await cancel(port);
@@ -126,10 +141,10 @@ export default function AuthPage() {
if (isOAuthServerRunning.current) return;
isOAuthServerRunning.current = true;
startOAuthServer();
startTauriOAuth();
return () => {
isOAuthServerRunning.current = false;
stopOAuthServer();
stopTauriOAuth();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
@@ -156,6 +171,9 @@ export default function AuthPage() {
return null;
}
// For tauri app development, use a custom OAuth server to handle the OAuth callback
// For tauri app production, use deeplink to handle the OAuth callback
// For web app, use the built-in OAuth callback page /auth/callback
return isTauriAppPlatform() ? (
<div className='flex pt-11'>
<button
+10
View File
@@ -50,6 +50,9 @@ importers:
'@tauri-apps/plugin-cli':
specifier: ^2.2.0
version: 2.2.0
'@tauri-apps/plugin-deep-link':
specifier: ^2.2.0
version: 2.2.0
'@tauri-apps/plugin-dialog':
specifier: ^2.2.0
version: 2.2.0
@@ -787,6 +790,9 @@ packages:
'@tauri-apps/plugin-cli@2.2.0':
resolution: {integrity: sha512-rvNhMog9rHr01Xk+trBFKJ0eZICIvPkm9GX6ogB89/0hROU/lf+a/sb4vC0wtSeR7zrJuCSxwxYuvHCZheaYFA==}
'@tauri-apps/plugin-deep-link@2.2.0':
resolution: {integrity: sha512-H6mkxr2KZ3XJcKL44tiq6cOjCw9DL8OgU1xjn3j26Qsn+H/roPFiyhR7CHuB8Ar+sQFj4YVlfmJwtBajK2FETQ==}
'@tauri-apps/plugin-dialog@2.2.0':
resolution: {integrity: sha512-6bLkYK68zyK31418AK5fNccCdVuRnNpbxquCl8IqgFByOgWFivbiIlvb79wpSXi0O+8k8RCSsIpOquebusRVSg==}
@@ -3741,6 +3747,10 @@ snapshots:
dependencies:
'@tauri-apps/api': 2.1.1
'@tauri-apps/plugin-deep-link@2.2.0':
dependencies:
'@tauri-apps/api': 2.1.1
'@tauri-apps/plugin-dialog@2.2.0':
dependencies:
'@tauri-apps/api': 2.1.1