Files
AFFiNE-Mirror/packages/frontend/apps/android/src/proxy.ts
T
DarkSky ce9841df9d feat(server): passkey pre-refactor (#15060)
#### PR Dependency Tree


* **PR #15060** 👈

This tree was auto-generated by
[Charcoal](https://github.com/danerwilliams/charcoal)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* OpenApp native sign-in and native session exchange (JWT) for mobile &
desktop.
  * Centralized short-lived auth challenge store for one-time tokens.
* Encrypted per-endpoint token storage and native token handlers
(Android, iOS, Electron).

* **Improvements**
* Richer auth-method reporting (password, magic link, OAuth, passkey)
and improved sign-in flows.
* Hardened magic-link, OAuth, and session issuance; JWT-backed sessions
and websocket JWT support.
* UX tweaks: form-based password submit, OTP autocomplete, adjusted
captcha flow.

* **Bug Fixes**
  * Expanded tests and auth-state resets to avoid cross-test leakage.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-01 17:11:15 +08:00

95 lines
2.5 KiB
TypeScript

import { Auth } from './plugins/auth';
function authEndpointForUrl(url: string | URL) {
try {
const parsed = new URL(url, globalThis.location.origin);
return parsed.protocol === 'http:' || parsed.protocol === 'https:'
? parsed.origin
: null;
} catch {
return null;
}
}
function canonicalEndpoint(endpoint: string) {
return authEndpointForUrl(endpoint) ?? endpoint;
}
/**
* the below code includes the custom fetch and xmlhttprequest implementation for ios webview.
* should be included in the entry file of the app or webworker.
*/
const rawFetch = globalThis.fetch;
globalThis.fetch = async (input: RequestInfo | URL, init?: RequestInit) => {
const request = new Request(input, init);
const origin = authEndpointForUrl(request.url);
const token = origin
? await readEndpointToken(origin).catch(() => null)
: null;
if (token) {
request.headers.set('Authorization', `Bearer ${token}`);
}
return rawFetch(request);
};
const rawXMLHttpRequest = globalThis.XMLHttpRequest;
const xhrRequestUrls = new WeakMap<XMLHttpRequest, string>();
globalThis.XMLHttpRequest = class extends rawXMLHttpRequest {
override open(
method: string,
url: string | URL,
async: boolean = true,
username?: string | null,
password?: string | null
): void {
xhrRequestUrls.set(this, url.toString());
return super.open(
method,
url,
async,
username ?? undefined,
password ?? undefined
);
}
override send(body?: Document | XMLHttpRequestBodyInit | null): void {
const requestUrl = xhrRequestUrls.get(this);
const origin = authEndpointForUrl(requestUrl ?? globalThis.location.href);
(origin ? readEndpointToken(origin) : Promise.resolve(null)).then(
token => {
if (token) {
this.setRequestHeader('Authorization', `Bearer ${token}`);
}
return super.send(body);
},
() => {
return super.send(body);
}
);
}
};
export async function readEndpointToken(
endpoint: string
): Promise<string | null> {
const { token } = await Auth.readEndpointToken({
endpoint: canonicalEndpoint(endpoint),
});
return token ?? null;
}
export async function writeEndpointToken(endpoint: string, token: string) {
await Auth.writeEndpointToken({
endpoint: canonicalEndpoint(endpoint),
token,
});
}
export async function deleteEndpointToken(endpoint: string) {
await Auth.deleteEndpointToken({ endpoint: canonicalEndpoint(endpoint) });
}