@hawcx/react-native-sdk 1.0.8 → 1.1.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.
Files changed (134) hide show
  1. package/CHANGELOG.md +3 -0
  2. package/HawcxReactNative.podspec +2 -2
  3. package/README.md +327 -109
  4. package/android/build.gradle +2 -2
  5. package/android/src/main/java/com/hawcx/reactnative/HawcxEventDispatcher.kt +4 -0
  6. package/android/src/main/java/com/hawcx/reactnative/HawcxReactNativeModule.kt +324 -1
  7. package/android/src/main/java/com/hawcx/reactnative/v6/HawcxV6Bridge.kt +402 -0
  8. package/ios/Frameworks/HawcxFramework.xcframework/Info.plist +5 -5
  9. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/HawcxFramework +0 -0
  10. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Info.plist +0 -0
  11. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.abi.json +22145 -2
  12. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.private.swiftinterface +628 -0
  13. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  14. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios.swiftinterface +628 -0
  15. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/HawcxFramework +0 -0
  16. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Info.plist +0 -0
  17. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.abi.json +22145 -2
  18. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +628 -0
  19. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  20. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/arm64-apple-ios-simulator.swiftinterface +628 -0
  21. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.abi.json +22145 -2
  22. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +628 -0
  23. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  24. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/Modules/HawcxFramework.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +628 -0
  25. package/ios/Frameworks/HawcxFramework.xcframework/ios-arm64_x86_64-simulator/HawcxFramework.framework/_CodeSignature/CodeResources +21 -21
  26. package/ios/HawcxReactNative.m +56 -0
  27. package/ios/HawcxReactNative.swift +380 -1
  28. package/ios/HawcxV6BridgeSupport.swift +468 -0
  29. package/lib/commonjs/index.js +326 -3
  30. package/lib/commonjs/index.js.map +1 -1
  31. package/lib/commonjs/v6Normalization.js +325 -0
  32. package/lib/commonjs/v6Normalization.js.map +1 -0
  33. package/lib/commonjs/v6State.js +186 -0
  34. package/lib/commonjs/v6State.js.map +1 -0
  35. package/lib/commonjs/v6Types.js +2 -0
  36. package/lib/commonjs/v6Types.js.map +1 -0
  37. package/lib/commonjs/v6WebLogin.js +101 -0
  38. package/lib/commonjs/v6WebLogin.js.map +1 -0
  39. package/lib/module/index.js +287 -1
  40. package/lib/module/index.js.map +1 -1
  41. package/lib/module/v6Normalization.js +318 -0
  42. package/lib/module/v6Normalization.js.map +1 -0
  43. package/lib/module/v6State.js +173 -0
  44. package/lib/module/v6State.js.map +1 -0
  45. package/lib/module/v6Types.js +2 -0
  46. package/lib/module/v6Types.js.map +1 -0
  47. package/lib/module/v6WebLogin.js +92 -0
  48. package/lib/module/v6WebLogin.js.map +1 -0
  49. package/lib/typescript/index.d.ts +83 -0
  50. package/lib/typescript/index.d.ts.map +1 -1
  51. package/lib/typescript/v6Normalization.d.ts +3 -0
  52. package/lib/typescript/v6Normalization.d.ts.map +1 -0
  53. package/lib/typescript/v6State.d.ts +13 -0
  54. package/lib/typescript/v6State.d.ts.map +1 -0
  55. package/lib/typescript/v6Types.d.ts +157 -0
  56. package/lib/typescript/v6Types.d.ts.map +1 -0
  57. package/lib/typescript/v6WebLogin.d.ts +32 -0
  58. package/lib/typescript/v6WebLogin.d.ts.map +1 -0
  59. package/package.json +21 -9
  60. package/src/index.ts +477 -0
  61. package/src/v6Normalization.ts +356 -0
  62. package/src/v6State.ts +238 -0
  63. package/src/v6Types.ts +194 -0
  64. package/src/v6WebLogin.ts +154 -0
  65. package/android/.settings/org.eclipse.buildship.core.prefs +0 -2
  66. package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  67. package/android/gradle/wrapper/gradle-wrapper.properties +0 -6
  68. package/android/gradlew +0 -185
  69. package/android/gradlew.bat +0 -89
  70. package/android/libs/hawcx-5.1.4.aar +0 -0
  71. package/docs/RELEASE.md +0 -129
  72. package/example/README.md +0 -59
  73. package/example/android/app/build.gradle +0 -126
  74. package/example/android/app/debug.keystore +0 -0
  75. package/example/android/app/proguard-rules.pro +0 -10
  76. package/example/android/app/src/debug/AndroidManifest.xml +0 -9
  77. package/example/android/app/src/main/AndroidManifest.xml +0 -27
  78. package/example/android/app/src/main/java/com/hawcx/example/MainActivity.kt +0 -22
  79. package/example/android/app/src/main/java/com/hawcx/example/MainApplication.kt +0 -45
  80. package/example/android/app/src/main/res/drawable/rn_edit_text_material.xml +0 -36
  81. package/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  82. package/example/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  83. package/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  84. package/example/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  85. package/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  86. package/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  87. package/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  88. package/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  89. package/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  90. package/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  91. package/example/android/app/src/main/res/values/strings.xml +0 -3
  92. package/example/android/app/src/main/res/values/styles.xml +0 -9
  93. package/example/android/build.gradle +0 -35
  94. package/example/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  95. package/example/android/gradle/wrapper/gradle-wrapper.properties +0 -7
  96. package/example/android/gradle.properties +0 -41
  97. package/example/android/gradlew +0 -249
  98. package/example/android/gradlew.bat +0 -92
  99. package/example/android/local.properties +0 -2
  100. package/example/android/settings.gradle +0 -38
  101. package/example/app.json +0 -4
  102. package/example/babel.config.js +0 -3
  103. package/example/e2e/README.md +0 -17
  104. package/example/e2e/hawcx-login.yaml +0 -14
  105. package/example/index.js +0 -5
  106. package/example/ios/.xcode.env +0 -11
  107. package/example/ios/HawcxExampleApp/AppDelegate.h +0 -6
  108. package/example/ios/HawcxExampleApp/AppDelegate.mm +0 -31
  109. package/example/ios/HawcxExampleApp/Images.xcassets/AppIcon.appiconset/Contents.json +0 -53
  110. package/example/ios/HawcxExampleApp/Images.xcassets/Contents.json +0 -6
  111. package/example/ios/HawcxExampleApp/Info.plist +0 -55
  112. package/example/ios/HawcxExampleApp/LaunchScreen.storyboard +0 -47
  113. package/example/ios/HawcxExampleApp/PrivacyInfo.xcprivacy +0 -37
  114. package/example/ios/HawcxExampleApp/main.m +0 -10
  115. package/example/ios/HawcxExampleApp.xcodeproj/project.pbxproj +0 -704
  116. package/example/ios/HawcxExampleApp.xcodeproj/project.xcworkspace/xcuserdata/agambhullar.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  117. package/example/ios/HawcxExampleApp.xcodeproj/xcshareddata/xcschemes/HawcxExampleApp.xcscheme +0 -90
  118. package/example/ios/HawcxExampleApp.xcodeproj/xcuserdata/agambhullar.xcuserdatad/xcschemes/xcschememanagement.plist +0 -16
  119. package/example/ios/HawcxExampleApp.xcworkspace/contents.xcworkspacedata +0 -10
  120. package/example/ios/HawcxExampleAppTests/HawcxExampleAppTests.m +0 -66
  121. package/example/ios/HawcxExampleAppTests/Info.plist +0 -24
  122. package/example/ios/Podfile +0 -79
  123. package/example/ios/Podfile.lock +0 -1290
  124. package/example/metro.config.js +0 -16
  125. package/example/package-lock.json +0 -13220
  126. package/example/package.json +0 -30
  127. package/example/src/App.tsx +0 -755
  128. package/example/src/hawcx.config.ts +0 -25
  129. package/example/tsconfig.json +0 -8
  130. package/ios/Frameworks/.keep +0 -0
  131. package/lib/typescript/__tests__/index.test.d.ts +0 -2
  132. package/lib/typescript/__tests__/index.test.d.ts.map +0 -1
  133. package/react_mobile_sdk_plan.md +0 -242
  134. package/src/__tests__/index.test.ts +0 -206
