@rakomi/react-native 0.0.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/COMPLIANCE.md +90 -0
- package/LICENSE +21 -0
- package/README.md +327 -2
- package/SECURITY.md +206 -0
- package/THIRD-PARTY-NOTICES +11 -0
- package/dist/index.cjs +2788 -0
- package/dist/index.d.cts +698 -0
- package/dist/index.d.ts +698 -0
- package/dist/index.js +2681 -0
- package/dist/native/index.cjs +646 -0
- package/dist/native/index.d.cts +143 -0
- package/dist/native/index.d.ts +143 -0
- package/dist/native/index.js +637 -0
- package/dist/passkey-adapter-D_Z3Z7lV.d.cts +469 -0
- package/dist/passkey-adapter-D_Z3Z7lV.d.ts +469 -0
- package/package.json +96 -5
- package/sbom.cdx.json +72 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { N as NativeAuthAdapter } from '../passkey-adapter-D_Z3Z7lV.cjs';
|
|
2
|
+
export { A as AppLifecycle, r as AppStateSubscription, a as AppStateValue, b as AttestationVerifier, B as BackgroundTask, c as BiometricGate, d as BiometricResult, e as BrowserAuthSessionOptions, f as BrowserAuthSessionResult, C as ConnectivityProvider, g as CreateDefaultExpoAdapterOptions, h as CreateNativeDpopProverOptions, i as CreateNativePasskeyAdapterOptions, j as DeepLinkProvider, s as DeepLinkSubscription, k as DpopProofInput, D as DpopProver, l as NativeDpopModuleSpec, m as NativePasskeyCeremonyAdapter, n as NativePasskeyModuleSpec, t as NetInfoSubscription, P as ParClient, S as SystemBrowser, T as TokenCache, o as createDefaultExpoAdapter, p as createNativeDpopProver, q as createNativePasskeyAdapter, u as probePlatformAuthenticator } from '../passkey-adapter-D_Z3Z7lV.cjs';
|
|
3
|
+
import '@rakomi/sdk-core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Reference implementation: bare React Native `NativeAuthAdapter`.
|
|
7
|
+
*
|
|
8
|
+
* For consumers NOT on Expo. Wires the same contract the default Expo adapter
|
|
9
|
+
* implements (`createDefaultExpoAdapter`) but using bare-RN-friendly community
|
|
10
|
+
* packages:
|
|
11
|
+
*
|
|
12
|
+
* - `react-native-keychain` for secure storage
|
|
13
|
+
* - `react-native-inappbrowser-reborn` for system browser (Custom Tabs / SFSafariViewController)
|
|
14
|
+
* - `react-native-quick-crypto` for `getRandomBytes` + `digestSha256`
|
|
15
|
+
* - `react-native/Linking` for deep-link callback ingest
|
|
16
|
+
* - `react-native-biometrics` for biometric gate
|
|
17
|
+
* - `react-native/AppState` for app-lifecycle transitions
|
|
18
|
+
* - `@react-native-community/netinfo` for connectivity
|
|
19
|
+
*
|
|
20
|
+
* **Not a default export** bare-RN consumers MUST call `createBareRnAdapter`
|
|
21
|
+
* explicitly and pass the result via `<RakomiProvider nativeAdapter={...}>`. We
|
|
22
|
+
* keep this in `src/native/` as documentation/reference; the actual implementation
|
|
23
|
+
* stubs are intentional — `NotImplementedError` thrown lines indicate where the
|
|
24
|
+
* bare-RN package import goes. Replace the throws with the real package binding.
|
|
25
|
+
*
|
|
26
|
+
* Why stubbed: bare-RN packages have install-time native code that can't be
|
|
27
|
+
* imported at SDK build time. Consumer's bundler links them at app build.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
interface CreateBareRnAdapterOptions {
|
|
31
|
+
/** Required injection — `react-native-quick-crypto` named exports. */
|
|
32
|
+
quickCrypto: {
|
|
33
|
+
randomBytes(length: number): Uint8Array;
|
|
34
|
+
createHash(alg: 'sha256'): {
|
|
35
|
+
update(b: Uint8Array): {
|
|
36
|
+
digest(): Uint8Array;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
/** Required injection — `react-native-keychain` namespace. */
|
|
41
|
+
keychain: {
|
|
42
|
+
setGenericPassword(username: string, password: string, options: {
|
|
43
|
+
service: string;
|
|
44
|
+
accessible?: string;
|
|
45
|
+
}): Promise<unknown>;
|
|
46
|
+
getGenericPassword(options: {
|
|
47
|
+
service: string;
|
|
48
|
+
authenticationPrompt?: {
|
|
49
|
+
title: string;
|
|
50
|
+
};
|
|
51
|
+
}): Promise<{
|
|
52
|
+
username: string;
|
|
53
|
+
password: string;
|
|
54
|
+
} | false>;
|
|
55
|
+
resetGenericPassword(options: {
|
|
56
|
+
service: string;
|
|
57
|
+
}): Promise<boolean>;
|
|
58
|
+
};
|
|
59
|
+
/** Required injection — `react-native-inappbrowser-reborn` namespace. */
|
|
60
|
+
inAppBrowser: {
|
|
61
|
+
isAvailable(): Promise<boolean>;
|
|
62
|
+
openAuth(url: string, redirectUri: string, options?: {
|
|
63
|
+
ephemeralWebSession?: boolean;
|
|
64
|
+
}): Promise<{
|
|
65
|
+
type: 'success' | 'cancel' | 'dismiss';
|
|
66
|
+
url?: string;
|
|
67
|
+
}>;
|
|
68
|
+
};
|
|
69
|
+
/** Required injection — `react-native-biometrics` instance. */
|
|
70
|
+
biometrics: {
|
|
71
|
+
isSensorAvailable(): Promise<{
|
|
72
|
+
available: boolean;
|
|
73
|
+
biometryType?: string;
|
|
74
|
+
}>;
|
|
75
|
+
simplePrompt(options: {
|
|
76
|
+
promptMessage: string;
|
|
77
|
+
cancelButtonText?: string;
|
|
78
|
+
}): Promise<{
|
|
79
|
+
success: boolean;
|
|
80
|
+
error?: string;
|
|
81
|
+
}>;
|
|
82
|
+
};
|
|
83
|
+
/** Required injection — `react-native/Linking` namespace. */
|
|
84
|
+
linking: {
|
|
85
|
+
getInitialURL(): Promise<string | null>;
|
|
86
|
+
addEventListener(event: 'url', handler: (e: {
|
|
87
|
+
url: string;
|
|
88
|
+
}) => void): {
|
|
89
|
+
remove(): void;
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
/** Required injection — `react-native/AppState` namespace. */
|
|
93
|
+
appState: {
|
|
94
|
+
currentState: 'active' | 'background' | 'inactive' | 'unknown';
|
|
95
|
+
addEventListener(event: 'change', handler: (state: 'active' | 'background' | 'inactive' | 'unknown') => void): {
|
|
96
|
+
remove(): void;
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
/** Required injection — `@react-native-community/netinfo` namespace. */
|
|
100
|
+
netInfo: {
|
|
101
|
+
fetch(): Promise<{
|
|
102
|
+
isConnected: boolean | null;
|
|
103
|
+
}>;
|
|
104
|
+
addEventListener(handler: (state: {
|
|
105
|
+
isConnected: boolean | null;
|
|
106
|
+
}) => void): () => void;
|
|
107
|
+
};
|
|
108
|
+
/** Tenant-scoped Keychain service prefix. Default `'rakomi'`. */
|
|
109
|
+
keychainServicePrefix?: string;
|
|
110
|
+
}
|
|
111
|
+
declare function createBareRnAdapter(options: CreateBareRnAdapterOptions): NativeAuthAdapter;
|
|
112
|
+
|
|
113
|
+
/** Which ceremony produced this envelope. The required-set differs per direction — deliberately. */
|
|
114
|
+
type CredentialEnvelopeKind = 'registration' | 'assertion';
|
|
115
|
+
/** The envelope broke the W3C contract. Terminal: the module is broken, retrying changes nothing. */
|
|
116
|
+
declare class CredentialEnvelopeError extends Error {
|
|
117
|
+
constructor(message: string);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Validate a parsed native response against the W3C envelope for `kind`.
|
|
121
|
+
*
|
|
122
|
+
* Throws {@link CredentialEnvelopeError} naming the field and the violated rule — never the field's
|
|
123
|
+
* VALUE. A `PasskeyError` message reaches logs and crash reporters; a credential id and a
|
|
124
|
+
* `clientDataJSON` are durable user identifiers, so the diagnosis must be free of them.
|
|
125
|
+
*/
|
|
126
|
+
declare function assertW3cCredentialEnvelope(kind: CredentialEnvelopeKind, parsed: unknown): void;
|
|
127
|
+
/**
|
|
128
|
+
* Validate, then **re-project** the envelope onto the members the contract knows.
|
|
129
|
+
*
|
|
130
|
+
* Validating without projecting is a check, not a boundary. The bridge used to forward the whole parsed
|
|
131
|
+
* object, and the server accepts the credential as an opaque blob — so every extra member a buggy or
|
|
132
|
+
* hostile module invented rode straight through to persistence. A `transports` that is a *string*
|
|
133
|
+
* instead of an array, or a five-thousand-element array, lands in the database and then poisons every
|
|
134
|
+
* subsequent `allowCredentials` for that user. Dropping unknown members costs nothing (the server reads
|
|
135
|
+
* none of them) and closes the class outright, instead of blacklisting the shapes we happened to think
|
|
136
|
+
* of.
|
|
137
|
+
*
|
|
138
|
+
* `Object.create(null)` for the projection, so a `"__proto__"` key that survived `JSON.parse` as an own
|
|
139
|
+
* property cannot be carried into an object with a real prototype further down.
|
|
140
|
+
*/
|
|
141
|
+
declare function sanitizeCredentialEnvelope(kind: CredentialEnvelopeKind, parsed: unknown): Record<string, unknown>;
|
|
142
|
+
|
|
143
|
+
export { type CreateBareRnAdapterOptions, CredentialEnvelopeError, type CredentialEnvelopeKind, NativeAuthAdapter, assertW3cCredentialEnvelope, createBareRnAdapter, sanitizeCredentialEnvelope };
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { N as NativeAuthAdapter } from '../passkey-adapter-D_Z3Z7lV.js';
|
|
2
|
+
export { A as AppLifecycle, r as AppStateSubscription, a as AppStateValue, b as AttestationVerifier, B as BackgroundTask, c as BiometricGate, d as BiometricResult, e as BrowserAuthSessionOptions, f as BrowserAuthSessionResult, C as ConnectivityProvider, g as CreateDefaultExpoAdapterOptions, h as CreateNativeDpopProverOptions, i as CreateNativePasskeyAdapterOptions, j as DeepLinkProvider, s as DeepLinkSubscription, k as DpopProofInput, D as DpopProver, l as NativeDpopModuleSpec, m as NativePasskeyCeremonyAdapter, n as NativePasskeyModuleSpec, t as NetInfoSubscription, P as ParClient, S as SystemBrowser, T as TokenCache, o as createDefaultExpoAdapter, p as createNativeDpopProver, q as createNativePasskeyAdapter, u as probePlatformAuthenticator } from '../passkey-adapter-D_Z3Z7lV.js';
|
|
3
|
+
import '@rakomi/sdk-core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Reference implementation: bare React Native `NativeAuthAdapter`.
|
|
7
|
+
*
|
|
8
|
+
* For consumers NOT on Expo. Wires the same contract the default Expo adapter
|
|
9
|
+
* implements (`createDefaultExpoAdapter`) but using bare-RN-friendly community
|
|
10
|
+
* packages:
|
|
11
|
+
*
|
|
12
|
+
* - `react-native-keychain` for secure storage
|
|
13
|
+
* - `react-native-inappbrowser-reborn` for system browser (Custom Tabs / SFSafariViewController)
|
|
14
|
+
* - `react-native-quick-crypto` for `getRandomBytes` + `digestSha256`
|
|
15
|
+
* - `react-native/Linking` for deep-link callback ingest
|
|
16
|
+
* - `react-native-biometrics` for biometric gate
|
|
17
|
+
* - `react-native/AppState` for app-lifecycle transitions
|
|
18
|
+
* - `@react-native-community/netinfo` for connectivity
|
|
19
|
+
*
|
|
20
|
+
* **Not a default export** bare-RN consumers MUST call `createBareRnAdapter`
|
|
21
|
+
* explicitly and pass the result via `<RakomiProvider nativeAdapter={...}>`. We
|
|
22
|
+
* keep this in `src/native/` as documentation/reference; the actual implementation
|
|
23
|
+
* stubs are intentional — `NotImplementedError` thrown lines indicate where the
|
|
24
|
+
* bare-RN package import goes. Replace the throws with the real package binding.
|
|
25
|
+
*
|
|
26
|
+
* Why stubbed: bare-RN packages have install-time native code that can't be
|
|
27
|
+
* imported at SDK build time. Consumer's bundler links them at app build.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
interface CreateBareRnAdapterOptions {
|
|
31
|
+
/** Required injection — `react-native-quick-crypto` named exports. */
|
|
32
|
+
quickCrypto: {
|
|
33
|
+
randomBytes(length: number): Uint8Array;
|
|
34
|
+
createHash(alg: 'sha256'): {
|
|
35
|
+
update(b: Uint8Array): {
|
|
36
|
+
digest(): Uint8Array;
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
/** Required injection — `react-native-keychain` namespace. */
|
|
41
|
+
keychain: {
|
|
42
|
+
setGenericPassword(username: string, password: string, options: {
|
|
43
|
+
service: string;
|
|
44
|
+
accessible?: string;
|
|
45
|
+
}): Promise<unknown>;
|
|
46
|
+
getGenericPassword(options: {
|
|
47
|
+
service: string;
|
|
48
|
+
authenticationPrompt?: {
|
|
49
|
+
title: string;
|
|
50
|
+
};
|
|
51
|
+
}): Promise<{
|
|
52
|
+
username: string;
|
|
53
|
+
password: string;
|
|
54
|
+
} | false>;
|
|
55
|
+
resetGenericPassword(options: {
|
|
56
|
+
service: string;
|
|
57
|
+
}): Promise<boolean>;
|
|
58
|
+
};
|
|
59
|
+
/** Required injection — `react-native-inappbrowser-reborn` namespace. */
|
|
60
|
+
inAppBrowser: {
|
|
61
|
+
isAvailable(): Promise<boolean>;
|
|
62
|
+
openAuth(url: string, redirectUri: string, options?: {
|
|
63
|
+
ephemeralWebSession?: boolean;
|
|
64
|
+
}): Promise<{
|
|
65
|
+
type: 'success' | 'cancel' | 'dismiss';
|
|
66
|
+
url?: string;
|
|
67
|
+
}>;
|
|
68
|
+
};
|
|
69
|
+
/** Required injection — `react-native-biometrics` instance. */
|
|
70
|
+
biometrics: {
|
|
71
|
+
isSensorAvailable(): Promise<{
|
|
72
|
+
available: boolean;
|
|
73
|
+
biometryType?: string;
|
|
74
|
+
}>;
|
|
75
|
+
simplePrompt(options: {
|
|
76
|
+
promptMessage: string;
|
|
77
|
+
cancelButtonText?: string;
|
|
78
|
+
}): Promise<{
|
|
79
|
+
success: boolean;
|
|
80
|
+
error?: string;
|
|
81
|
+
}>;
|
|
82
|
+
};
|
|
83
|
+
/** Required injection — `react-native/Linking` namespace. */
|
|
84
|
+
linking: {
|
|
85
|
+
getInitialURL(): Promise<string | null>;
|
|
86
|
+
addEventListener(event: 'url', handler: (e: {
|
|
87
|
+
url: string;
|
|
88
|
+
}) => void): {
|
|
89
|
+
remove(): void;
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
/** Required injection — `react-native/AppState` namespace. */
|
|
93
|
+
appState: {
|
|
94
|
+
currentState: 'active' | 'background' | 'inactive' | 'unknown';
|
|
95
|
+
addEventListener(event: 'change', handler: (state: 'active' | 'background' | 'inactive' | 'unknown') => void): {
|
|
96
|
+
remove(): void;
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
/** Required injection — `@react-native-community/netinfo` namespace. */
|
|
100
|
+
netInfo: {
|
|
101
|
+
fetch(): Promise<{
|
|
102
|
+
isConnected: boolean | null;
|
|
103
|
+
}>;
|
|
104
|
+
addEventListener(handler: (state: {
|
|
105
|
+
isConnected: boolean | null;
|
|
106
|
+
}) => void): () => void;
|
|
107
|
+
};
|
|
108
|
+
/** Tenant-scoped Keychain service prefix. Default `'rakomi'`. */
|
|
109
|
+
keychainServicePrefix?: string;
|
|
110
|
+
}
|
|
111
|
+
declare function createBareRnAdapter(options: CreateBareRnAdapterOptions): NativeAuthAdapter;
|
|
112
|
+
|
|
113
|
+
/** Which ceremony produced this envelope. The required-set differs per direction — deliberately. */
|
|
114
|
+
type CredentialEnvelopeKind = 'registration' | 'assertion';
|
|
115
|
+
/** The envelope broke the W3C contract. Terminal: the module is broken, retrying changes nothing. */
|
|
116
|
+
declare class CredentialEnvelopeError extends Error {
|
|
117
|
+
constructor(message: string);
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Validate a parsed native response against the W3C envelope for `kind`.
|
|
121
|
+
*
|
|
122
|
+
* Throws {@link CredentialEnvelopeError} naming the field and the violated rule — never the field's
|
|
123
|
+
* VALUE. A `PasskeyError` message reaches logs and crash reporters; a credential id and a
|
|
124
|
+
* `clientDataJSON` are durable user identifiers, so the diagnosis must be free of them.
|
|
125
|
+
*/
|
|
126
|
+
declare function assertW3cCredentialEnvelope(kind: CredentialEnvelopeKind, parsed: unknown): void;
|
|
127
|
+
/**
|
|
128
|
+
* Validate, then **re-project** the envelope onto the members the contract knows.
|
|
129
|
+
*
|
|
130
|
+
* Validating without projecting is a check, not a boundary. The bridge used to forward the whole parsed
|
|
131
|
+
* object, and the server accepts the credential as an opaque blob — so every extra member a buggy or
|
|
132
|
+
* hostile module invented rode straight through to persistence. A `transports` that is a *string*
|
|
133
|
+
* instead of an array, or a five-thousand-element array, lands in the database and then poisons every
|
|
134
|
+
* subsequent `allowCredentials` for that user. Dropping unknown members costs nothing (the server reads
|
|
135
|
+
* none of them) and closes the class outright, instead of blacklisting the shapes we happened to think
|
|
136
|
+
* of.
|
|
137
|
+
*
|
|
138
|
+
* `Object.create(null)` for the projection, so a `"__proto__"` key that survived `JSON.parse` as an own
|
|
139
|
+
* property cannot be carried into an object with a real prototype further down.
|
|
140
|
+
*/
|
|
141
|
+
declare function sanitizeCredentialEnvelope(kind: CredentialEnvelopeKind, parsed: unknown): Record<string, unknown>;
|
|
142
|
+
|
|
143
|
+
export { type CreateBareRnAdapterOptions, CredentialEnvelopeError, type CredentialEnvelopeKind, NativeAuthAdapter, assertW3cCredentialEnvelope, createBareRnAdapter, sanitizeCredentialEnvelope };
|