From d9f874b2b32c4b8f804553c192d8053208634394 Mon Sep 17 00:00:00 2001 From: Shachar Udi Date: Fri, 25 Apr 2025 09:32:53 -0400 Subject: [PATCH 01/25] webauthn and webauthn with auth data implemented on JS and iOS --- README.md | 26 ++ RELEASE_NOTES.md | 2 +- example/ios/Podfile | 2 +- example/ios/Podfile.lock | 126 +------ example/src/App.tsx | 42 ++- example/src/home.tsx | 65 +++- ios/TsAuthentication.mm | 2 + ios/TsAuthentication.swift | 468 +++++++++++++++---------- react-native-ts-authentication.podspec | 2 +- src/index.tsx | 53 +++ 10 files changed, 474 insertions(+), 314 deletions(-) diff --git a/README.md b/README.md index 5aaff38..a9daf4f 100644 --- a/README.md +++ b/README.md @@ -201,6 +201,32 @@ private randomString = (): string => { } ``` +### Approval with WebAuthn +```js +onApprovalWebAuthn = async (username: string, approvalData: { [key: string]: string }): Promise => { + try { + const result = await TSAuthenticationSDKModule.approvalWebAuthn(username, approvalData, []); + console.log("Approval result: ", result); + // Use the result to complete WebAuthn approval in your backend. + } catch (error: any) { + this.setState({ errorMessage: `${error}` }); + } +} +``` + +### Approval with WebAuthn with Authentication Data +```js +onApprovalWebAuthnWithData = async (rawAuthenticationData: TSWebAuthnAuthenticationData): Promise => { + try { + const result = await TSAuthenticationSDKModule.approvalWebAuthnWithData(rawAuthenticationData, []); + console.log("Approval result: ", result); + // Use the result to complete WebAuthn approval in your backend. + } catch (error: any) { + this.setState({ errorMessage: `${error}` }); + } +} +``` + ### Information about the device #### Get Device Info diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index f4c9c69..cc4efd5 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,4 +1,4 @@ -## 0.1.4 July 2024 +## 0.1.5 July 2024 ### Content #### Enhancements 1. Upgraded native SDKs to iOS `1.1.3` and Android `1.0.19`. diff --git a/example/ios/Podfile b/example/ios/Podfile index 19ca45e..d9102a1 100644 --- a/example/ios/Podfile +++ b/example/ios/Podfile @@ -40,7 +40,7 @@ target 'TsAuthenticationExample' do # # Note that if you have use_frameworks! enabled, Flipper will not work and # you should disable the next line. - :flipper_configuration => flipper_config, + # :flipper_configuration => flipper_config, # An absolute path to your application root. :app_path => "#{Pod::Config.instance.installation_root}/.." ) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 734e9d3..4cd282f 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1,6 +1,5 @@ PODS: - boost (1.76.0) - - CocoaAsyncSocket (7.6.5) - DoubleConversion (1.1.6) - FBLazyVector (0.72.7) - FBReactNativeSpec (0.72.7): @@ -10,71 +9,12 @@ PODS: - React-Core (= 0.72.7) - React-jsi (= 0.72.7) - ReactCommon/turbomodule/core (= 0.72.7) - - Flipper (0.182.0): - - Flipper-Folly (~> 2.6) - - Flipper-Boost-iOSX (1.76.0.1.11) - - Flipper-DoubleConversion (3.2.0.1) - - Flipper-Fmt (7.1.7) - - Flipper-Folly (2.6.10): - - Flipper-Boost-iOSX - - Flipper-DoubleConversion - - Flipper-Fmt (= 7.1.7) - - Flipper-Glog - - libevent (~> 2.1.12) - - OpenSSL-Universal (= 1.1.1100) - - Flipper-Glog (0.5.0.5) - - Flipper-PeerTalk (0.0.4) - - FlipperKit (0.182.0): - - FlipperKit/Core (= 0.182.0) - - FlipperKit/Core (0.182.0): - - Flipper (~> 0.182.0) - - FlipperKit/CppBridge - - FlipperKit/FBCxxFollyDynamicConvert - - FlipperKit/FBDefines - - FlipperKit/FKPortForwarding - - SocketRocket (~> 0.6.0) - - FlipperKit/CppBridge (0.182.0): - - Flipper (~> 0.182.0) - - FlipperKit/FBCxxFollyDynamicConvert (0.182.0): - - Flipper-Folly (~> 2.6) - - FlipperKit/FBDefines (0.182.0) - - FlipperKit/FKPortForwarding (0.182.0): - - CocoaAsyncSocket (~> 7.6) - - Flipper-PeerTalk (~> 0.0.4) - - FlipperKit/FlipperKitHighlightOverlay (0.182.0) - - FlipperKit/FlipperKitLayoutHelpers (0.182.0): - - FlipperKit/Core - - FlipperKit/FlipperKitHighlightOverlay - - FlipperKit/FlipperKitLayoutTextSearchable - - FlipperKit/FlipperKitLayoutIOSDescriptors (0.182.0): - - FlipperKit/Core - - FlipperKit/FlipperKitHighlightOverlay - - FlipperKit/FlipperKitLayoutHelpers - - YogaKit (~> 1.18) - - FlipperKit/FlipperKitLayoutPlugin (0.182.0): - - FlipperKit/Core - - FlipperKit/FlipperKitHighlightOverlay - - FlipperKit/FlipperKitLayoutHelpers - - FlipperKit/FlipperKitLayoutIOSDescriptors - - FlipperKit/FlipperKitLayoutTextSearchable - - YogaKit (~> 1.18) - - FlipperKit/FlipperKitLayoutTextSearchable (0.182.0) - - FlipperKit/FlipperKitNetworkPlugin (0.182.0): - - FlipperKit/Core - - FlipperKit/FlipperKitReactPlugin (0.182.0): - - FlipperKit/Core - - FlipperKit/FlipperKitUserDefaultsPlugin (0.182.0): - - FlipperKit/Core - - FlipperKit/SKIOSNetworkPlugin (0.182.0): - - FlipperKit/Core - - FlipperKit/FlipperKitNetworkPlugin - fmt (6.2.1) - glog (0.3.5) - hermes-engine (0.72.7): - hermes-engine/Pre-built (= 0.72.7) - hermes-engine/Pre-built (0.72.7) - libevent (2.1.12) - - OpenSSL-Universal (1.1.1100) - RCT-Folly (2021.07.22.00): - boost - DoubleConversion @@ -375,10 +315,10 @@ PODS: - React-jsinspector (0.72.7) - React-logger (0.72.7): - glog - - react-native-ts-authentication (0.1.3): + - react-native-ts-authentication (0.1.5): - RCT-Folly (= 2021.07.22.00) - React-Core - - TSAuthentication (~> 1.1.3) + - TSAuthentication (~> 1.1.13) - React-NativeModulesApple (0.72.7): - hermes-engine - React-callinvoker @@ -492,42 +432,19 @@ PODS: - RNCAsyncStorage (1.21.0): - React-Core - SocketRocket (0.6.1) - - TSAuthentication (1.1.3): - - TSCoreSDK (~> 1.0.24) - - TSCoreSDK (1.0.24) + - TSAuthentication (1.1.13): + - TSCoreSDK (~> 1.0.29) + - TSCoreSDK (1.0.29) - Yoga (1.14.0) - - YogaKit (1.18.1): - - Yoga (~> 1.14) DEPENDENCIES: - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`) - - Flipper (= 0.182.0) - - Flipper-Boost-iOSX (= 1.76.0.1.11) - - Flipper-DoubleConversion (= 3.2.0.1) - - Flipper-Fmt (= 7.1.7) - - Flipper-Folly (= 2.6.10) - - Flipper-Glog (= 0.5.0.5) - - Flipper-PeerTalk (= 0.0.4) - - FlipperKit (= 0.182.0) - - FlipperKit/Core (= 0.182.0) - - FlipperKit/CppBridge (= 0.182.0) - - FlipperKit/FBCxxFollyDynamicConvert (= 0.182.0) - - FlipperKit/FBDefines (= 0.182.0) - - FlipperKit/FKPortForwarding (= 0.182.0) - - FlipperKit/FlipperKitHighlightOverlay (= 0.182.0) - - FlipperKit/FlipperKitLayoutPlugin (= 0.182.0) - - FlipperKit/FlipperKitLayoutTextSearchable (= 0.182.0) - - FlipperKit/FlipperKitNetworkPlugin (= 0.182.0) - - FlipperKit/FlipperKitReactPlugin (= 0.182.0) - - FlipperKit/FlipperKitUserDefaultsPlugin (= 0.182.0) - - FlipperKit/SKIOSNetworkPlugin (= 0.182.0) - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) - libevent (~> 2.1.12) - - OpenSSL-Universal (= 1.1.1100) - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) - RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`) - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) @@ -535,7 +452,6 @@ DEPENDENCIES: - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) - React-Codegen (from `build/generated/ios`) - React-Core (from `../node_modules/react-native/`) - - React-Core/DevSupport (from `../node_modules/react-native/`) - React-Core/RCTWebSocket (from `../node_modules/react-native/`) - React-CoreModules (from `../node_modules/react-native/React/CoreModules`) - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) @@ -568,22 +484,11 @@ DEPENDENCIES: SPEC REPOS: trunk: - - CocoaAsyncSocket - - Flipper - - Flipper-Boost-iOSX - - Flipper-DoubleConversion - - Flipper-Fmt - - Flipper-Folly - - Flipper-Glog - - Flipper-PeerTalk - - FlipperKit - fmt - libevent - - OpenSSL-Universal - SocketRocket - TSAuthentication - TSCoreSDK - - YogaKit EXTERNAL SOURCES: boost: @@ -672,23 +577,13 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost: 57d2868c099736d80fcd648bf211b4431e51a558 - CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54 FBLazyVector: 5fbbff1d7734827299274638deb8ba3024f6c597 FBReactNativeSpec: 638095fe8a01506634d77b260ef8a322019ac671 - Flipper: 6edb735e6c3e332975d1b17956bcc584eccf5818 - Flipper-Boost-iOSX: fd1e2b8cbef7e662a122412d7ac5f5bea715403c - Flipper-DoubleConversion: 2dc99b02f658daf147069aad9dbd29d8feb06d30 - Flipper-Fmt: 60cbdd92fc254826e61d669a5d87ef7015396a9b - Flipper-Folly: 584845625005ff068a6ebf41f857f468decd26b3 - Flipper-Glog: 70c50ce58ddaf67dc35180db05f191692570f446 - Flipper-PeerTalk: 116d8f857dc6ef55c7a5a75ea3ceaafe878aadc9 - FlipperKit: 2efad7007d6745a3f95e4034d547be637f89d3f6 fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9 glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b hermes-engine: 9180d43df05c1ed658a87cc733dc3044cf90c00a libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 - OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 RCTRequired: 83bca1c184feb4d2e51c72c8369b83d641443f95 RCTTypeSafety: 13c4a87a16d7db6cd66006ce9759f073402ef85b @@ -704,7 +599,7 @@ SPEC CHECKSUMS: React-jsiexecutor: c49502e5d02112247ee4526bc3ccfc891ae3eb9b React-jsinspector: 8baadae51f01d867c3921213a25ab78ab4fbcd91 React-logger: 8edc785c47c8686c7962199a307015e2ce9a0e4f - react-native-ts-authentication: 4cde495084271f5ba210a3949afcc1ad871faee7 + react-native-ts-authentication: a7d5112aff31ef2c3240721772714d99bd518e8d React-NativeModulesApple: b6868ee904013a7923128892ee4a032498a1024a React-perflogger: 31ea61077185eb1428baf60c0db6e2886f141a5a React-RCTActionSheet: 392090a3abc8992eb269ef0eaa561750588fc39d @@ -724,11 +619,10 @@ SPEC CHECKSUMS: ReactCommon: 5f704096ccf7733b390f59043b6fa9cc180ee4f6 RNCAsyncStorage: 618d03a5f52fbccb3d7010076bc54712844c18ef SocketRocket: f32cd54efbe0f095c4d7594881e52619cfe80b17 - TSAuthentication: 622f45bde933e3f252ede79fa21ce371ef924081 - TSCoreSDK: b480415b11b5b202cbf43275b1ea40f68b546b6e + TSAuthentication: 71ee5ea0443f970bf5e3f57a9859c62ecc194380 + TSCoreSDK: c926ecf79c54d421153c6a2dca316fdb7e105af8 Yoga: 4c3aa327e4a6a23eeacd71f61c81df1bcdf677d5 - YogaKit: f782866e155069a2cca2517aafea43200b01fd5a -PODFILE CHECKSUM: 40c199a67ca4793b0dc29ad258c27bc4fe82df69 +PODFILE CHECKSUM: 174477b07904a4b4c349bd0f8bdf2118176f8031 -COCOAPODS: 1.14.2 +COCOAPODS: 1.15.2 diff --git a/example/src/App.tsx b/example/src/App.tsx index 6d4c61b..9f0a7b3 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -51,6 +51,8 @@ export default class App extends React.Component { ) : ( @@ -196,6 +198,44 @@ export default class App extends React.Component { } } + // Approvals WebAuthn + + public onApprovalWebAuthn = async (username: string, approvalData: { [key: string]: string; }) => { + if (username === '') { + this.setState({ errorMessage: 'Please enter a username' }); + return; + } + this.approvalWebAuthn(username, approvalData); + } + + private approvalWebAuthn = async(username: string, approvalData: { [key: string]: string; }): Promise => { + try { + const result = await TSAuthenticationSDKModule.approvalWebAuthn(username, approvalData, []); + console.log("Approval result: ", result); + } catch (error: any) { + this.setState({ errorMessage: `${error}` }); + } + } + + // Approvals WebAuthn with Authentication Data + + public onApprovalWebAuthnWithData = async (rawAuthenticationData: { [key: string]: any; }) => { + if (rawAuthenticationData === null) { + this.setState({ errorMessage: 'Please enter authentication data' }); + return; + } + this.approvalWebAuthnWithData(rawAuthenticationData); + } + + private approvalWebAuthnWithData = async (rawAuthenticationData: { [key: string]: any; }): Promise => { + try { + const result = await TSAuthenticationSDKModule.approvalWebAuthnWithData(rawAuthenticationData, []); + console.log("Approval result: ", result); + } catch (error: any) { + this.setState({ errorMessage: `${error}` }); + } + } + // Navigation private navigateToAuthenticatedUserScreen = (username: string, isNewRegistration: boolean): void => { @@ -222,7 +262,7 @@ export default class App extends React.Component { this.configureExampleApp(appConfiguration); } else { - console.log(`Please configure the app by updating the 'config.ts' file`); + console.error(`Please configure the app by updating the 'config.ts' file`); } } diff --git a/example/src/home.tsx b/example/src/home.tsx index 66dea96..e309161 100644 --- a/example/src/home.tsx +++ b/example/src/home.tsx @@ -6,11 +6,14 @@ */ import React, { type ReactElement } from 'react'; -import { View, StyleSheet, Text, Button, TextInput } from 'react-native'; +import { View, StyleSheet, Text, Button, TextInput, Alert } from 'react-native'; +import { TSAuthenticationSDK } from '../../lib/typescript/src'; export type Props = { onStartAuthentication: (username: string) => void; onStartNativeBiometrics: (username: string) => void; + onApprovalWebAuthn: (username: string, approvalData: { [key: string]: string; }) => void; + onApprovalWebAuthnWithData: (rawAuthenticationData: { [key: string]: any; } ) => void; errorMessage: string; }; @@ -35,6 +38,8 @@ export default class HomeScreen extends React.Component { {this.renderUsernameInputField()} {this.renderStartAuthenticationButton()} {this.renderNativeBiometricsButton()} + {this.renderApprovalWebAuthnButton()} + {this.renderApprovalWebAuthnWithDataButton()} {this.renderStatusLabel()} ); @@ -42,7 +47,7 @@ export default class HomeScreen extends React.Component { private renderUsernameInputField(): ReactElement { return ( - + this.setState({ username: text })} @@ -56,7 +61,7 @@ export default class HomeScreen extends React.Component { private renderStatusLabel(): ReactElement { return ( - + {this.props.errorMessage} ) @@ -64,7 +69,7 @@ export default class HomeScreen extends React.Component { private renderStartAuthenticationButton(): ReactElement { return ( - +