bitwarden_server_communication_config/wasm/
js_platform_api.rs1use bitwarden_threading::ThreadBoundRunner;
2use wasm_bindgen::prelude::*;
3
4use crate::{AcquiredCookie, ServerCommunicationConfigPlatformApi};
5
6#[wasm_bindgen(typescript_custom_section)]
7const TS_CUSTOM_TYPES: &'static str = r#"
8/**
9 * Platform API interface for acquiring SSO cookies.
10 *
11 * Platform clients implement this interface to handle cookie acquisition
12 * through browser redirects or other platform-specific mechanisms.
13 */
14export interface ServerCommunicationConfigPlatformApi {
15 /**
16 * Acquires cookies for the given hostname.
17 *
18 * This typically involves redirecting to an IdP login page and extracting
19 * cookies from the load balancer response. For sharded cookies, returns
20 * multiple entries with names like "CookieName-0", "CookieName-1", etc.
21 *
22 * @param hostname The server hostname (e.g., "vault.acme.com")
23 * @returns An array of AcquiredCookie objects, or undefined if acquisition failed or was cancelled
24 */
25 acquireCookies(hostname: string): Promise<AcquiredCookie[] | undefined>;
26}
27"#;
28
29#[wasm_bindgen]
30extern "C" {
31 #[wasm_bindgen(
33 js_name = ServerCommunicationConfigPlatformApi,
34 typescript_type = "ServerCommunicationConfigPlatformApi"
35 )]
36 pub type RawJsServerCommunicationConfigPlatformApi;
37
38 #[wasm_bindgen(catch, method, structural, js_name = acquireCookies)]
40 pub async fn acquire_cookies(
41 this: &RawJsServerCommunicationConfigPlatformApi,
42 hostname: String,
43 ) -> Result<JsValue, JsValue>;
44}
45
46pub struct JsServerCommunicationConfigPlatformApi(
52 ThreadBoundRunner<RawJsServerCommunicationConfigPlatformApi>,
53);
54
55impl JsServerCommunicationConfigPlatformApi {
56 pub fn new(platform_api: RawJsServerCommunicationConfigPlatformApi) -> Self {
59 Self(ThreadBoundRunner::new(platform_api))
60 }
61}
62
63impl Clone for JsServerCommunicationConfigPlatformApi {
64 fn clone(&self) -> Self {
65 Self(self.0.clone())
66 }
67}
68
69#[async_trait::async_trait]
70impl ServerCommunicationConfigPlatformApi for JsServerCommunicationConfigPlatformApi {
71 async fn acquire_cookies(&self, hostname: String) -> Option<Vec<AcquiredCookie>> {
72 self.0
73 .run_in_thread(move |platform_api| async move {
74 let js_value = platform_api
75 .acquire_cookies(hostname)
76 .await
77 .map_err(|e| format!("{e:?}"))?;
78
79 if js_value.is_undefined() || js_value.is_null() {
80 return Ok(None);
81 }
82
83 let cookies: Vec<AcquiredCookie> =
84 serde_wasm_bindgen::from_value(js_value).map_err(|e| e.to_string())?;
85 Ok(Some(cookies))
86 })
87 .await
88 .ok()
89 .and_then(|result: Result<Option<Vec<AcquiredCookie>>, String>| result.ok())
90 .flatten()
91 }
92}