react-native-dpop 0.3.0 → 1.0.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/README.md +143 -53
- package/ReactNativeDPoP.podspec +1 -1
- package/android/src/main/java/com/reactnativedpop/DPoPKeyStore.kt +23 -2
- package/android/src/main/java/com/reactnativedpop/DPoPModule.kt +79 -33
- package/android/src/main/java/com/reactnativedpop/DPoPPackage.kt +7 -7
- package/android/src/main/java/com/reactnativedpop/DPoPUtils.kt +6 -6
- package/ios/DPoPKeyStore.swift +11 -2
- package/ios/DPoPModule.swift +96 -31
- package/ios/DPoPModuleBridge.mm +7 -6
- package/ios/DPoPUtils.swift +5 -5
- package/lib/module/NativeReactNativeDPoP.js +4 -2
- package/lib/module/NativeReactNativeDPoP.js.map +1 -1
- package/lib/module/index.js +33 -22
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/examples/shared/DPoPExampleContent.d.ts +2 -0
- package/lib/typescript/examples/shared/DPoPExampleContent.d.ts.map +1 -0
- package/lib/typescript/examples/v0.75/App.d.ts +2 -0
- package/lib/typescript/examples/v0.75/App.d.ts.map +1 -0
- package/lib/typescript/examples/v0.83/App.d.ts +2 -0
- package/lib/typescript/examples/v0.83/App.d.ts.map +1 -0
- package/lib/typescript/src/NativeReactNativeDPoP.d.ts +3 -3
- package/lib/typescript/src/NativeReactNativeDPoP.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +34 -24
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/package.json +8 -4
- package/src/NativeReactNativeDPoP.ts +15 -13
- package/src/index.tsx +66 -45
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-dpop",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "React Native library for DPoP proof generation and key management.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"android",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"license": "MIT",
|
|
19
19
|
"author": "Pedro Cirilo <phscirilo123@gmail.com> (https://github.com/Cirilord)",
|
|
20
20
|
"main": "./lib/module/index.js",
|
|
21
|
+
"react-native": "./src/index.tsx",
|
|
21
22
|
"types": "./lib/typescript/src/index.d.ts",
|
|
22
23
|
"exports": {
|
|
23
24
|
".": {
|
|
@@ -47,8 +48,8 @@
|
|
|
47
48
|
"!**/.*"
|
|
48
49
|
],
|
|
49
50
|
"scripts": {
|
|
50
|
-
"clean": "del-cli android/build
|
|
51
|
-
"example": "yarn workspace react-native-dpop-example",
|
|
51
|
+
"clean": "del-cli android/build examples/v0.83/android/build examples/v0.83/android/app/build examples/v0.83/ios/build lib",
|
|
52
|
+
"example": "yarn workspace react-native-dpop-example-v0.83",
|
|
52
53
|
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
53
54
|
"prepare": "bob build",
|
|
54
55
|
"release": "release-it",
|
|
@@ -71,12 +72,14 @@
|
|
|
71
72
|
"@react-native/babel-preset": "0.83.0",
|
|
72
73
|
"@react-native/eslint-config": "0.83.0",
|
|
73
74
|
"@release-it/conventional-changelog": "^10.0.1",
|
|
75
|
+
"@tsconfig/strictest": "^2.0.8",
|
|
74
76
|
"@types/jest": "^29.5.14",
|
|
75
77
|
"@types/react": "^19.2.0",
|
|
76
78
|
"commitlint": "^19.8.1",
|
|
77
79
|
"del-cli": "^6.0.0",
|
|
78
80
|
"eslint": "^9.35.0",
|
|
79
81
|
"eslint-config-prettier": "^10.1.8",
|
|
82
|
+
"eslint-plugin-import": "^2.32.0",
|
|
80
83
|
"eslint-plugin-prettier": "^5.5.4",
|
|
81
84
|
"jest": "^29.7.0",
|
|
82
85
|
"lefthook": "^2.0.3",
|
|
@@ -89,7 +92,8 @@
|
|
|
89
92
|
"typescript": "^5.9.2"
|
|
90
93
|
},
|
|
91
94
|
"workspaces": [
|
|
92
|
-
"
|
|
95
|
+
"examples/v0.75",
|
|
96
|
+
"examples/v0.83"
|
|
93
97
|
],
|
|
94
98
|
"packageManager": "yarn@4.11.0",
|
|
95
99
|
"react-native-builder-bob": {
|
|
@@ -4,16 +4,7 @@ import type { UnsafeObject } from 'react-native/Libraries/Types/CodegenTypes';
|
|
|
4
4
|
|
|
5
5
|
export interface Spec extends TurboModule {
|
|
6
6
|
assertHardwareBacked(alias: string | null): Promise<void>;
|
|
7
|
-
calculateThumbprint(alias: string | null): Promise<string>;
|
|
8
7
|
deleteKeyPair(alias: string | null): Promise<void>;
|
|
9
|
-
getKeyInfo(alias: string | null): Promise<UnsafeObject>;
|
|
10
|
-
getPublicKeyDer(alias: string | null): Promise<string>;
|
|
11
|
-
getPublicKeyJwk(alias: string | null): Promise<UnsafeObject>;
|
|
12
|
-
getPublicKeyRaw(alias: string | null): Promise<string>;
|
|
13
|
-
hasKeyPair(alias: string | null): Promise<boolean>;
|
|
14
|
-
isBoundToAlias(proof: string, alias: string | null): Promise<boolean>;
|
|
15
|
-
rotateKeyPair(alias: string | null): Promise<void>;
|
|
16
|
-
signWithDpopPrivateKey(payload: string, alias: string | null): Promise<string>;
|
|
17
8
|
generateProof(
|
|
18
9
|
htu: string,
|
|
19
10
|
htm: string,
|
|
@@ -23,11 +14,22 @@ export interface Spec extends TurboModule {
|
|
|
23
14
|
kid: string | null,
|
|
24
15
|
jti: string | null,
|
|
25
16
|
iat: number | null,
|
|
26
|
-
alias: string | null
|
|
17
|
+
alias: string | null,
|
|
18
|
+
requireHardwareBacked: boolean
|
|
27
19
|
): Promise<UnsafeObject>;
|
|
20
|
+
getKeyInfo(alias: string | null): Promise<UnsafeObject>;
|
|
21
|
+
getPublicKeyDer(alias: string | null): Promise<string>;
|
|
22
|
+
getPublicKeyJwk(alias: string | null): Promise<UnsafeObject>;
|
|
23
|
+
getPublicKeyRaw(alias: string | null): Promise<string>;
|
|
24
|
+
getPublicKeyThumbprint(alias: string | null): Promise<string>;
|
|
25
|
+
hasKeyPair(alias: string | null): Promise<boolean>;
|
|
26
|
+
isBoundToAlias(proof: string, alias: string | null): Promise<boolean>;
|
|
27
|
+
rotateKeyPair(alias: string | null): Promise<void>;
|
|
28
|
+
signWithDPoPPrivateKey(payload: string, alias: string | null): Promise<string>;
|
|
28
29
|
}
|
|
29
30
|
|
|
30
|
-
const
|
|
31
|
-
|
|
31
|
+
const nativeDPoPModule =
|
|
32
|
+
// eslint-disable-next-line dot-notation -- required by noPropertyAccessFromIndexSignature from @tsconfig/strictest
|
|
33
|
+
TurboModuleRegistry.get<Spec>('ReactNativeDPoP') ?? (NativeModules['ReactNativeDPoP'] as Spec | undefined);
|
|
32
34
|
|
|
33
|
-
export default
|
|
35
|
+
export default nativeDPoPModule as Spec;
|
package/src/index.tsx
CHANGED
|
@@ -3,8 +3,8 @@ import NativeReactNativeDPoP from './NativeReactNativeDPoP';
|
|
|
3
3
|
type AdditionalClaims = Record<string, unknown>;
|
|
4
4
|
|
|
5
5
|
export type PublicJwk = {
|
|
6
|
-
kty: 'EC';
|
|
7
6
|
crv: 'P-256';
|
|
7
|
+
kty: 'EC';
|
|
8
8
|
x: string;
|
|
9
9
|
y: string;
|
|
10
10
|
};
|
|
@@ -12,50 +12,60 @@ export type PublicJwk = {
|
|
|
12
12
|
export type PublicKeyFormat = 'JWK' | 'DER' | 'RAW';
|
|
13
13
|
|
|
14
14
|
export type SecureHardwareFallbackReason = 'UNAVAILABLE' | 'PROVIDER_ERROR' | 'POLICY_REJECTED' | 'UNKNOWN';
|
|
15
|
+
export type AndroidSecurityLevelName = 'SOFTWARE' | 'TRUSTED_ENVIRONMENT' | 'STRONGBOX';
|
|
16
|
+
export type IOSSecurityLevelName = 'SOFTWARE' | 'SECURE_ENCLAVE';
|
|
15
17
|
|
|
16
18
|
export type DPoPKeyInfo = {
|
|
17
|
-
alias: string;
|
|
18
|
-
hasKeyPair: boolean;
|
|
19
19
|
algorithm?: string;
|
|
20
|
+
alias: string;
|
|
20
21
|
curve?: string;
|
|
21
|
-
insideSecureHardware?: boolean;
|
|
22
22
|
hardware?: {
|
|
23
23
|
android?: {
|
|
24
|
+
securityLevel?: number;
|
|
25
|
+
securityLevelName?: AndroidSecurityLevelName;
|
|
24
26
|
strongBoxAvailable: boolean;
|
|
25
27
|
strongBoxBacked: boolean;
|
|
26
|
-
securityLevel?: number;
|
|
27
28
|
strongBoxFallbackReason?: SecureHardwareFallbackReason | null;
|
|
28
29
|
};
|
|
29
30
|
ios?: {
|
|
30
31
|
secureEnclaveAvailable: boolean;
|
|
31
32
|
secureEnclaveBacked: boolean;
|
|
32
|
-
securityLevel?: number | null;
|
|
33
33
|
secureEnclaveFallbackReason?: SecureHardwareFallbackReason | null;
|
|
34
|
+
securityLevel?: number | null;
|
|
35
|
+
securityLevelName?: IOSSecurityLevelName;
|
|
34
36
|
};
|
|
35
37
|
};
|
|
38
|
+
hasKeyPair: boolean;
|
|
39
|
+
insideSecureHardware?: boolean;
|
|
36
40
|
};
|
|
37
41
|
|
|
38
42
|
export type GenerateProofInput = {
|
|
39
|
-
htu: string;
|
|
40
|
-
htm: string;
|
|
41
|
-
nonce?: string;
|
|
42
43
|
accessToken?: string;
|
|
43
44
|
additional?: AdditionalClaims;
|
|
44
|
-
kid?: string;
|
|
45
|
-
jti?: string;
|
|
46
|
-
iat?: number;
|
|
47
45
|
alias?: string;
|
|
46
|
+
htm: string;
|
|
47
|
+
htu: string;
|
|
48
|
+
iat?: number;
|
|
49
|
+
jti?: string;
|
|
50
|
+
kid?: string;
|
|
51
|
+
nonce?: string;
|
|
52
|
+
requireHardwareBacked?: boolean;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export type DPoPHeaders = {
|
|
56
|
+
Authorization?: string;
|
|
57
|
+
DPoP: string;
|
|
48
58
|
};
|
|
49
59
|
|
|
50
60
|
export type DPoPProofContext = {
|
|
51
|
-
htu: string;
|
|
52
|
-
htm: string;
|
|
53
|
-
nonce: string | null;
|
|
54
|
-
ath: string | null;
|
|
55
61
|
additional: AdditionalClaims | null;
|
|
56
|
-
|
|
57
|
-
|
|
62
|
+
ath: string | null;
|
|
63
|
+
htm: string;
|
|
64
|
+
htu: string;
|
|
58
65
|
iat: number;
|
|
66
|
+
jti: string;
|
|
67
|
+
kid: string | null;
|
|
68
|
+
nonce: string | null;
|
|
59
69
|
};
|
|
60
70
|
|
|
61
71
|
type GenerateProofResult = {
|
|
@@ -64,8 +74,8 @@ type GenerateProofResult = {
|
|
|
64
74
|
};
|
|
65
75
|
|
|
66
76
|
export class DPoP {
|
|
77
|
+
public readonly alias: string | undefined;
|
|
67
78
|
public readonly proof: string;
|
|
68
|
-
public readonly alias?: string;
|
|
69
79
|
public readonly proofContext: DPoPProofContext;
|
|
70
80
|
|
|
71
81
|
private constructor(proof: string, proofContext: DPoPProofContext, alias?: string) {
|
|
@@ -74,27 +84,21 @@ export class DPoP {
|
|
|
74
84
|
this.alias = alias;
|
|
75
85
|
}
|
|
76
86
|
|
|
77
|
-
public async
|
|
78
|
-
|
|
87
|
+
public static async assertHardwareBacked(alias?: string): Promise<void> {
|
|
88
|
+
await NativeReactNativeDPoP.assertHardwareBacked(alias ?? null);
|
|
79
89
|
}
|
|
80
90
|
|
|
81
|
-
public async
|
|
82
|
-
|
|
83
|
-
return NativeReactNativeDPoP.getPublicKeyDer(this.alias ?? null);
|
|
84
|
-
}
|
|
85
|
-
if (format === 'RAW') {
|
|
86
|
-
return NativeReactNativeDPoP.getPublicKeyRaw(this.alias ?? null);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return NativeReactNativeDPoP.getPublicKeyJwk(this.alias ?? null) as Promise<PublicJwk>;
|
|
90
|
-
}
|
|
91
|
+
public static async buildDPoPHeaders(input: GenerateProofInput): Promise<DPoPHeaders> {
|
|
92
|
+
const dPoP = await DPoP.generateProof(input);
|
|
91
93
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
return {
|
|
95
|
+
DPoP: dPoP.proof,
|
|
96
|
+
...(input.accessToken ? { Authorization: `DPoP ${input.accessToken}` } : {}),
|
|
97
|
+
};
|
|
94
98
|
}
|
|
95
99
|
|
|
96
|
-
public async
|
|
97
|
-
|
|
100
|
+
public static async deleteKeyPair(alias?: string): Promise<void> {
|
|
101
|
+
await NativeReactNativeDPoP.deleteKeyPair(alias ?? null);
|
|
98
102
|
}
|
|
99
103
|
|
|
100
104
|
public static async generateProof(input: GenerateProofInput): Promise<DPoP> {
|
|
@@ -106,21 +110,15 @@ export class DPoP {
|
|
|
106
110
|
input.additional ?? null,
|
|
107
111
|
input.kid ?? null,
|
|
108
112
|
input.jti ?? null,
|
|
109
|
-
|
|
110
|
-
input.
|
|
113
|
+
// RN 0.75 Android bridge can crash when a nullable Double arrives as null.
|
|
114
|
+
input.iat ?? Math.floor(Date.now() / 1000),
|
|
115
|
+
input.alias ?? null,
|
|
116
|
+
input.requireHardwareBacked ?? false
|
|
111
117
|
)) as GenerateProofResult;
|
|
112
118
|
|
|
113
119
|
return new DPoP(result.proof, result.proofContext, input.alias);
|
|
114
120
|
}
|
|
115
121
|
|
|
116
|
-
public static async assertHardwareBacked(alias?: string): Promise<void> {
|
|
117
|
-
await NativeReactNativeDPoP.assertHardwareBacked(alias ?? null);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
public static async deleteKeyPair(alias?: string): Promise<void> {
|
|
121
|
-
await NativeReactNativeDPoP.deleteKeyPair(alias ?? null);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
122
|
public static async getKeyInfo(alias?: string): Promise<DPoPKeyInfo> {
|
|
125
123
|
return NativeReactNativeDPoP.getKeyInfo(alias ?? null) as Promise<DPoPKeyInfo>;
|
|
126
124
|
}
|
|
@@ -132,4 +130,27 @@ export class DPoP {
|
|
|
132
130
|
public static async rotateKeyPair(alias?: string): Promise<void> {
|
|
133
131
|
await NativeReactNativeDPoP.rotateKeyPair(alias ?? null);
|
|
134
132
|
}
|
|
133
|
+
|
|
134
|
+
public async getPublicKey(format: PublicKeyFormat): Promise<PublicJwk | string> {
|
|
135
|
+
if (format === 'DER') {
|
|
136
|
+
return NativeReactNativeDPoP.getPublicKeyDer(this.alias ?? null);
|
|
137
|
+
}
|
|
138
|
+
if (format === 'RAW') {
|
|
139
|
+
return NativeReactNativeDPoP.getPublicKeyRaw(this.alias ?? null);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return NativeReactNativeDPoP.getPublicKeyJwk(this.alias ?? null) as Promise<PublicJwk>;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
public async getPublicKeyThumbprint(): Promise<string> {
|
|
146
|
+
return NativeReactNativeDPoP.getPublicKeyThumbprint(this.alias ?? null);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
public async isBoundToAlias(alias?: string): Promise<boolean> {
|
|
150
|
+
return NativeReactNativeDPoP.isBoundToAlias(this.proof, alias ?? this.alias ?? null);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
public async signWithDPoPPrivateKey(payload: string): Promise<string> {
|
|
154
|
+
return NativeReactNativeDPoP.signWithDPoPPrivateKey(payload, this.alias ?? null);
|
|
155
|
+
}
|
|
135
156
|
}
|