package/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.1.0] - YYYY-MM-DD
4
+ - TODO: add release notes
5
+
3
6
  ## [1.0.8] - 2026-01-21
4
7
  - Android biometrics restriction issue fixed
5
8
 
@@ -4,10 +4,10 @@ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
4
  Pod::Spec.new do |s|
5
5
  s.name = 'HawcxReactNative'
6
6
  s.version = package['version']
7
- s.summary = 'React Native bindings for the Hawcx V5 mobile authentication framework.'
7
+ s.summary = 'React Native bindings for the Hawcx mobile authentication SDKs (V5 + V6).'
8
8
  s.description = <<-DESC
9
9
  Production-grade React Native bridge that wraps HawcxFramework (iOS) to expose
10
- V5 authentication, OTP, push, and web session flows to JavaScript callers.
10
+ Hawcx V5 and V6 authentication, device trust, push, and web session flows to JavaScript callers.
11
11
  DESC
12
12
  s.homepage = 'https://github.com/hawcx/reactnative_sdk'
13
13
  s.license = { :type => 'MIT', :file => 'LICENSE' }
package/README.md CHANGED
@@ -1,176 +1,394 @@
1
1
  # Hawcx React Native SDK
2
2
 
3
- Official React Native bindings for the Hawcx V5 mobile authentication platform. The package wraps the production Hawcx iOS and Android SDKs so you can deliver Smart‑Connect (OTP + device trust + push approvals) inside a single cross‑platform API.
3
+ Official React Native bindings for the Hawcx mobile authentication platform. The package
4
+ wraps the production Hawcx iOS and Android SDKs so you can ship the current V6 adaptive
5
+ flow in a single cross-platform API while keeping existing V5 utilities available during
6
+ migration.
7
+
8
+ ## What This Package Includes
9
+
10
+ - V6 adaptive authentication via `useHawcxV6Auth`, `startV6Flow`, and `hawcxV6Client`
11
+ - Production native iOS and Android SDK integrations under the hood
12
+ - Redirect, approval polling, and QR approval helpers for V6 flows
13
+ - Existing V5 auth and push/session helpers for apps already in production
4
14
 
5
15
  ## Requirements
6
16
 
7
- * React Native 0.73 (Hermes enabled by default)
8
- * iOS 17+ / Android 8+ (SDK requires API level 26 for Android)
9
- * OAuth client credentials **must stay on your backend**.
17
+ - React Native 0.73+
18
+ - iOS 17.5+
19
+ - Android API 26+
20
+ - OAuth client credentials kept on your backend
10
21
 
11
22
  ## Installation
12
23
 
24
+ Add the package:
25
+
13
26
  ```bash
14
- npm install @hawcx/react-native-sdk@1.0.8
15
- # or yarn add @hawcx/react-native-sdk
27
+ npm install @hawcx/react-native-sdk
16
28
  ```
17
29
 
30
+ Pin to the released version your team has approved for production.
31
+
18
32
  ### iOS
19
33
 
20
- ```
34
+ Install pods after adding the package:
35
+
36
+ ```bash
21
37
  cd ios
22
38
  pod install
23
39
  cd ..
24
40
  ```
25
41
 
26
- Open the workspace (`ios/*.xcworkspace`) in Xcode when you need to run on a device. The pod installs the vendored HawcxFramework.xcframework automatically.
42
+ The Podspec vendors `HawcxFramework.xcframework` automatically, so no manual iOS
43
+ framework setup is required.
27
44
 
28
45
  ### Android
29
46
 
30
- No manual steps are required—Gradle picks up the bundled `hawcx-*.aar`. Make sure the Android SDK is installed and `ANDROID_HOME`/`adb` are on your path, then run `npm run android`. If you upgrade from an older package version, run `cd android && ./gradlew clean` once before rebuilding so React Native re-links the native module.
47
+ The React Native package depends on the released Hawcx Android SDK, so your Android app
48
+ must be able to resolve the Hawcx Maven repository.
49
+
50
+ Add the repository in `android/settings.gradle`:
51
+
52
+ ```groovy
53
+ dependencyResolutionManagement {
54
+ repositories {
55
+ google()
56
+ mavenCentral()
57
+ maven {
58
+ url = uri("https://raw.githubusercontent.com/hawcx/hawcx_android_sdk/main/maven")
59
+ metadataSources {
60
+ mavenPom()
61
+ artifact()
62
+ }
63
+ }
64
+ }
65
+ }
66
+ ```
67
+
68
+ The hosted Hawcx Maven repository is public. You do not need a GitHub token for the
69
+ standard React Native setup.
31
70
 
32
- ## Quick Start
71
+ If your Android project still bundles a local `hawcx-*.aar` or uses `flatDir { dirs("libs") }`,
72
+ remove that and let Gradle resolve the native SDK from Maven.
73
+
74
+ If Gradle has cached an older dependency graph, run:
75
+
76
+ ```bash
77
+ cd android
78
+ ./gradlew clean
79
+ cd ..
80
+ ```
81
+
82
+ ## V6 Quick Start
83
+
84
+ Initialize the SDK once during app bootstrap:
33
85
 
34
86
  ```tsx
35
- import { useEffect } from 'react';
36
- import { initialize, addAuthListener } from '@hawcx/react-native-sdk';
37
-
38
- export function bootstrapHawcx() {
39
- return initialize({
40
- projectApiKey: 'YOUR_PROJECT_API_KEY',
41
- baseUrl: 'https://your-hawcx-host.example.com',
42
- }).then(() => {
43
- const subscription = addAuthListener(event => {
44
- if (event.type === 'auth_error') {
45
- console.warn('Hawcx error', event.payload);
46
- }
47
- });
48
- return () => subscription.remove();
49
- });
87
+ import { initialize } from '@hawcx/react-native-sdk';
88
+
89
+ await initialize({
90
+ projectApiKey: '<YOUR_CONFIG_ID>',
91
+ baseUrl: 'https://stage-api.hawcx.com',
92
+ autoPollApprovals: true,
93
+ });
94
+ ```
95
+
96
+ ### Initialization Notes
97
+
98
+ - `projectApiKey` is the Hawcx value provisioned for this integration. In current public
99
+ releases, this is the same value you may receive as your project API key / Config ID.
100
+ - `baseUrl` should point to your Hawcx tenant host root. Do not append `/v1`, `/auth`,
101
+ or `/hc_auth` yourself.
102
+ - `autoPollApprovals` defaults to `true`, which is the right choice for most apps.
103
+ - `relyingParty` is optional. Set it only when your backend expects the
104
+ `X-Relying-Party` header for this integration.
105
+ - `oauthConfig` is not required for the recommended V6 flow. Keep OAuth credentials on
106
+ your backend.
107
+
108
+ ## How V6 Works
109
+
110
+ 1. Initialize the package with your Config ID and tenant host.
111
+ 2. Start a flow, usually `signin`, with the user's identifier.
112
+ 3. Render the next prompt Hawcx returns.
113
+ 4. Send the user's input back to the SDK.
114
+ 5. When the flow completes, send the authorization code to your backend.
115
+ 6. Let your backend exchange the code and create the app session.
116
+
117
+ The native SDKs handle protocol requests, PKCE when needed, trusted-device storage,
118
+ device-trust processing, and approval polling.
119
+
120
+ ## Build an Auth Screen
121
+
122
+ The recommended React Native integration shape is a screen or coordinator that:
123
+
124
+ 1. holds the current `HawcxV6AuthState`
125
+ 2. starts the flow
126
+ 3. reacts to the current prompt
127
+ 4. forwards the user's input back to the SDK
128
+
129
+ ```tsx
130
+ import { useState } from 'react';
131
+ import { Button, Text, TextInput, View } from 'react-native';
132
+ import {
133
+ useHawcxV6Auth,
134
+ type HawcxV6Method,
135
+ } from '@hawcx/react-native-sdk';
136
+
137
+ export function V6AuthScreen() {
138
+ const [identifier, setIdentifier] = useState('');
139
+ const [code, setCode] = useState('');
140
+ const [totp, setTotp] = useState('');
141
+ const v6 = useHawcxV6Auth(undefined, { flowType: 'signin' });
142
+
143
+ const renderPrompt = () => {
144
+ switch (v6.state.status) {
145
+ case 'select_method':
146
+ return v6.state.prompt?.prompt.type === 'select_method'
147
+ ? v6.state.prompt.prompt.methods.map((method: HawcxV6Method) => (
148
+ <Button
149
+ key={method.id}
150
+ title={method.label}
151
+ onPress={() => void v6.selectMethod(method.id)}
152
+ />
153
+ ))
154
+ : null;
155
+
156
+ case 'enter_code':
157
+ return (
158
+ <>
159
+ <TextInput value={code} onChangeText={setCode} keyboardType="number-pad" />
160
+ <Button title="Continue" onPress={() => void v6.submitCode(code)} />
161
+ </>
162
+ );
163
+
164
+ case 'enter_totp':
165
+ return (
166
+ <>
167
+ <TextInput value={totp} onChangeText={setTotp} />
168
+ <Button title="Continue" onPress={() => void v6.submitTotp(totp)} />
169
+ </>
170
+ );
171
+
172
+ case 'await_approval':
173
+ return <Text>Waiting for approval...</Text>;
174
+
175
+ case 'redirect':
176
+ return <Text>Continue in the browser to finish this step.</Text>;
177
+
178
+ default:
179
+ return null;
180
+ }
181
+ };
182
+
183
+ return (
184
+ <View>
185
+ <TextInput value={identifier} onChangeText={setIdentifier} />
186
+ <Button
187
+ title="Continue"
188
+ onPress={() =>
189
+ void v6.start({
190
+ flowType: 'signin',
191
+ identifier: identifier.trim(),
192
+ })
193
+ }
194
+ />
195
+ {renderPrompt()}
196
+ </View>
197
+ );
50
198
  }
51
199
  ```
52
200
 
53
- Call `bootstrapHawcx()` once when your app starts (e.g., inside your root component or Redux saga). After that you can use hooks or imperative helpers to drive Smart‑Connect.
201
+ ### V6 Flow Types
202
+
203
+ `flowType` supports:
204
+
205
+ - `signin`
206
+ - `signup`
207
+ - `account_manage`
54
208
 
55
- > **Note:** `baseUrl` must be the tenant-specific Hawcx host (e.g., `https://hawcx-api.hawcx.com`). The native SDK appends `/hc_auth` internally and routes all APIs through that cluster.
209
+ Most apps should start with `signin`.
56
210
 
57
- ### Authentication flow (OTP + authorization code)
211
+ ## Redirect Handling
58
212
 
59
- The SDK now always returns an authorization code. Your frontend must forward it to your backend, which redeems it with Hawcx using the OAuth client credentials we issued for your project.
213
+ When the current prompt is `redirect`, open the provided URL in the browser and forward
214
+ the return URL back into the SDK:
60
215
 
61
216
  ```tsx
62
- import React, { useEffect, useState } from 'react';
63
- import { useHawcxAuth, storeBackendOAuthTokens } from '@hawcx/react-native-sdk';
217
+ import { useEffect } from 'react';
218
+ import { Linking } from 'react-native';
64
219
 
65
- export function SmartConnectScreen() {
66
- const { state, authenticate, submitOtp, reset } = useHawcxAuth();
67
- const [email, setEmail] = useState('');
68
- const [otp, setOtp] = useState('');
220
+ useEffect(() => {
221
+ const subscription = Linking.addEventListener('url', ({ url }) => {
222
+ void v6.handleRedirectUrl(url);
223
+ });
69
224
 
70
- useEffect(() => {
71
- if (state.status === 'authorization_code') {
72
- void exchangeCode(state.payload).finally(() => reset());
73
- }
74
- }, [state, reset]);
225
+ return () => subscription.remove();
226
+ }, [v6.handleRedirectUrl]);
227
+
228
+ const openRedirect = async () => {
229
+ if (v6.state.prompt?.prompt.type !== 'redirect') {
230
+ return;
231
+ }
232
+
233
+ await Linking.openURL(v6.state.prompt.prompt.url);
234
+ };
235
+ ```
236
+
237
+ React Native handles the JavaScript callback side, but you still need to register your
238
+ callback scheme natively on iOS and Android so the app receives the return URL.
239
+
240
+ ## Backend Exchange
241
+
242
+ When the flow completes, the SDK returns:
243
+
244
+ - `session`
245
+ - `authCode`
246
+ - `expiresAt`
247
+ - `codeVerifier` when PKCE was generated by the SDK
248
+ - `traceId` for support and correlation
249
+
250
+ For most apps, send `authCode` and `codeVerifier` to your backend immediately over HTTPS
251
+ and perform the exchange there. Keep OAuth client credentials and token verification on
252
+ the server, not in the React Native app.
253
+
254
+ Recommended payload shape:
255
+
256
+ ```json
257
+ {
258
+ "authCode": "<authCode>",
259
+ "codeVerifier": "<optional-codeVerifier>",
260
+ "identifier": "user@example.com",
261
+ "session": "<optional-session>"
262
+ }
263
+ ```
264
+
265
+ Your backend should:
266
+
267
+ 1. exchange `authCode` and `codeVerifier` with the Hawcx backend SDK
268
+ 2. verify the returned claims
269
+ 3. create your app session or tokens
270
+ 4. return the app auth result your app needs
271
+
272
+ ### React Native app-to-backend example
273
+
274
+ ```tsx
275
+ import { useEffect } from 'react';
276
+ import {
277
+ storeBackendOAuthTokens,
278
+ useHawcxV6Auth,
279
+ } from '@hawcx/react-native-sdk';
280
+
281
+ useEffect(() => {
282
+ if (v6.state.status !== 'completed' || !v6.state.completed) {
283
+ return;
284
+ }
75
285
 
76
- const exchangeCode = async ({ code, expiresIn }) => {
77
- const response = await fetch('https://your-backend.example.com/api/hawcx/login', {
286
+ const run = async () => {
287
+ const response = await fetch('https://your-backend.example.com/api/hawcx/exchange', {
78
288
  method: 'POST',
79
289
  headers: { 'Content-Type': 'application/json' },
80
- body: JSON.stringify({ email: email.trim(), code, expires_in: expiresIn }),
290
+ body: JSON.stringify({
291
+ authCode: v6.state.completed.authCode,
292
+ codeVerifier: v6.state.completed.codeVerifier,
293
+ identifier,
294
+ session: v6.state.completed.session,
295
+ }),
81
296
  });
297
+
82
298
  if (!response.ok) {
83
- throw new Error('Backend verification failed');
299
+ throw new Error('Backend exchange failed');
300
+ }
301
+
302
+ const result = await response.json();
303
+
304
+ if (result.accessToken) {
305
+ await storeBackendOAuthTokens(
306
+ identifier,
307
+ result.accessToken,
308
+ result.refreshToken,
309
+ );
84
310
  }
85
- const { access_token, refresh_token } = await response.json();
86
- await storeBackendOAuthTokens(email.trim(), access_token, refresh_token);
87
311
  };
88
312
 
89
- return (
90
- <>
91
- {/* Collect identifier */}
92
- <Button title="Continue" onPress={() => authenticate(email.trim())} />
93
-
94
- {state.status === 'otp' && (
95
- <>
96
- <TextInput value={otp} onChangeText={setOtp} keyboardType="number-pad" />
97
- <Button title="Verify OTP" onPress={() => submitOtp(otp)} />
98
- </>
99
- )}
100
-
101
- {state.status === 'authorization_code' && <Text>Sending authorization code…</Text>}
102
- {state.status === 'additional_verification_required' && (
103
- <Text>Additional verification required: {state.payload.detail ?? state.payload.sessionId}</Text>
104
- )}
105
- {state.status === 'error' && <Text>{state.error.message}</Text>}
106
- </>
107
- );
108
- }
313
+ void run();
314
+ }, [identifier, v6.state]);
109
315
  ```
110
316
 
111
- ### Backend exchange
317
+ `storeBackendOAuthTokens` is optional for the core V6 flow. Use it when your backend
318
+ returns tokens that the shared native session and push helpers should persist.
112
319
 
113
- Redeem the authorization code on your server using the hawcx/oauth-client package or your preferred language SDK. Never ship `clientId`, token endpoint, private keys, or Hawcx public keys inside your mobile app.
320
+ For backend implementation details, see:
114
321
 
115
- ```ts
116
- import express from 'express';
117
- import { exchangeCodeForTokenAndClaims } from '@hawcx/oauth-client';
322
+ - [Node.js backend quickstart](https://docs.hawcx.com/docs/v1/sdk-reference/backend/nodejs/quickstart)
323
+ - [Python backend quickstart](https://docs.hawcx.com/docs/v1/sdk-reference/backend/python/quickstart)
118
324
 
119
- const app = express();
120
- app.use(express.json());
325
+ ## QR Approvals and Web Login Helpers
121
326
 
122
- app.post('/api/hawcx/login', async (req, res) => {
123
- const { email, code, expires_in } = req.body ?? {};
124
- if (!email || !code) {
125
- return res.status(400).json({ success: false, error: 'Missing email or code' });
126
- }
327
+ The package also exposes helpers for QR approval and legacy web-login scans:
127
328
 
128
- try {
129
- const [claims, idToken] = await exchangeCodeForTokenAndClaims({
130
- code,
131
- oauthTokenUrl: process.env.HAWCX_OAUTH_TOKEN_ENDPOINT!,
132
- clientId: process.env.HAWCX_OAUTH_CLIENT_ID!,
133
- publicKey: process.env.HAWCX_OAUTH_PUBLIC_KEY_PEM!,
134
- audience: process.env.HAWCX_OAUTH_CLIENT_ID,
135
- issuer: process.env.HAWCX_OAUTH_ISSUER,
136
- });
329
+ - `routeWebLoginScan(raw)`
330
+ - `approveV6Qr(rawPayload, identifier, options)`
331
+ - `useHawcxWebLogin()`
137
332
 
138
- return res.json({
139
- success: true,
140
- message: `Verified ${claims.email}`,
141
- access_token: idToken,
142
- refresh_token: idToken,
143
- });
144
- } catch (error) {
145
- return res.status(401).json({ success: false, error: error.message });
146
- }
147
- });
333
+ For protocol QR payloads, you can approve directly from React Native:
334
+
335
+ ```tsx
336
+ import { approveV6Qr, routeWebLoginScan } from '@hawcx/react-native-sdk';
337
+
338
+ const route = routeWebLoginScan(scanValue);
339
+ if (route.kind === 'protocol_qr') {
340
+ const result = await approveV6Qr(route.payload.raw, identifier, {
341
+ rememberDevice: true,
342
+ });
343
+
344
+ console.log(result.outcome, result.payloadType);
345
+ }
148
346
  ```
149
347
 
150
- Once the backend responds, call `storeBackendOAuthTokens(userId, tokens)` so the Hawcx SDK saves them securely and can continue handling push registration and device sessions.
348
+ ## Existing V5 and Shared Helpers
349
+
350
+ The package still includes the older V5 auth surface for apps that already use it,
351
+ including:
151
352
 
152
- ## Hooks & Helpers
353
+ - `authenticate`, `submitOtp`, `useHawcxAuth`
354
+ - `useHawcxWebLogin`
355
+ - `setPushDeviceToken`
356
+ - `notifyUserAuthenticated`
357
+ - `handlePushNotification`, `approvePushRequest`, `declinePushRequest`
153
358
 
154
- * `useHawcxAuth()` React hook that exposes the current auth state and helpers (`authenticate`, `submitOtp`, `reset`).
155
- * `useHawcxWebLogin()` Drive QR/PIN based approvals.
156
- * `addAuthListener` / `addSessionListener` / `addPushListener` – Lower-level event APIs if you prefer an imperative approach.
157
- * `setPushDeviceToken` / `notifyUserAuthenticated` – Wire push login approvals.
359
+ Shared helpers such as `initialize` and `storeBackendOAuthTokens` remain available across
360
+ the current package surface.
158
361
 
159
- Refer to the updated [React Quickstart documentation](https://docs.hawcx.com/react/quickstart) for details on each API, push approvals, and device session management.
362
+ That makes incremental migration possible: new V6 flows can live on
363
+ `useHawcxV6Auth` while existing utilities remain available in the same package.
160
364
 
161
365
  ## Example App
162
366
 
163
- `/example` contains a full React Native app wired to the SDK with logging, OTP UI, push harness, and a backend toggle. To run it:
367
+ The `example/` directory contains the in-repo React Native reference app used during SDK
368
+ development:
164
369
 
165
370
  ```bash
166
371
  cd example
167
372
  npm install
168
- npm run ios # or npm run android
373
+ npm run ios
374
+ # or
375
+ npm run android
169
376
  ```
170
377
 
171
- Add your Project API key in `example/src/hawcx.config.ts` or paste it into the in-app form. The **Authorization Code & Backend Exchange** card runs in demo mode by default (codes complete locally). Set `BACKEND_FLOW_ENABLED = true` in `example/src/App.tsx` when you have a tunnel or backend ready to receive `{ code, email, expires_in }`.
378
+ Use it to validate V6 auth flows against your environment before integrating into your
379
+ own app.
380
+
381
+ ## Documentation
382
+
383
+ - [V6 React Native guide](https://docs.hawcx.com/docs/v1/sdk-reference/frontend/react-native/sdk-v6)
384
+ - [V5 React Native guide](https://docs.hawcx.com/docs/v1/sdk-reference/frontend/react-native/sdk)
385
+ - [V6 iOS guide](https://docs.hawcx.com/docs/v1/sdk-reference/frontend/ios/sdk-v6)
386
+ - [V6 Android guide](https://docs.hawcx.com/docs/v1/sdk-reference/frontend/android/sdk-v6)
387
+ - [Node.js backend quickstart](https://docs.hawcx.com/docs/v1/sdk-reference/backend/nodejs/quickstart)
388
+ - [Python backend quickstart](https://docs.hawcx.com/docs/v1/sdk-reference/backend/python/quickstart)
389
+ - [Documentation home](https://docs.hawcx.com)
172
390
 
173
391
  ## Support
174
392
 
175
- * Documentation: [React Quickstart](https://docs.hawcx.com/react/quickstart)
176
- * Questions? Reach out to your Hawcx solutions engineer or info@hawcx.com.
393
+ - [Website](https://www.hawcx.com)
394
+ - [Support Email](mailto:info@hawcx.com)
@@ -22,7 +22,7 @@ def safeExtGet(prop, fallback) {
22
22
  }
23
23
 
24
24
  group = 'com.hawcx.reactnative'
25
- version = project.findProperty('HAWCX_REACT_NATIVE_ANDROID_VERSION') ?: '1.0.8'
25
+ version = project.findProperty('HAWCX_REACT_NATIVE_ANDROID_VERSION') ?: '1.1.0'
26
26
 
27
27
  repositories {
28
28
  mavenCentral()
@@ -124,7 +124,7 @@ afterEvaluate {
124
124
  }
125
125
 
126
126
  dependencies {
127
- api("api.hawcx:hawcx:5.1.4")
127
+ api("api.hawcx:hawcx:6.0.2")
128
128
  def reactNativeVersion = safeExtGet('reactNativeAndroidVersion', '0.73.9')
129
129
  implementation "com.facebook.react:react-android:$reactNativeVersion"
130
130
  implementation 'androidx.annotation:annotation:1.8.1'
@@ -21,6 +21,10 @@ internal class HawcxEventDispatcher(
21
21
  emitEvent(PUSH_EVENT_NAME, type, payload)
22
22
  }
23
23
 
24
+ fun emitV6FlowEvent(type: String, payload: WritableMap? = null) {
25
+ emitEvent(V6_FLOW_EVENT_NAME, type, payload)
26
+ }
27
+
24
28
  private fun emitEvent(eventName: String, type: String, payload: WritableMap?) {
25
29
  val map = Arguments.createMap().apply {
26
30
  putString("type", type)