├── testapp ├── .node-version ├── .watchmanconfig ├── .ruby-version ├── app.json ├── .bundle │ └── config ├── babel.config.js ├── .prettierrc.json ├── android │ ├── app │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── values │ │ │ │ │ │ ├── strings.xml │ │ │ │ │ │ └── styles.xml │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ │ └── drawable │ │ │ │ │ │ └── rn_edit_text_material.xml │ │ │ │ ├── java │ │ │ │ │ └── com │ │ │ │ │ │ └── testapp │ │ │ │ │ │ ├── MainActivity.kt │ │ │ │ │ │ └── MainApplication.kt │ │ │ │ └── AndroidManifest.xml │ │ │ └── debug │ │ │ │ └── AndroidManifest.xml │ │ ├── debug.keystore │ │ └── proguard-rules.pro │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── settings.gradle │ ├── build.gradle │ └── gradle.properties ├── ios │ ├── testapp │ │ ├── Images.xcassets │ │ │ ├── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ ├── testapp.entitlements │ │ ├── AppDelegate.swift │ │ ├── PrivacyInfo.xcprivacy │ │ └── Info.plist │ ├── testapp.xcworkspace │ │ └── contents.xcworkspacedata │ ├── .xcode.env │ └── Podfile ├── .prettierrc.js ├── index.js ├── tsconfig.json ├── Gemfile ├── react-native.config.js ├── .eslintrc.js ├── _tests │ ├── testbed │ │ ├── EmptyTestSuite.ts │ │ ├── CustomMonitor.ts │ │ └── CustomInteraction.ts │ ├── PowerAuth_KDF.test.ts │ ├── PowerAuth_TimeSync.test.ts │ ├── helpers │ │ └── PasswordHelper.ts │ ├── PowerAuthUtils.test.ts │ └── PowerAuth_ErrorData.test.ts ├── src │ └── testbed │ │ ├── index.ts │ │ ├── private │ │ ├── CallStack.ts │ │ ├── ObjectHelper.ts │ │ └── ErrorHelper.ts │ │ └── TestInteraction.ts ├── metro.config.js ├── .env-example ├── .gitignore └── package.json ├── .npmrc ├── packages ├── cordova-powerauth-mobile-sdk │ ├── android │ │ ├── .gitignore │ │ ├── src │ │ │ └── main │ │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── wultra │ │ │ │ └── android │ │ │ │ └── powerauth │ │ │ │ ├── cdv │ │ │ │ ├── util │ │ │ │ │ ├── ReadableType.kt │ │ │ │ │ ├── ReadableMapKeySetIteratorImpl.kt │ │ │ │ │ ├── WritableArray.kt │ │ │ │ │ ├── Dynamic.kt │ │ │ │ │ ├── WritableMap.kt │ │ │ │ │ ├── ReadableArray.kt │ │ │ │ │ ├── ReadableMap.kt │ │ │ │ │ ├── WritableNativeArray.kt │ │ │ │ │ ├── NativeDynamic.kt │ │ │ │ │ ├── WritableNativeMap.kt │ │ │ │ │ └── ReadableNativeArray.kt │ │ │ │ ├── PowerAuthPassphraseMeterModule.kt │ │ │ │ ├── PowerAuthCryptoUtilsModule.kt │ │ │ │ └── PowerAuthObjectRegister.kt │ │ │ │ └── bridge │ │ │ │ └── Aliases.kt │ │ └── build.gradle │ ├── ios │ │ └── PowerAuth │ │ │ ├── LiftPowerAuthSdk.h │ │ │ ├── LiftPowerAuthSdk.m │ │ │ └── PAJSPlatform.h │ ├── src │ │ └── internal │ │ │ ├── NativePowerAuth.ts │ │ │ ├── Utils.ts │ │ │ └── NativeCordovaModule.ts │ └── package.json └── react-native-powerauth-mobile-sdk │ ├── ios │ ├── package.json │ ├── PowerAuth.xcodeproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── PowerAuth.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── .xcode.env │ ├── Podfile │ └── PowerAuth │ │ ├── PAJSPlatform.h │ │ ├── PowerAuthModule.h │ │ ├── PowerAuthStorageUtilsModule.h │ │ ├── Info.plist │ │ ├── PowerAuthPasswordModule.h │ │ ├── PowerAuthPassphraseMeterModule.h │ │ ├── PowerAuthCryptoUtilsModule.h │ │ ├── pin_tester.h │ │ ├── LiftPowerAuthSdk.m │ │ ├── PowerAuthData.h │ │ ├── PowerAuthData.m │ │ ├── LiftPowerAuthSdk.h │ │ ├── Constants.h │ │ ├── wpm_types.h │ │ └── PowerAuthEncryptorModule.h │ ├── android │ ├── settings.gradle │ ├── src │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ └── com │ │ │ └── wultra │ │ │ └── android │ │ │ └── powerauth │ │ │ ├── js │ │ │ ├── BaseJavaJsModule.kt │ │ │ ├── Utils.kt │ │ │ ├── ActivityAwareModule.kt │ │ │ ├── IManagedObject.kt │ │ │ ├── WrapperException.java │ │ │ ├── Constants.java │ │ │ └── PowerAuthCryptoUtilsJsModule.kt │ │ │ ├── bridge │ │ │ └── Aliases.kt │ │ │ └── reactnative │ │ │ ├── PowerAuthReactPackage.java │ │ │ ├── PowerAuthUtils.java │ │ │ ├── PowerAuthCryptoUtilsModule.java │ │ │ └── PowerAuthPassphraseMeterModule.java │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── generated │ │ └── jni │ │ │ └── CMakeLists.txt │ ├── gradlew.bat │ └── build.gradle │ ├── src │ ├── internal │ │ ├── SDKVersion.ts │ │ ├── NativeCryptoUtils.ts │ │ ├── NativePowerAuthIfc.ts │ │ ├── Utils.ts │ │ ├── NativePowerAuth.ts │ │ ├── NativeStorageUtils.ts │ │ ├── NativePassphraseMeter.ts │ │ ├── NativeModulesProvider.ts │ │ └── NativeModulesProviderIfc.ts │ ├── debug │ │ └── NativeObjectRegister.ts │ ├── model │ │ ├── PowerAuthConfirmRecoveryCodeDataResult.ts │ │ ├── PowerAuthDataFormat.ts │ │ ├── PowerAuthRecoveryActivationData.ts │ │ ├── PowerAuthNativeObject.ts │ │ ├── PowerAuthEncryptionHttpHeader.ts │ │ ├── PowerAuthAuthorizationHttpHeader.ts │ │ ├── PowerAuthActivationStatus.ts │ │ ├── PowerAuthExternalPendingOperation.ts │ │ ├── PowerAuthActivationState.ts │ │ ├── PowerAuthCreateActivationResult.ts │ │ ├── PowerAuthConfiguration.ts │ │ └── PowerAuthNativeTypes.ts │ ├── PowerAuthCryptoUtils.ts │ └── index.ts │ ├── .prettierrc.json │ ├── react-native.config.js │ ├── tsconfig.build-types.json │ ├── .eslintrc.js │ ├── tsconfig.json │ ├── scripts │ └── generate-sdk-version.cjs │ ├── .gitignore │ └── react-native-powerauth-mobile-sdk.podspec ├── .limedeploy ├── .vscode └── settings.json ├── testapp-cordova ├── www │ └── img │ │ └── logo.png ├── .gitignore ├── config.xml ├── package.json └── src │ └── App.tsx ├── .yarnrc.yml ├── .github ├── dependabot.yml ├── workflows │ ├── build-library.yml │ ├── build-react-native.yml │ └── build-cordova.yml └── actions │ └── prepare │ └── action.yml ├── docs ├── Version-2.4.md ├── Version-2.5.md ├── Migration-Instructions.md ├── Sample-Integration.md ├── _Sidebar.md ├── Troubleshooting.md ├── Secure-Vault.md ├── Installation.md ├── Crypto-Utilities.md ├── Accessing-Native-PowerAuthSDK.md ├── Additional-Utilities.md ├── Storage-Utilities.md ├── Changelog.md └── Device-Activation-Removal.md ├── .gitignore ├── .deploy └── package.json ├── .prepare-release.json └── scripts └── prepare-release.sh /testapp/.node-version: -------------------------------------------------------------------------------- 1 | 18 -------------------------------------------------------------------------------- /testapp/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /testapp/.ruby-version: -------------------------------------------------------------------------------- 1 | 2.7.6 2 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | //registry.npmjs.org/:_authToken=${NPM_TOKEN} 2 | -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/android/.gitignore: -------------------------------------------------------------------------------- 1 | .gradle/ -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/package.json: -------------------------------------------------------------------------------- 1 | ../package.json -------------------------------------------------------------------------------- /testapp/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "testapp", 3 | "displayName": "Test App" 4 | } -------------------------------------------------------------------------------- /testapp/.bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /.limedeploy: -------------------------------------------------------------------------------- 1 | DEPLOY_VERSIONING_FILES=( ".deploy/package.json,package.json" ) 2 | DEPLOY_MODE='npm' -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "java.configuration.updateBuildConfiguration": "interactive" 3 | } -------------------------------------------------------------------------------- /testapp/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:@react-native/babel-preset'], 3 | }; -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'PowerAuthReactNative' 2 | -------------------------------------------------------------------------------- /testapp/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "singleQuote": true, 4 | "trailingComma": "all" 5 | } 6 | 7 | 8 | -------------------------------------------------------------------------------- /testapp/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | testapp 3 | 4 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/internal/SDKVersion.ts: -------------------------------------------------------------------------------- 1 | // AUTO-GENERATED 2 | export const SDK_VERSION = '0.0.1-dev'; 3 | -------------------------------------------------------------------------------- /testapp/ios/testapp/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /testapp-cordova/www/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wultra/react-native-powerauth-mobile-sdk/HEAD/testapp-cordova/www/img/logo.png -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | nodeLinker: node-modules 2 | enableImmutableInstalls: false 3 | checksumBehavior: update 4 | nmHoistingLimits: workspaces 5 | 6 | 7 | -------------------------------------------------------------------------------- /testapp/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wultra/react-native-powerauth-mobile-sdk/HEAD/testapp/android/app/debug.keystore -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "singleQuote": true, 4 | "trailingComma": "all" 5 | } 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /testapp/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wultra/react-native-powerauth-mobile-sdk/HEAD/testapp/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /testapp/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | arrowParens: 'avoid', 3 | bracketSameLine: true, 4 | bracketSpacing: false, 5 | singleQuote: true, 6 | trailingComma: 'all', 7 | }; 8 | -------------------------------------------------------------------------------- /testapp/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wultra/react-native-powerauth-mobile-sdk/HEAD/testapp/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /testapp/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wultra/react-native-powerauth-mobile-sdk/HEAD/testapp/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /testapp/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wultra/react-native-powerauth-mobile-sdk/HEAD/testapp/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /testapp/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wultra/react-native-powerauth-mobile-sdk/HEAD/testapp/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /testapp/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wultra/react-native-powerauth-mobile-sdk/HEAD/testapp/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /testapp/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wultra/react-native-powerauth-mobile-sdk/HEAD/testapp/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /testapp/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wultra/react-native-powerauth-mobile-sdk/HEAD/testapp/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /testapp/index.js: -------------------------------------------------------------------------------- 1 | import { AppRegistry } from 'react-native'; 2 | import App from './src/App'; 3 | import { name as appName } from './app.json'; 4 | 5 | AppRegistry.registerComponent(appName, () => App); 6 | -------------------------------------------------------------------------------- /testapp/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wultra/react-native-powerauth-mobile-sdk/HEAD/testapp/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /testapp/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wultra/react-native-powerauth-mobile-sdk/HEAD/testapp/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /testapp/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wultra/react-native-powerauth-mobile-sdk/HEAD/testapp/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/gradle.properties: -------------------------------------------------------------------------------- 1 | android.useAndroidX=true 2 | android.enableJetifier=true 3 | 4 | # Required due to processing a massive react-android AAR 5 | org.gradle.jvmargs=-Xmx2048M -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: npm 4 | directory: "/" # Root directory 5 | schedule: 6 | interval: weekly 7 | exclude-paths: 8 | - "testapp/**" 9 | - "testapp-cordova/**" -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wultra/react-native-powerauth-mobile-sdk/HEAD/packages/react-native-powerauth-mobile-sdk/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/js/BaseJavaJsModule.kt: -------------------------------------------------------------------------------- 1 | package com.wultra.android.powerauth.js 2 | 3 | /** 4 | * Module base. 5 | */ 6 | public interface BaseJavaJsModule { 7 | 8 | fun getName(): String 9 | } 10 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/js/Utils.kt: -------------------------------------------------------------------------------- 1 | package com.wultra.android.powerauth.bridge 2 | 3 | @Retention(AnnotationRetention.RUNTIME) 4 | public annotation class JsApiMethod( 5 | public val isBlockingSynchronousMethod: Boolean = false 6 | ) -------------------------------------------------------------------------------- /testapp/ios/testapp.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /testapp/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@react-native/typescript-config/tsconfig.json", 3 | "compilerOptions": { 4 | "types": ["react-native"], 5 | "strict": true, 6 | // "noUncheckedIndexedAccess": true, 7 | // "noImplicitOverride": true, 8 | "noFallthroughCasesInSwitch": true 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/generated/jni/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.13) 2 | # Forward to the actual codegen output produced by the RN Gradle plugin 3 | add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/../../build/generated/source/codegen/jni PowerAuthReactNative_autolinked_build) 4 | 5 | 6 | -------------------------------------------------------------------------------- /testapp/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-all.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Apr 08 16:09:51 CEST 2025 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/react-native.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @type {import('@react-native-community/cli-types').UserDependencyConfig} 3 | */ 4 | module.exports = { 5 | dependency: { 6 | platforms: { 7 | android: { 8 | cmakeListsPath: 'generated/jni/CMakeLists.txt', 9 | }, 10 | }, 11 | }, 12 | }; -------------------------------------------------------------------------------- /docs/Version-2.4.md: -------------------------------------------------------------------------------- 1 | # Migration from 2.3.x to 2.4.x 2 | 3 | This guide contains instructions for migration from React Native PowerAuth mobile SDK version `2.3.x` to version `2.4.x`. 4 | 5 | ## Support for React Native 0.71 6 | 7 | There are no special migration instructions except that version 2.4.0 require that your application should support React Native 0.71 and later. -------------------------------------------------------------------------------- /docs/Version-2.5.md: -------------------------------------------------------------------------------- 1 | # Migration from 2.4.x to 2.5.x 2 | 3 | This guide contains instructions for migration from React Native PowerAuth mobile SDK version `2.4.x` to version `2.5.x`. 4 | 5 | ## Support for React Native 0.73+ 6 | 7 | There are no special migration instructions except that version 2.5.0 requires that your application should support React Native 0.73 and later. -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /testapp/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/cdv/util/ReadableType.kt: -------------------------------------------------------------------------------- 1 | package com.wultra.android.powerauth.cdv.util 2 | 3 | /** Defines the type of an object stored in a [ReadableArray] or [ReadableMap]. */ 4 | public enum class ReadableType { 5 | Null, 6 | Boolean, 7 | Number, 8 | String, 9 | Map, 10 | Array, 11 | } 12 | -------------------------------------------------------------------------------- /testapp/android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") } 2 | plugins { id("com.facebook.react.settings") } 3 | extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() } 4 | rootProject.name = 'testapp' 5 | include ':app' 6 | includeBuild('../node_modules/@react-native/gradle-plugin') 7 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/tsconfig.build-types.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "declaration": true, 5 | "emitDeclarationOnly": true, 6 | "declarationMap": false, 7 | "outDir": "lib/typescript", 8 | "noEmit": false 9 | }, 10 | "include": ["src/**/*"], 11 | "exclude": ["node_modules", "lib"] 12 | } 13 | -------------------------------------------------------------------------------- /testapp/ios/testapp/testapp.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.com.wultra.testGroup 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | plugins: ['@typescript-eslint'], 5 | extends: ['@react-native/eslint-config', 'plugin:@typescript-eslint/recommended', 'prettier'], 6 | ignorePatterns: ['lib/', 'node_modules/'], 7 | rules: { 8 | '@typescript-eslint/no-explicit-any': 'off', 9 | }, 10 | }; 11 | 12 | 13 | -------------------------------------------------------------------------------- /testapp/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version 4 | ruby ">= 2.6.10" 5 | 6 | # Exclude problematic versions of cocoapods and activesupport that causes build failures. 7 | gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1' 8 | gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0' 9 | gem 'xcodeproj', '< 1.26.0' 10 | gem 'concurrent-ruby', '< 1.3.4' 11 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/internal/NativeCryptoUtils.ts: -------------------------------------------------------------------------------- 1 | import { NativeModulesProvider } from './NativeModulesProvider'; 2 | import { Base64String } from "../PowerAuthCryptoUtils"; 3 | 4 | export interface PowerAuthCryptoUtilsIfc { 5 | hashSha256(data: Base64String): Promise 6 | randomBytes(length: number): Promise 7 | } 8 | 9 | export const NativeCryptoUtils = NativeModulesProvider.PowerAuthCryptoUtils; -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/js/ActivityAwareModule.kt: -------------------------------------------------------------------------------- 1 | package com.wultra.android.powerauth.js 2 | 3 | import android.app.Activity 4 | 5 | /** 6 | * Module aware of the activity. 7 | */ 8 | interface ActivityAwareModule { 9 | 10 | fun getCurrentActivity(): Activity 11 | } 12 | 13 | /** 14 | * Provider of activity. 15 | */ 16 | interface ActivityProvider { 17 | fun getActivity(): Activity 18 | } -------------------------------------------------------------------------------- /testapp/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 11 | 12 | -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/cdv/util/ReadableMapKeySetIteratorImpl.kt: -------------------------------------------------------------------------------- 1 | package com.wultra.android.powerauth.cdv.util 2 | 3 | 4 | class ReadableMapKeySetIteratorImpl(val iterator: Iterator) : ReadableMapKeySetIterator { 5 | 6 | override fun hasNextKey(): Boolean { 7 | return iterator.hasNext() 8 | } 9 | 10 | override fun nextKey(): String { 11 | return iterator.next() 12 | } 13 | } -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@react-native/typescript-config/tsconfig.json", 3 | "compilerOptions": { 4 | "declaration": false, 5 | "composite": false, 6 | "strict": true, 7 | "noUncheckedIndexedAccess": true, 8 | "noImplicitOverride": true, 9 | "noFallthroughCasesInSwitch": true, 10 | "skipLibCheck": false, 11 | "baseUrl": ".", 12 | "types": [] 13 | }, 14 | "exclude": ["node_modules", "lib"], 15 | "include": ["src"] 16 | } -------------------------------------------------------------------------------- /testapp/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # Run the following command from 'ios' folder to setup the path: 8 | # 9 | # echo "export NODE_BINARY=$(which node)" > .xcode.env.local 10 | # -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/scripts/generate-sdk-version.cjs: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const pkg = require('../package.json'); 5 | 6 | const outDir = path.join(__dirname, '..', 'src', 'internal'); 7 | const outFile = path.join(outDir, 'SDKVersion.ts'); 8 | 9 | fs.mkdirSync(outDir, { recursive: true }); 10 | fs.writeFileSync(outFile, `// AUTO-GENERATED\nexport const SDK_VERSION = '${pkg.version}';\n`); 11 | console.log(`Wrote ${outFile}`); 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /testapp/ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /.github/workflows/build-library.yml: -------------------------------------------------------------------------------- 1 | name: Build Library 2 | 3 | on: 4 | push: 5 | branches: 6 | - develop 7 | - release/* 8 | pull_request: 9 | 10 | jobs: 11 | build-library: 12 | name: Build and Pack 13 | runs-on: macos-latest 14 | steps: 15 | - name: Checkout the repo 16 | uses: actions/checkout@v4 17 | - name: Prepare environment 18 | uses: ./.github/actions/prepare 19 | with: 20 | env-file: ${{ secrets.ENV_TEST_FILE }} 21 | - name: Library build 22 | run: yarn build -------------------------------------------------------------------------------- /testapp/react-native.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | module.exports = { 4 | project: { 5 | ios: { 6 | automaticPodsInstallation: true, 7 | }, 8 | }, 9 | dependencies: { 10 | 'react-native-powerauth-mobile-sdk': { 11 | root: path.join(__dirname, '..', 'packages', 'react-native-powerauth-mobile-sdk'), 12 | platforms: { 13 | // Codegen script incorrectly fails without this 14 | // So we explicitly specify the platforms with empty object 15 | ios: {}, 16 | android: {}, 17 | }, 18 | }, 19 | }, 20 | }; -------------------------------------------------------------------------------- /docs/Migration-Instructions.md: -------------------------------------------------------------------------------- 1 | # Migration Instructions 2 | 3 | This page contains PowerAuth Mobile JS SDK migration instructions. 4 | 5 | 6 | When updating across multiple versions, you need to perform all migration steps additively. 7 | 8 | 9 | - [Migration from version `2.4.x` to `2.5.x`](Version-2.5.md) 10 | - [Migration from version `2.3.x` to `2.4.x`](Version-2.4.md) 11 | - [Migration from version `2.2.x` to `2.3.x`](Version-2.3.md) 12 | - [Migration from version `3.x.x` to `4.0.0`](Version-4.0.md) 13 | 14 | ## Read Next 15 | 16 | - [Sample Integration](Sample-Integration.md) -------------------------------------------------------------------------------- /testapp/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext { 3 | buildToolsVersion = "35.0.0" 4 | minSdkVersion = 24 5 | compileSdkVersion = 35 6 | targetSdkVersion = 35 7 | ndkVersion = "27.1.12297006" 8 | kotlinVersion = "2.0.21" 9 | } 10 | repositories { 11 | google() 12 | mavenCentral() 13 | } 14 | dependencies { 15 | classpath("com.android.tools.build:gradle") 16 | classpath("com.facebook.react:react-native-gradle-plugin") 17 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") 18 | } 19 | } 20 | 21 | apply plugin: "com.facebook.react.rootproject" 22 | -------------------------------------------------------------------------------- /testapp/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parser: '@typescript-eslint/parser', 4 | plugins: ['@typescript-eslint'], 5 | extends: ['@react-native/eslint-config', 'plugin:@typescript-eslint/recommended', 'prettier'], 6 | ignorePatterns: ['node_modules/'], 7 | rules: { 8 | '@typescript-eslint/no-explicit-any': 'off' 9 | }, 10 | overrides: [ 11 | { 12 | files: ['metro.config.js', 'react-native.config.js', 'babel.config.js'], 13 | env: { node: true }, 14 | parserOptions: { sourceType: 'script' }, 15 | rules: { 16 | '@typescript-eslint/no-var-requires': 'off' 17 | } 18 | } 19 | ] 20 | }; 21 | -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/cdv/util/WritableArray.kt: -------------------------------------------------------------------------------- 1 | package com.wultra.android.powerauth.cdv.util 2 | 3 | /** Interface for a mutable array. Used to pass arguments from Kotlin to JS. */ 4 | public interface WritableArray : ReadableArray { 5 | public fun pushArray(array: ReadableArray?) 6 | 7 | public fun pushBoolean(value: Boolean) 8 | 9 | public fun pushDouble(value: Double) 10 | 11 | public fun pushInt(value: Int) 12 | 13 | public fun pushLong(value: Long) 14 | 15 | public fun pushMap(map: ReadableMap?) 16 | 17 | public fun pushNull() 18 | 19 | public fun pushString(value: String?) 20 | } 21 | -------------------------------------------------------------------------------- /.github/actions/prepare/action.yml: -------------------------------------------------------------------------------- 1 | name: Prepare PowerAuth JS environment 2 | 3 | inputs: 4 | env-file: 5 | description: Contents of the testapp/.env file 6 | required: false 7 | default: "empty" 8 | 9 | runs: 10 | using: composite 11 | steps: 12 | - name: Use Node.js 22 13 | uses: actions/setup-node@v4 14 | with: 15 | node-version: 22 16 | - name: Enable Yarn 17 | shell: bash 18 | run: corepack enable 19 | - name: Install dependencies (Yarn) 20 | shell: bash 21 | run: yarn install --immutable 22 | - name: Set .env file 23 | shell: bash 24 | run: | 25 | echo -e "${{ inputs.env-file }}" > testapp/.env -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/cdv/util/Dynamic.kt: -------------------------------------------------------------------------------- 1 | package com.wultra.android.powerauth.cdv.util 2 | 3 | /** 4 | * Type representing a piece of data with unknown runtime type. Useful for allowing javascript to 5 | * pass one of multiple types down to the native layer. 6 | */ 7 | public interface Dynamic { 8 | public val type: ReadableType 9 | 10 | public val isNull: Boolean 11 | 12 | public fun asArray(): ReadableArray 13 | 14 | public fun asBoolean(): Boolean 15 | 16 | public fun asDouble(): Double 17 | 18 | public fun asInt(): Int 19 | 20 | public fun asMap(): ReadableMap 21 | 22 | public fun asString(): String 23 | 24 | public fun recycle(): Unit 25 | } 26 | -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | mavenCentral() 4 | google() 5 | } 6 | 7 | dependencies { 8 | classpath("com.android.tools.build:gradle:8.7.2") 9 | } 10 | } 11 | 12 | apply plugin: "org.jetbrains.kotlin.android" 13 | 14 | 15 | android { 16 | namespace = "com.wultra.android.powerauth.cdv" 17 | 18 | compileOptions { 19 | sourceCompatibility JavaVersion.VERSION_1_8 20 | targetCompatibility JavaVersion.VERSION_1_8 21 | } 22 | } 23 | 24 | repositories { 25 | mavenCentral() 26 | google() 27 | } 28 | 29 | dependencies { 30 | implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.9.22")) 31 | api "com.wultra.android.powerauth:powerauth-sdk:1.9.5" 32 | } 33 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/Podfile: -------------------------------------------------------------------------------- 1 | #require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 2 | require_relative '../node_modules/react-native/scripts/react_native_pods' 3 | 4 | platform :ios, '18.0' 5 | 6 | project 'PowerAuth' 7 | 8 | target 'PowerAuth' do 9 | config = use_native_modules! 10 | use_react_native!( 11 | :path => config[:reactNativePath], 12 | :hermes_enabled => false 13 | ) 14 | pod 'PowerAuth2', '~> 1.9.5' 15 | # Uncomment to use not-published SDK in project. This is effective only if you manually open 'ios/PowerAuth.xcworkspace' 16 | #pod 'PowerAuth2', :git => 'https://github.com/wultra/powerauth-mobile-sdk.git', :branch => 'develop', :submodules => true 17 | end 18 | -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/ios/PowerAuth/LiftPowerAuthSdk.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // This feature is not available for Cordova -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/ios/PowerAuth/LiftPowerAuthSdk.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // This feature is not available for Cordova 18 | -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/ios/PowerAuth/PAJSPlatform.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef PAJS_CORDOVA 18 | #define PAJS_CORDOVA 19 | #endif 20 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth/PAJSPlatform.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef PAJS_REACT 18 | #define PAJS_REACT 19 | #endif 20 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth/PowerAuthModule.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2020 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import "PAJS.h" 18 | 19 | PAJS_MODULE(PowerAuthModule) 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /testapp/_tests/testbed/EmptyTestSuite.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2022 Wultra s.r.o. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | import { TestSuite } from "../../src/testbed"; 18 | 19 | export class EmptyTestSuite extends TestSuite { 20 | } -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/internal/NativePowerAuthIfc.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export interface NativePowerAuthIfc { 18 | callNative(...args: any[]): Promise; 19 | } -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth/PowerAuthStorageUtilsModule.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import "PAJS.h" 18 | 19 | PAJS_MODULE_BASIC(PowerAuthStorageUtilsModule) 20 | 21 | @end 22 | 23 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/internal/Utils.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { Platform } from 'react-native'; 18 | 19 | export class Utils { 20 | static platformOs = Platform.OS; 21 | } -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/cdv/util/WritableMap.kt: -------------------------------------------------------------------------------- 1 | package com.wultra.android.powerauth.cdv.util 2 | 3 | /** Interface for a mutable map. Used to pass arguments from Kotlin to JS. */ 4 | public interface WritableMap : ReadableMap { 5 | public fun copy(): WritableMap 6 | 7 | public fun merge(source: ReadableMap) 8 | 9 | public fun putArray(key: String, value: ReadableArray?) 10 | 11 | public fun putBoolean(key: String, value: Boolean) 12 | 13 | public fun putDouble(key: String, value: Double) 14 | 15 | public fun putInt(key: String, value: Int) 16 | 17 | public fun putLong(key: String, value: Long) 18 | 19 | public fun putMap(key: String, value: ReadableMap?) 20 | 21 | public fun putNull(key: String) 22 | 23 | public fun putString(key: String, value: String?) 24 | } 25 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | 22 | 23 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth/PowerAuthPasswordModule.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import "PAJS.h" 18 | 19 | /** 20 | Bridge module implementing PowerAuthPassword JavaScript class. 21 | */ 22 | PAJS_MODULE(PowerAuthPasswordModule) 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth/PowerAuthPassphraseMeterModule.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import "PAJS.h" 18 | 19 | /** 20 | Bridge implementing PowerAuthPassphraseMeter interface. 21 | */ 22 | PAJS_MODULE(PowerAuthPassphraseMeterModule) 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /testapp/src/testbed/index.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2022 Wultra s.r.o. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | export * from './expect'; 18 | export * from './TestInteraction'; 19 | export * from './TestLog'; 20 | export * from './TestMonitor'; 21 | export * from './TestProgress'; 22 | export * from './TestRunner'; 23 | export * from './TestSuite'; -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth/PowerAuthCryptoUtilsModule.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import "PAJS.h" 18 | 19 | /** 20 | Bridge module implementing PowerAuthCryptoUtils JavaScript class for iOS. 21 | */ 22 | PAJS_MODULE_BASIC(PowerAuthCryptoUtilsModule) 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/src/internal/NativePowerAuth.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | //@ts-nocheck 18 | 19 | import { NativeCordovaModule } from "./NativeCordovaModule"; 20 | 21 | export class NativePowerAuth extends NativeCordovaModule { 22 | 23 | readonly pluginName = "PowerAuthModule"; 24 | } 25 | -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/src/internal/Utils.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | export class Utils { 18 | 19 | static platformOs = this.detectPlatform() 20 | 21 | private static detectPlatform(): string { 22 | 23 | // @ts-expect-error 24 | return cordova.platformId 25 | } 26 | } -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/debug/NativeObjectRegister.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2022 Wultra s.r.o. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | import { NativeModulesProvider } from "../internal/NativeModulesProvider"; 18 | 19 | /** 20 | * Instance of native object register. 21 | */ 22 | export const NativeObjectRegister = NativeModulesProvider.PowerAuthObjectRegister; 23 | -------------------------------------------------------------------------------- /testapp/android/app/src/main/java/com/testapp/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.testapp 2 | 3 | import com.facebook.react.ReactActivity 4 | import com.facebook.react.ReactActivityDelegate 5 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled 6 | import com.facebook.react.defaults.DefaultReactActivityDelegate 7 | 8 | class MainActivity : ReactActivity() { 9 | 10 | /** 11 | * Returns the name of the main component registered from JavaScript. This is used to schedule 12 | * rendering of the component. 13 | */ 14 | override fun getMainComponentName(): String = "testapp" 15 | 16 | /** 17 | * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] 18 | * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] 19 | */ 20 | override fun createReactActivityDelegate(): ReactActivityDelegate = 21 | DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) 22 | } 23 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | .DS_Store 3 | 4 | # vscode 5 | .vscode 6 | !.vscode/launch.json 7 | 8 | # library 9 | node_modules 10 | lib 11 | 12 | # demoapp 13 | demoapp/node_modules 14 | 15 | # Android 16 | android/.gradle/ 17 | android/.project 18 | android/.settings 19 | android/.idea 20 | android/local.properties 21 | /android/.classpath 22 | demoapp/android/local.properties 23 | demoapp/android/.gradle/ 24 | demoapp/android/.project 25 | demoapp/android/.idea 26 | demoapp/android/.settings 27 | demoapp/android/app/.gradle/ 28 | demoapp/android/app/.project 29 | demoapp/android/app/.settings 30 | demoapp/.expo 31 | *build/ 32 | .idea 33 | *.iml 34 | *.ipr 35 | *.iws 36 | out 37 | gen-external-apklibs 38 | 39 | # iOS 40 | xcuserdata 41 | *.xcuserstate 42 | ios/Pods/* 43 | demoapp/ios/Pods/* 44 | .xcode.env.local 45 | 46 | # artifacts 47 | *.tgz 48 | 49 | # Yarn and monorepo 50 | .yarn 51 | .yarn/* 52 | !.yarn/releases 53 | !.yarn/plugins 54 | .pnp.* 55 | -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/cdv/util/ReadableArray.kt: -------------------------------------------------------------------------------- 1 | package com.wultra.android.powerauth.cdv.util 2 | 3 | import java.util.ArrayList 4 | 5 | /** 6 | * Interface for an array that allows typed access to its members. Used to pass parameters from JS 7 | * to Kotlin. 8 | */ 9 | public interface ReadableArray { 10 | public fun getArray(index: Int): ReadableArray 11 | 12 | public fun getBoolean(index: Int): Boolean 13 | 14 | public fun getDouble(index: Int): Double 15 | 16 | public fun getDynamic(index: Int): Dynamic 17 | 18 | public fun getInt(index: Int): Int 19 | 20 | public fun getLong(index: Int): Long 21 | 22 | public fun getMap(index: Int): ReadableMap 23 | 24 | public fun getString(index: Int): String 25 | 26 | public fun getType(index: Int): ReadableType 27 | 28 | public fun isNull(index: Int): Boolean 29 | 30 | public fun size(): Int 31 | 32 | public fun toArrayList(): ArrayList 33 | } 34 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/model/PowerAuthConfirmRecoveryCodeDataResult.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * Result of the confirmRecoveryCode PowerAuth method. 19 | */ 20 | export interface PowerAuthConfirmRecoveryCodeDataResult { 21 | /** 22 | * Indicates that the code was already confirmed in the past 23 | */ 24 | alreadyConfirmed: boolean 25 | } -------------------------------------------------------------------------------- /testapp/src/testbed/private/CallStack.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2022 Wultra s.r.o. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | export function parseRnCallStack(stack: string, padding: string = ""): string { 18 | const lines = stack.split('\n'); 19 | if (lines.length == 0) { 20 | return ''; 21 | } 22 | return lines 23 | .filter(line => line.length > 0 && line.startsWith(' at')) 24 | .map(line => `${padding} ${line}`).join('\n') 25 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | .DS_Store 3 | 4 | # vscode 5 | .vscode 6 | !.vscode/launch.json 7 | 8 | # library 9 | node_modules 10 | lib 11 | 12 | # demoapp 13 | demoapp/node_modules 14 | 15 | # Android 16 | android/.gradle/ 17 | android/.project 18 | android/.settings 19 | android/.idea 20 | android/local.properties 21 | /android/.classpath 22 | demoapp/android/local.properties 23 | demoapp/android/.gradle/ 24 | demoapp/android/.project 25 | demoapp/android/.idea 26 | demoapp/android/.settings 27 | demoapp/android/app/.gradle/ 28 | demoapp/android/app/.project 29 | demoapp/android/app/.settings 30 | demoapp/.expo 31 | *build/ 32 | .idea 33 | *.iml 34 | *.ipr 35 | *.iws 36 | out 37 | gen-external-apklibs 38 | 39 | # iOS 40 | xcuserdata 41 | *.xcuserstate 42 | ios/Pods/* 43 | demoapp/ios/Pods/* 44 | .xcode.env.local 45 | 46 | # artifacts 47 | *.tgz 48 | package-lock.json 49 | npm-shrinkwrap.json 50 | 51 | # Yarn and monorepo 52 | .yarn 53 | yarn/* 54 | !.yarn/releases 55 | !.yarn/plugins 56 | !.yarn/patches 57 | !.yarn/sdks 58 | !.yarn/versions 59 | .pnp.* 60 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth/pin_tester.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef wultra_pin_tester_h 18 | #define wultra_pin_tester_h 19 | 20 | #include 21 | #include "wpm_types.h" 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif 26 | 27 | WPM_PasscodeResult PinTester_testPasscode(const char * pin); 28 | 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | #endif /* wultra_pin_tester_h */ 34 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/model/PowerAuthDataFormat.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * Input or output data format specification for the cryptographic operation: 19 | * - `UTF8` - data is formatted as a plain string that will be converted into UTF-8 encoded sequence of bytes before the operation. 20 | * - `BASE64` - binary data encoded into Base64 string. 21 | */ 22 | export type PowerAuthDataFormat = 'UTF8' | 'BASE64' 23 | -------------------------------------------------------------------------------- /testapp-cordova/.gitignore: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | 19 | .DS_Store 20 | 21 | # Generated by package manager 22 | node_modules/ 23 | 24 | # Generated by Cordova 25 | /plugins/ 26 | /platforms/ 27 | 28 | # compiled file 29 | www/js/index.js 30 | 31 | .temp/ -------------------------------------------------------------------------------- /testapp/ios/testapp/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import React 3 | import React_RCTAppDelegate 4 | import ReactAppDependencyProvider 5 | 6 | @main 7 | class AppDelegate: RCTAppDelegate { 8 | override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool { 9 | self.moduleName = "testapp" 10 | self.dependencyProvider = RCTAppDependencyProvider() 11 | 12 | // You can add your custom initial props in the dictionary below. 13 | // They will be passed down to the ViewController used by React Native. 14 | self.initialProps = [:] 15 | 16 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 17 | } 18 | 19 | override func sourceURL(for bridge: RCTBridge) -> URL? { 20 | self.bundleURL() 21 | } 22 | 23 | override func bundleURL() -> URL? { 24 | #if DEBUG 25 | RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index") 26 | #else 27 | Bundle.main.url(forResource: "main", withExtension: "jsbundle") 28 | #endif 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /docs/Sample-Integration.md: -------------------------------------------------------------------------------- 1 | # Sample Integration 2 | 3 | To better understand the APIs of the PowerAuth Mobile JS SDK, we prepared a sample test application. 4 | 5 | ## Test Application 6 | 7 | The test application with the PowerAuth Mobile JS SDK integration can be found inside the `testapp` folder of the [GitHub repository](https://github.com/wultra/react-native-powerauth-mobile-sdk#docucheck-keep-link). Visit [_tests](https://github.com/wultra/react-native-powerauth-mobile-sdk/blob/develop/testapp/_tests#docucheck-keep-link) folder for example usage of the SDK. The [PowerAuth_Example.ts](https://github.com/wultra/react-native-powerauth-mobile-sdk/blob/develop/testapp/_tests/PowerAuth_Example.ts#docucheck-keep-link) file is perhaps the best start point, because contains a well commented example of the activation flow. 8 | 9 | 10 | The test application is using direct calls to PowerAuth Cloud component to manage activations on the server automatically. You suppose to don't do such thing in the real application. 11 | 12 | 13 | ## Read Next 14 | 15 | - [User Info](User-Info.md) -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/bridge/Aliases.kt: -------------------------------------------------------------------------------- 1 | package com.wultra.android.powerauth.bridge 2 | 3 | import android.content.Context 4 | 5 | // point to React bridge 6 | typealias Arguments = com.facebook.react.bridge.Arguments 7 | typealias Dynamic = com.facebook.react.bridge.Dynamic 8 | typealias Promise = com.facebook.react.bridge.Promise 9 | typealias ReactMethod = com.facebook.react.bridge.ReactMethod 10 | typealias ReadableArray = com.facebook.react.bridge.ReadableArray 11 | typealias ReadableMap = com.facebook.react.bridge.ReadableMap 12 | typealias ReadableType = com.facebook.react.bridge.ReadableType 13 | typealias WritableArray = com.facebook.react.bridge.WritableArray 14 | typealias WritableMap = com.facebook.react.bridge.WritableMap 15 | 16 | 17 | 18 | // bridge to concrete platform implementation 19 | typealias BuildConfig = com.wultra.android.powerauth.reactnative.BuildConfig 20 | typealias PwBuildConfig = com.wultra.android.powerauth.bridge.ReactPwBuildConfig 21 | 22 | object ReactPwBuildConfig { 23 | fun isDebuggable(context: Context) = BuildConfig.DEBUG 24 | } -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/internal/NativePowerAuth.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { NativeModules } from "react-native"; 18 | import { NativePowerAuthIfc } from "./NativePowerAuthIfc"; 19 | 20 | export class NativePowerAuth implements NativePowerAuthIfc { 21 | callNative(name: string, ...args: any[]): Promise { 22 | // eslint-disable-next-line @typescript-eslint/ban-types 23 | return (NativeModules.PowerAuth[name] as Function).apply(null, ...args); 24 | } 25 | } -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/model/PowerAuthRecoveryActivationData.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * The `PowerAuthRecoveryActivationData` object contains information about recovery code and PUK, created 19 | * during the activation process. 20 | */ 21 | export interface PowerAuthRecoveryActivationData { 22 | /** 23 | * Contains recovery code. 24 | */ 25 | recoveryCode: string 26 | /** 27 | * Contains PUK, valid with recovery code. 28 | */ 29 | puk: string 30 | } -------------------------------------------------------------------------------- /.github/workflows/build-react-native.yml: -------------------------------------------------------------------------------- 1 | name: Build RN Integration 2 | 3 | on: 4 | push: 5 | branches: 6 | - develop 7 | - release/* 8 | pull_request: 9 | 10 | jobs: 11 | build-ios: 12 | name: iOS 13 | runs-on: macos-latest 14 | steps: 15 | - name: Checkout the repo 16 | uses: actions/checkout@v4 17 | - name: Prepare environment 18 | uses: ./.github/actions/prepare 19 | with: 20 | env-file: ${{ secrets.ENV_TEST_FILE }} 21 | - name: Build RN iOS 22 | run: yarn buildReactIos 23 | build-android: 24 | name: Android 25 | runs-on: macos-latest 26 | steps: 27 | - name: Checkout the repo 28 | uses: actions/checkout@v4 29 | - name: Prepare environment 30 | uses: ./.github/actions/prepare 31 | with: 32 | env-file: ${{ secrets.ENV_TEST_FILE }} 33 | - name: Setup Java 17 34 | uses: actions/setup-java@v4 35 | with: 36 | distribution: 'temurin' 37 | java-version: '17' 38 | cache: 'gradle' 39 | - name: Build RN Android 40 | run: yarn buildReactAndroid -------------------------------------------------------------------------------- /testapp/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 13 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /testapp/ios/testapp/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "2x", 6 | "size" : "20x20" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "scale" : "3x", 11 | "size" : "20x20" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "scale" : "2x", 16 | "size" : "29x29" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "scale" : "3x", 21 | "size" : "29x29" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "scale" : "2x", 26 | "size" : "40x40" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "scale" : "2x", 36 | "size" : "60x60" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "scale" : "3x", 41 | "size" : "60x60" 42 | }, 43 | { 44 | "idiom" : "ios-marketing", 45 | "scale" : "1x", 46 | "size" : "1024x1024" 47 | } 48 | ], 49 | "info" : { 50 | "author" : "xcode", 51 | "version" : 1 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /.github/workflows/build-cordova.yml: -------------------------------------------------------------------------------- 1 | name: Build Cordova Integration 2 | 3 | on: 4 | push: 5 | branches: 6 | - develop 7 | - release/* 8 | pull_request: 9 | 10 | jobs: 11 | build-ios: 12 | name: iOS 13 | runs-on: macos-latest 14 | steps: 15 | - name: Checkout the repo 16 | uses: actions/checkout@v4 17 | - name: Prepare environment 18 | uses: ./.github/actions/prepare 19 | with: 20 | env-file: ${{ secrets.ENV_TEST_FILE }} 21 | - name: Build Cordova iOS 22 | run: yarn buildCordovaIos 23 | build-android: 24 | name: Android 25 | runs-on: macos-latest 26 | steps: 27 | - name: Checkout the repo 28 | uses: actions/checkout@v4 29 | - name: Prepare environment 30 | uses: ./.github/actions/prepare 31 | with: 32 | env-file: ${{ secrets.ENV_TEST_FILE }} 33 | - name: Setup Java 17 34 | uses: actions/setup-java@v4 35 | with: 36 | distribution: 'temurin' 37 | java-version: '17' 38 | cache: 'gradle' 39 | - name: Build Cordova Android 40 | run: yarn buildCordovaAndroid -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/js/IManagedObject.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.wultra.android.powerauth.js 17 | 18 | /** 19 | * Interface for objects stored in the objects register. 20 | */ 21 | interface IManagedObject { 22 | /** 23 | * Do cleanup when object is being removed from the register. 24 | */ 25 | fun cleanup() 26 | 27 | /** 28 | * Return actual object stored in the register. 29 | */ 30 | fun managedInstance(): T 31 | } 32 | -------------------------------------------------------------------------------- /testapp/ios/testapp/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyAccessedAPITypes 6 | 7 | 8 | NSPrivacyAccessedAPIType 9 | NSPrivacyAccessedAPICategoryFileTimestamp 10 | NSPrivacyAccessedAPITypeReasons 11 | 12 | C617.1 13 | 14 | 15 | 16 | NSPrivacyAccessedAPIType 17 | NSPrivacyAccessedAPICategoryUserDefaults 18 | NSPrivacyAccessedAPITypeReasons 19 | 20 | CA92.1 21 | 22 | 23 | 24 | NSPrivacyAccessedAPIType 25 | NSPrivacyAccessedAPICategorySystemBootTime 26 | NSPrivacyAccessedAPITypeReasons 27 | 28 | 35F9.1 29 | 30 | 31 | 32 | NSPrivacyCollectedDataTypes 33 | 34 | NSPrivacyTracking 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /testapp/metro.config.js: -------------------------------------------------------------------------------- 1 | const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config'); 2 | const path = require('path'); 3 | const exclusionList = require('metro-config/src/defaults/exclusionList'); 4 | 5 | /** 6 | * Metro configuration 7 | * https://reactnative.dev/docs/metro 8 | * 9 | * @type {import('@react-native/metro-config').MetroConfig} 10 | */ 11 | const root = path.resolve(__dirname, '..'); 12 | const sdk = path.resolve(root, 'packages', 'react-native-powerauth-mobile-sdk'); 13 | const singletons = ['react', 'react-native']; 14 | 15 | const config = { 16 | watchFolders: [sdk], 17 | resolver: { 18 | unstable_enableSymlinks: true, 19 | enablePackageExports: true, 20 | nodeModulesPaths: [path.resolve(__dirname, 'node_modules')], 21 | blacklistRE: exclusionList( 22 | singletons.map(m => new RegExp(`^${path.join(root, 'node_modules', m).replace(/[\\/]/g, '[\\/]')}\/.*$`)) 23 | ), 24 | extraNodeModules: singletons.reduce((acc, name) => { 25 | acc[name] = path.join(__dirname, 'node_modules', name); 26 | return acc; 27 | }, {}), 28 | }, 29 | }; 30 | 31 | module.exports = mergeConfig(getDefaultConfig(__dirname), config); 32 | -------------------------------------------------------------------------------- /testapp/.env-example: -------------------------------------------------------------------------------- 1 | # ------------------------------------------------------------- # 2 | # If you need to provide credentials for PowerAuth Server # 3 | # then copy this file to `.env` and put your credentials there. # 4 | # # 5 | # The `.env` file is ignored by git, so it will not leak your # 6 | # credentials by accident. # 7 | # # 8 | # If you change some variable, then: # 9 | # run "npm run android" - to apply change on Android # 10 | # run "npm run ios" - to apply changes on iOS # 11 | # ------------------------------------------------------------- # 12 | 13 | # PowerAuth Cloud API 14 | POWERAUTH_CLOUD_URL=https://my-url.com/powerauth-cloud 15 | POWERAUTH_CLOUD_USERNAME=my-login 16 | POWERAUTH_CLOUD_PASSWORD=my-password 17 | POWERAUTH_CLOUD_APP_ID=my-app-id 18 | 19 | # User Data Store API 20 | UDS_SERVER_URL= 21 | UDS_SERVER_USERNAME= 22 | UDS_SERVER_PASSWORD= 23 | 24 | # PowerAuth Enrollment API 25 | ENROLLMENT_SERVER_URL=https://my-url.com/enrollment-server 26 | SDK_CONFIG=BASE64_ENCODED_CONFIG -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/internal/NativeStorageUtils.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { NativeModulesProvider } from './NativeModulesProvider'; 18 | 19 | export interface PowerAuthStorageUtilsIfc { 20 | setString(key: string, value: string, storageType: string): Promise 21 | getString(key: string, storageType: string): Promise 22 | exists(key: string, storageType: string): Promise 23 | remove(key: string, storageType: string): Promise 24 | } 25 | 26 | export const NativeStorageUtils = NativeModulesProvider.PowerAuthStorageUtils; 27 | 28 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth/LiftPowerAuthSdk.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import 18 | #import "PowerAuthObjectRegister.h" 19 | #import 20 | #import 21 | 22 | PowerAuthSDK * LiftPowerAuthSdk(NSString * instanceId, RCTBridge * bridge) 23 | { 24 | PowerAuthSDK * sdk; 25 | PowerAuthObjectRegister * paor = [bridge moduleForName:@"PowerAuthObjectRegister"]; 26 | if (paor) 27 | { 28 | sdk = [paor findObjectWithId:instanceId expectedClass:[PowerAuthSDK class]]; 29 | } 30 | return sdk; 31 | } 32 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth/PowerAuthData.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import "Utilities.h" 18 | 19 | /** 20 | Object that wrap NSData to JavaScript. 21 | */ 22 | @interface PowerAuthData : NSObject 23 | 24 | /// Initialize object with NSData object. 25 | /// - Parameters: 26 | /// - data: Data object to manage from JavaScript 27 | /// - cleanup: Do data cleanup if possible. 28 | - (nonnull instancetype) initWithData:(nonnull NSData*)data cleanup:(BOOL)cleanup; 29 | 30 | /// Contains managed data object. 31 | @property (nonatomic, readonly, strong, nonnull) NSData * data; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /docs/_Sidebar.md: -------------------------------------------------------------------------------- 1 | **Integration Tutorials** 2 | 3 | - [Installation](Installation.md) 4 | - [Configuration](Configuration.md) 5 | - [Device Activation](Device-Activation.md) 6 | - [Requesting Device Activation Status](Requesting-Device-Activation-Status.md) 7 | - [Data Signing](Data-Signing.md) 8 | - [Password Management](Password-Management.md) 9 | - [Working with passwords securely](Secure-Password.md) 10 | - [Biometry Setup](Biometry-Setup.md) 11 | - [Device Activation Removal](Device-Activation-Removal.md) 12 | - [End-To-End Encryption](End-To-End-Encryption.md) 13 | - [Secure Vault](Secure-Vault.md) 14 | - [Recovery Codes](Recovery-Codes.md) 15 | - [Token Based Authentication](Token-Based-Authentication.md) 16 | 17 | **Additional Topics** 18 | 19 | - [Troubleshooting](Troubleshooting.md) 20 | - [Migration Instructions](Migration-Instructions.md) 21 | - [Sample Integration](Sample-Integration.md) 22 | - [User Info](User-Info.md) 23 | - [Time Synchronization](Time-Synchronization.md) 24 | - [Crypto Utilities](Crypto-Utilities.md) 25 | - [Storage Utilities](Storage-Utilities.md) 26 | - [Accessing the Native PowerAuthSDK](Accessing-Native-PowerAuthSDK.md) 27 | - [Additional Utilities](Additional-Utilities.md) 28 | 29 | **Other** 30 | - [Changelog](Changelog.md) -------------------------------------------------------------------------------- /testapp/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | ios/.xcode.env.local 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | *.hprof 33 | .cxx/ 34 | *.keystore 35 | !debug.keystore 36 | 37 | # node.js 38 | # 39 | node_modules/ 40 | npm-debug.log 41 | yarn-error.log 42 | 43 | # fastlane 44 | # 45 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 46 | # screenshots whenever they are needed. 47 | # For more information about the recommended setup visit: 48 | # https://docs.fastlane.tools/best-practices/source-control/ 49 | 50 | **/fastlane/report.xml 51 | **/fastlane/Preview.html 52 | **/fastlane/screenshots 53 | **/fastlane/test_output 54 | 55 | # Bundle artifact 56 | *.jsbundle 57 | 58 | # Ruby / CocoaPods 59 | /ios/Pods/ 60 | /vendor/bundle/ 61 | 62 | # Temporary files created by Metro to check the health of the file watcher 63 | .metro-health-check* 64 | 65 | # Config 66 | .env 67 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/model/PowerAuthNativeObject.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { NativeModulesProvider } from "../internal/NativeModulesProvider" 18 | 19 | /** 20 | * Low level interface provided by native PowerAuthObjectRegister. 21 | */ 22 | export interface PowerAuthNativeObject { 23 | /** 24 | * Test whether underlying native object register still contains object with given ID. 25 | * @param objectId Object identifier to test. 26 | */ 27 | isValidNativeObject(objectId: string): Promise 28 | } 29 | 30 | export const PowerAuthNativeObject = NativeModulesProvider.PowerAuthObjectRegister as PowerAuthNativeObject -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/model/PowerAuthEncryptionHttpHeader.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * Object representing encryption HTTP header with data required for PowerAuth End-To-End encrypted request. 19 | */ 20 | export interface PowerAuthEncryptionHttpHeader { 21 | /** 22 | * Property representing PowerAuth HTTP Authorization Header. The current implementation 23 | * contains value "X-PowerAuth-Encryption" for standard encryption. 24 | */ 25 | readonly key: string 26 | /** 27 | * Computed value of the PowerAuth HTTP Encryption Header, to be used in HTTP request "as is". 28 | */ 29 | readonly value: string 30 | } -------------------------------------------------------------------------------- /testapp/_tests/testbed/CustomMonitor.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2022 Wultra s.r.o. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | import { TestEvent, TestMonitor } from "../../src/testbed/TestMonitor" 18 | import { TestProgress } from "../../src/testbed/TestProgress" 19 | 20 | export class CustomMonitor implements TestMonitor { 21 | 22 | eventList: TestEvent[] = [] 23 | suiteProgress: TestProgress | undefined 24 | testsProgress: TestProgress | undefined 25 | 26 | reportEvent(event: TestEvent): void { 27 | this.eventList.push(event) 28 | } 29 | reportTestSuitesProgress(progress: TestProgress): void { 30 | this.suiteProgress = progress 31 | } 32 | reportAllTestsProgress(progress: TestProgress): void { 33 | this.testsProgress = progress 34 | } 35 | } -------------------------------------------------------------------------------- /docs/Troubleshooting.md: -------------------------------------------------------------------------------- 1 | # Troubleshooting 2 | 3 | ## Upgrading SDK 4 | 5 | If you upgraded SDK to a newer major or minor version and encounter some problems, then please follow the [Migration Instructions](Migration-Instructions.md) first. 6 | 7 | ## Enable debug log 8 | 9 | In case you encounter a problem with this library, then try to turn-on a detailed debug log to provide a more information for the library developers: 10 | 11 | ```javascript 12 | // Enable debug log with failed call to native function. 13 | PowerAuthDebug.traceNativeCodeCalls(true); 14 | // Trace all calls to native library 15 | PowerAuthDebug.traceNativeCodeCalls(true, true); 16 | ``` 17 | 18 | 19 | The `PowerAuthDebug` class is effective only when `isEnabled` is `true`. We don't want to log the sensitive information to the console in the production application. 20 | 21 | 22 | ## Dumping native objects 23 | 24 | If `PowerAuthDebug.isEnabled` is turned on, then you can dump information about all native objects allocated and used by PowerAuth Mobile JS SDK: 25 | 26 | ```javascript 27 | // Dump all objects 28 | await PowerAuthDebug.dumpNativeObjects(); 29 | // Dump objects related to PowerAuth instance 30 | await PowerAuthDebug.dumpNativeObjects(powerAuth.instanceId); 31 | ``` 32 | 33 | ## Read Next 34 | 35 | - [Migration Instructions](Migration-Instructions.md) -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/model/PowerAuthAuthorizationHttpHeader.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * Object representing authorization HTTP header with the PowerAuth-Authorization or PowerAuth-Token signature. 19 | */ 20 | export interface PowerAuthAuthorizationHttpHeader { 21 | /** 22 | * Property representing PowerAuth HTTP Authorization Header. The current implementation 23 | * contains value "X-PowerAuth-Authorization" for standard authorization and "X-PowerAuth-Token" for 24 | * token-based authorization. 25 | */ 26 | key: string 27 | /** 28 | * Computed value of the PowerAuth HTTP Authorization Header, to be used in HTTP requests "as is". 29 | */ 30 | value: string 31 | } -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/cdv/util/ReadableMap.kt: -------------------------------------------------------------------------------- 1 | package com.wultra.android.powerauth.cdv.util 2 | 3 | import java.util.HashMap 4 | import kotlin.collections.Iterator 5 | import kotlin.collections.Map 6 | 7 | /** 8 | * Interface for a map that allows typed access to its members. Used to pass parameters from JS to 9 | * Kotlin. 10 | */ 11 | public interface ReadableMap { 12 | public val entryIterator: Iterator> 13 | 14 | public fun getArray(name: String): ReadableArray? 15 | 16 | public fun getBoolean(name: String): Boolean 17 | 18 | public fun getDouble(name: String): Double 19 | 20 | public fun getDynamic(name: String): Dynamic 21 | 22 | public fun getInt(name: String): Int 23 | 24 | public fun getLong(name: String): Long 25 | 26 | public fun getMap(name: String): ReadableMap? 27 | 28 | public fun getString(name: String): String? 29 | 30 | public fun getType(name: String): ReadableType 31 | 32 | public fun hasKey(name: String): Boolean 33 | 34 | public fun isNull(name: String): Boolean 35 | 36 | public fun keySetIterator(): ReadableMapKeySetIterator 37 | 38 | public fun toHashMap(): HashMap 39 | } 40 | 41 | public interface ReadableMapKeySetIterator { 42 | public fun hasNextKey(): Boolean 43 | 44 | public fun nextKey(): String 45 | } 46 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth/PowerAuthData.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import "PowerAuthData.h" 18 | #import "Utilities.h" 19 | 20 | @implementation PowerAuthData 21 | { 22 | BOOL _cleanup; 23 | } 24 | 25 | - (instancetype) initWithData:(nonnull NSData*)data 26 | cleanup:(BOOL)cleanup 27 | { 28 | self = [super init]; 29 | if (self) { 30 | _data = data; 31 | _cleanup = cleanup; 32 | } 33 | return self; 34 | } 35 | 36 | - (void) dealloc 37 | { 38 | if (_cleanup) { 39 | NSMutableData * mutable = CAST_TO(_data, NSMutableData); 40 | if (mutable) { 41 | memset(mutable.mutableBytes, 0, mutable.length); 42 | } 43 | } 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /testapp/src/testbed/TestInteraction.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2022 Wultra s.r.o. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | import { TestContext } from "./TestSuite" 18 | 19 | export enum UserPromptDuration { 20 | QUICK, 21 | SHORT, 22 | LONG 23 | } 24 | 25 | export interface UserInteraction { 26 | showPrompt(context: TestContext, message: string, duration: UserPromptDuration): Promise 27 | sleepWithProgress(context: TestContext, durationMs: number): Promise 28 | } 29 | 30 | export interface TestInteraction extends UserInteraction { 31 | reportWarning(context: TestContext, message: string): void 32 | reportInfo(context: TestContext, message: string): void 33 | reportSkip(context: TestContext, reason: string): void 34 | reportFailure(context: TestContext, reason: string): void 35 | } -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/bridge/Aliases.kt: -------------------------------------------------------------------------------- 1 | package com.wultra.android.powerauth.bridge 2 | 3 | import android.content.Context 4 | import android.content.pm.ApplicationInfo 5 | 6 | 7 | 8 | // point to React bridge 9 | typealias Arguments = com.wultra.android.powerauth.cdv.util.Arguments 10 | typealias Dynamic = com.wultra.android.powerauth.cdv.util.Dynamic 11 | typealias Promise = com.wultra.android.powerauth.cdv.util.Promise 12 | typealias ReadableArray = com.wultra.android.powerauth.cdv.util.ReadableArray 13 | typealias ReadableMap = com.wultra.android.powerauth.cdv.util.ReadableMap 14 | typealias ReadableType = com.wultra.android.powerauth.cdv.util.ReadableType 15 | typealias WritableArray = com.wultra.android.powerauth.cdv.util.WritableArray 16 | typealias WritableMap = com.wultra.android.powerauth.cdv.util.WritableMap 17 | 18 | 19 | // bridge to concrete platform implementation 20 | typealias BuildConfig = com.wultra.android.powerauth.bridge.DummyBuildConfig 21 | typealias PwBuildConfig = com.wultra.android.powerauth.bridge.CordovaPwBuildConfig 22 | 23 | object DummyBuildConfig { 24 | val DEBUG = false // unused in the lib 25 | } 26 | 27 | object CordovaPwBuildConfig { 28 | fun isDebuggable(context: Context): Boolean { 29 | return 0 != context.applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE 30 | } 31 | } -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/cdv/util/WritableNativeArray.kt: -------------------------------------------------------------------------------- 1 | package com.wultra.android.powerauth.cdv.util 2 | 3 | 4 | /** 5 | * Cordova implementation of writable array. 6 | * 7 | * It's not in fact native, it's based on Kotlin collections. 8 | */ 9 | class WritableNativeArray(list: List = emptyList()) : ReadableNativeArray(list), WritableArray { 10 | 11 | override fun pushArray(array: ReadableArray?) { 12 | if (!(array == null || array is ReadableNativeArray)) { 13 | throw IllegalArgumentException("Illegal type provided") 14 | } 15 | _mutableList.add(array as ReadableNativeArray?) 16 | } 17 | 18 | override fun pushBoolean(value: Boolean) { 19 | _mutableList.add(value) 20 | } 21 | 22 | override fun pushDouble(value: Double) { 23 | _mutableList.add(value) 24 | } 25 | 26 | override fun pushInt(value: Int) { 27 | _mutableList.add(value) 28 | } 29 | 30 | override fun pushLong(value: Long) { 31 | _mutableList.add(value) 32 | } 33 | 34 | override fun pushMap(map: ReadableMap?) { 35 | _mutableList.add(map as ReadableNativeMap?) 36 | } 37 | 38 | override fun pushNull() { 39 | _mutableList.add(null) 40 | } 41 | 42 | override fun pushString(value: String?) { 43 | _mutableList.add(value) 44 | } 45 | } -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/PowerAuthCryptoUtils.ts: -------------------------------------------------------------------------------- 1 | import {NativeWrapper} from "./internal/NativeWrapper"; 2 | import {NativeCryptoUtils} from "./internal/NativeCryptoUtils"; 3 | 4 | /** 5 | * Typealias for Base64 encoded string. 6 | * This type emphasizes the fact that we expect Base64 encoded string. 7 | */ 8 | export type Base64String = string; 9 | 10 | export class PowerAuthCryptoUtils { 11 | 12 | /** 13 | * Hashes given data using SHA-256 algorithm. 14 | * @param data String data encoded in Base64 format. 15 | * @returns Hashed data in Base64 format 16 | * @throws `PowerAuthErrorCode.WRONG_PARAMETER` if data is not Base64 encoded. 17 | */ 18 | static async hashSha256(data: Base64String): Promise { 19 | try { 20 | return await NativeCryptoUtils.hashSha256(data); 21 | } catch (error) { 22 | throw NativeWrapper.processException(error) 23 | } 24 | } 25 | 26 | /** 27 | * Generates random bytes. 28 | * @param length Number of bytes to generate. 29 | * @returns Random bytes in Base64 format. 30 | */ 31 | static async randomBytes(length: number): Promise { 32 | try { 33 | return await NativeCryptoUtils.randomBytes(length); 34 | } catch (error) { 35 | throw NativeWrapper.processException(error) 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/internal/NativePassphraseMeter.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { PinTestResult } from '../index' 18 | import { NativeModulesProvider } from './NativeModulesProvider'; 19 | import { PowerAuthRawPasswordType } from '../model/PowerAuthNativeTypes'; 20 | /** 21 | * Password interface implemented in the native code. 22 | */ 23 | export interface PowerAuthPassphraseMeterIfc { 24 | /** 25 | * Test strength of PIN. 26 | * @param pin PIN to test. 27 | * @returns `PinTestResult` object. 28 | * @throws `PowerAuthErrorCode.WRONG_PARAM` if PIN contains other characters than digits or length is less than 4. 29 | */ 30 | testPin(pin: PowerAuthRawPasswordType): Promise 31 | } 32 | 33 | export const NativePassphraseMeter = NativeModulesProvider.PowerAuthPassphraseMeter; -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/internal/NativeModulesProvider.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { NativeModules } from "react-native"; 18 | import { NativeModulesProviderIfc } from "./NativeModulesProviderIfc"; 19 | import { NativePowerAuth } from "./NativePowerAuth"; 20 | 21 | class Provider implements NativeModulesProviderIfc { 22 | PowerAuthObjectRegister = NativeModules.PowerAuthObjectRegister; 23 | PowerAuthEncryptor = NativeModules.PowerAuthEncryptor 24 | PowerAuthPassphraseMeter = NativeModules.PowerAuthPassphraseMeter 25 | PowerAuthPassword = NativeModules.PowerAuthPassword 26 | PowerAuthCryptoUtils = NativeModules.PowerAuthCryptoUtils 27 | PowerAuthStorageUtils = NativeModules.PowerAuthStorageUtils 28 | PowerAuth = new NativePowerAuth() 29 | } 30 | 31 | export const NativeModulesProvider = new Provider() as NativeModulesProviderIfc -------------------------------------------------------------------------------- /testapp/_tests/PowerAuth_KDF.test.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2022 Wultra s.r.o. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | import { expect } from "../src/testbed"; 18 | import { TestWithActivation } from "./helpers/TestWithActivation"; 19 | 20 | export class PowerAuth_KDFTests extends TestWithActivation { 21 | async testFetchEncryptionKey() { 22 | const key1a = await this.sdk.fetchEncryptionKey(this.credentials.knowledge, 1000) 23 | expect(key1a).toBeDefined() 24 | const key1b = await this.sdk.fetchEncryptionKey(this.credentials.knowledge, 1000) 25 | expect(key1b).toBe(key1a) 26 | 27 | const key2a = await this.sdk.fetchEncryptionKey(this.credentials.knowledge, 1001) 28 | expect(key2a).toBeDefined() 29 | const key2b = await this.sdk.fetchEncryptionKey(this.credentials.knowledge, 1001) 30 | expect(key2a).toBe(key2b) 31 | 32 | expect(key1a).toNotBe(key2a) 33 | } 34 | } -------------------------------------------------------------------------------- /testapp/_tests/testbed/CustomInteraction.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2022 Wultra s.r.o. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | import { TestContext, UserInteraction, UserPromptDuration } from "../../src/testbed"; 18 | 19 | export interface PromptWithDuration { 20 | prompt: string 21 | duration: UserPromptDuration | "CUSTOM" 22 | } 23 | 24 | export class CustomInteraction implements UserInteraction { 25 | promptList: PromptWithDuration[] = [] 26 | 27 | reset() { 28 | this.promptList = [] 29 | } 30 | 31 | showPrompt(context: TestContext, message: string, duration: UserPromptDuration): Promise { 32 | this.promptList.push({prompt: message, duration: duration}) 33 | return Promise.resolve() 34 | } 35 | 36 | sleepWithProgress(context: TestContext, durationMs: number): Promise { 37 | this.promptList.push({prompt: `Sleep for ${durationMs} ms`, duration: "CUSTOM" }) 38 | return Promise.resolve() 39 | } 40 | } -------------------------------------------------------------------------------- /docs/Secure-Vault.md: -------------------------------------------------------------------------------- 1 | # Secure Vault 2 | 3 | PowerAuth SDK has basic support for an encrypted secure vault. At this moment, the only supported method allows your application to establish an encryption / decryption key with a given index. The index represents a "key number" - your identifier for a given key. Different business logic purposes should have encryption keys with a different index value. 4 | 5 | On a server-side, all secure vault-related work is concentrated in a `/pa/v3/vault/unlock` endpoint of PowerAuth Standard RESTful API. In order to receive data from this response, the call must be authenticated with at least 2FA (using password or PIN). 6 | 7 | 8 | The secure vault mechanism does not support biometry by default. Use PIN code or password-based authentication for unlocking the secure vault, or ask your server developers to enable biometry for vault unlock call by configuring PowerAuth Server instance. 9 | 10 | 11 | ## Obtaining Encryption Key 12 | 13 | In order to obtain an encryption key with a given index, use the following code: 14 | 15 | ```javascript 16 | // 2FA signature. It uses device-related key and user PIN code. 17 | const auth = PowerAuthAuthentication.password("1234"); 18 | 19 | // Select custom key index 20 | const index = 1000; 21 | 22 | try { 23 | // Fetch encryption key with given index 24 | const r = await powerAuth.fetchEncryptionKey(auth, index); 25 | // ... use encryption key to encrypt or decrypt data 26 | } catch (e) { 27 | // Report error 28 | } 29 | ``` 30 | 31 | ## Read Next 32 | 33 | - [Recovery Codes](Recovery-Codes.md) 34 | -------------------------------------------------------------------------------- /.deploy/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-native-powerauth-mobile-sdk", 3 | "title": "PowerAuth SDK for React Native Mobile Apps", 4 | "version": "%DEPLOY_VERSION%", 5 | "description": "Wultra PowerAuth Mobile SDK React Native component for iOS and Android", 6 | "main": "lib/index.js", 7 | "types": "lib/index.d.ts", 8 | "source": "src/index", 9 | "files": [ 10 | "README.md", 11 | "android/src/main/AndroidManifest.xml", 12 | "android/src/main/java/com/wultra/android/powerauth/reactnative/*.java", 13 | "android/build.gradle", 14 | "lib/*.*", 15 | "lib/internal/*.js", 16 | "lib/model/*.*", 17 | "lib/debug/*.*", 18 | "ios/PowerAuth.xcodeproj/project.pbxproj", 19 | "ios/PowerAuth/*.m", 20 | "ios/PowerAuth/*.c", 21 | "ios/PowerAuth/*.h", 22 | "react-native-powerauth-mobile-sdk.podspec" 23 | ], 24 | "scripts": { 25 | "prepare": "tsc" 26 | }, 27 | "homepage": "https://www.wultra.com/mobile-security-suite", 28 | "repository": { 29 | "type": "git", 30 | "url": "https://github.com/wultra/react-native-powerauth-mobile-sdk.git" 31 | }, 32 | "keywords": [ 33 | "react-native", 34 | "powerauth", 35 | "security" 36 | ], 37 | "author": { 38 | "name": "Wultra s.r.o.", 39 | "email": "support@wultra.com" 40 | }, 41 | "license": "Apache 2.0", 42 | "licenseFilename": "LICENSE", 43 | "readmeFilename": "README.md", 44 | "dependencies": { 45 | "node-fetch": ">=2.6.1" 46 | }, 47 | "peerDependencies": { 48 | "react-native": "*" 49 | }, 50 | "devDependencies": { 51 | "lodash": "^4.17.21", 52 | "react-native": "^0.73.4" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/model/PowerAuthActivationStatus.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { PowerAuthActivationState } from './PowerAuthActivationState'; 18 | 19 | /** 20 | * The `PowerAuthActivationStatus` object represents complete status of the activation. 21 | */ 22 | export interface PowerAuthActivationStatus { 23 | /** 24 | * State of the activation. 25 | */ 26 | state: PowerAuthActivationState 27 | /** 28 | * Number of failed authentication attempts in a row. 29 | */ 30 | failCount: number 31 | /** 32 | * Maximum number of allowed failed authentication attempts in a row. 33 | */ 34 | maxFailCount: number 35 | /** 36 | * Contains `(maxFailCount - failCount)` if state is `ACTIVE`, otherwise 0. 37 | */ 38 | remainingAttempts: number 39 | /** 40 | * Contains custom object returned from the server. The value is optional and PowerAuth Application Server must support this custom object. 41 | */ 42 | customObject?: any 43 | } 44 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth/LiftPowerAuthSdk.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2024 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import 18 | #import 19 | #import 20 | 21 | #ifdef __cplusplus 22 | // C++ 23 | #define PA_EXTERN_C extern "C" 24 | #define PA_EXTERN_C_BEGIN extern "C" { 25 | #define PA_EXTERN_C_END } 26 | #else 27 | // C 28 | #define PA_EXTERN_C extern 29 | #define PA_EXTERN_C_BEGIN 30 | #define PA_EXTERN_C_END 31 | #endif 32 | 33 | /// Function that lifts PowerAuthSDK instance from the React-Native module if present (configured). If the object is not available, returns nil. 34 | /// @param instanceId Id of the instance that was configured from the JS/TS layer. 35 | /// @param bridge React bridge reference obtained from your ReactNative module or app. 36 | /// @return Native PowerAuthSDK or nil if such instance is not configured. 37 | PA_EXTERN_C PowerAuthSDK * LiftPowerAuthSdk(NSString * instanceId, RCTBridge * bridge); 38 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/model/PowerAuthExternalPendingOperation.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * ### iOS specific 19 | * 20 | * The `PowerAuthExternalPendingOperationType` defines types of operation 21 | * started in another application that share activation data. 22 | */ 23 | export type PowerAuthExternalPendingOperationType = "ACTIVATION" | "PROTOCOL_UPGRADE" 24 | 25 | /** 26 | * ### iOS specific 27 | * 28 | * The `PowerAuthExternalPendingOperation` interface contains data that can identify an external 29 | * application that started the critical operation. 30 | */ 31 | export interface PowerAuthExternalPendingOperation { 32 | /** 33 | * Type of operation running in another application. 34 | */ 35 | externalOperationType: PowerAuthExternalPendingOperationType 36 | /** 37 | * Identifier of external application that started the operation. This is the same identifier 38 | * you provided to `PowerAuthSharingConfiguration` during the PowerAuth initialization. 39 | */ 40 | externalApplicationId: string 41 | } -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/model/PowerAuthActivationState.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * The `PowerAuthActivationState` enum defines all possible states of activation. 19 | * The state is a part of information received together with the rest 20 | * of the `PowerAuthActivationStatus` object. 21 | */ 22 | export enum PowerAuthActivationState { 23 | /** 24 | * The activation is just created. 25 | */ 26 | CREATED = "CREATED", 27 | /** 28 | * The activation is not completed yet on the server. 29 | */ 30 | PENDING_COMMIT = "PENDING_COMMIT", 31 | /** 32 | * The shared secure context is valid and active. 33 | */ 34 | ACTIVE = "ACTIVE", 35 | /** 36 | * The activation is blocked. 37 | */ 38 | BLOCKED = "BLOCKED", 39 | /** 40 | * The activation doesn't exist anymore. 41 | */ 42 | REMOVED = "REMOVED", 43 | /** 44 | * The activation is technically blocked. You cannot use it anymore 45 | * for the signature calculations. 46 | */ 47 | DEADLOCK = "DEADLOCK" 48 | } -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/internal/NativeModulesProviderIfc.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { NativeObjectRegisterIfc } from "../debug/NativeObjectRegisterIfc"; 18 | import { PowerAuthEncryptorIfc } from "./NativeEncryptor"; 19 | import { PowerAuthNativeObject } from "../model/PowerAuthNativeObject"; 20 | import { PowerAuthPassphraseMeterIfc } from "./NativePassphraseMeter"; 21 | import { PowerAuthPasswordIfc } from "./NativePassword"; 22 | import { NativePowerAuthIfc } from "./NativePowerAuthIfc"; 23 | import { PowerAuthCryptoUtilsIfc } from "./NativeCryptoUtils"; 24 | import { PowerAuthStorageUtilsIfc } from "./NativeStorageUtils"; 25 | 26 | 27 | export interface NativeModulesProviderIfc { 28 | PowerAuthObjectRegister: NativeObjectRegisterIfc & PowerAuthNativeObject; 29 | PowerAuthEncryptor: PowerAuthEncryptorIfc; 30 | PowerAuthPassphraseMeter: PowerAuthPassphraseMeterIfc; 31 | PowerAuthPassword: PowerAuthPasswordIfc; 32 | PowerAuthCryptoUtils: PowerAuthCryptoUtilsIfc; 33 | PowerAuthStorageUtils: PowerAuthStorageUtilsIfc; 34 | PowerAuth: NativePowerAuthIfc; 35 | } -------------------------------------------------------------------------------- /docs/Installation.md: -------------------------------------------------------------------------------- 1 | # Installation 2 | 3 | - [Installation for React-Native](#react-native-installation) 4 | - [Installation for Cordova](#cordova-installation) 5 | 6 | ## React-Native Installation 7 | 8 | ### Supported Platforms 9 | 10 | The library is available for the following __React Native (0.64.1+)__ platforms: 11 | 12 | - __Android 5.0 (API 21)__ and newer 13 | - __iOS 13.4__ and newer 14 | 15 | ### How To Install 16 | 17 | #### 1. Install the package via npm 18 | ```sh 19 | npm i react-native-powerauth-mobile-sdk --save 20 | ``` 21 | 22 | #### 2. Install pods for iOS 23 | 24 | To make integration working with iOS, don't forget to install Pods: 25 | 26 | ```sh 27 | cd ios 28 | pod install 29 | ``` 30 | 31 | #### 3. Import PowerAuth in your js/ts files 32 | 33 | ```typescript 34 | import { PowerAuth, PowerAuthAuthentication, PowerAuthError } from 'react-native-powerauth-mobile-sdk'; 35 | ``` 36 | 37 | ## Cordova Installation 38 | 39 | ### Supported Platforms 40 | 41 | The library is available for the following __Apache Cordova (>=12.0.0)__ platforms: 42 | 43 | - __Android 7.0 (API 24)__ and newer (cordova-android version >=12.0.0) 44 | - __iOS 11.0__ and newer (cordova-ios version >=7.0.0) 45 | 46 | ### How To Install 47 | 48 | #### 1. Install the plugin via the cordova plugin installer 49 | ```sh 50 | cordova plugin add cordova-powerauth-mobile-sdk 51 | ``` 52 | 53 | #### 2. Install pods for iOS (if needed) 54 | 55 | To make integration working with iOS, you might need to install Pods: 56 | 57 | ```sh 58 | cd platforms/ios 59 | pod install 60 | ``` 61 | 62 | #### 3. Start using PowerAuth classes 63 | 64 | ```typescript 65 | const powerAuth = new PowerAuth("my-test-instance"); 66 | ``` 67 | 68 | ## Read Next 69 | 70 | - [Configuration](./Configuration.md) 71 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth/Constants.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import "Utilities.h" 18 | 19 | /// Time interval in milliseconds to keep pre-authorized biometric 20 | /// key in memory. 21 | #define BIOMETRY_KEY_KEEP_ALIVE_TIME 10000 22 | 23 | /// Time interval in milliseconds to keep password object valid 24 | /// in memory. 25 | #define PASSWORD_KEY_KEEP_ALIVE_TIME (5 * 60 * 1000) 26 | 27 | /// Time interval in milliseconds to keep encryptor object alive in memory 28 | #define ENCRYPTOR_KEEP_ALIVE_TIME (5 * 60 * 1000) 29 | /// Time interval in milliseconds to keep decryptor object alive in memory 30 | #define DECRYPTOR_KEEP_ALIVE_TIME (5 * 60 * 1000) 31 | 32 | /// Upper limit for Unicode Code Point 33 | #define CODEPOINT_MAX 0x10FFFF 34 | 35 | /// Default period in milliseconds for automatic objects cleanup job. 36 | #define CLEANUP_PERIOD_DEFAULT 10000 37 | /// Minimum allowed period for automatic objects cleanup job. 38 | #define CLEANUP_PERIOD_MIN 100 39 | /// Maximum allowed period for automatic objects cleanup job. 40 | #define CLEANUP_PERIOD_MAX 60000 41 | -------------------------------------------------------------------------------- /testapp/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "testapp", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "android": "yarn dlx react-native run-android", 7 | "ios": "yarn dlx react-native run-ios", 8 | "start": "yarn dlx react-native start", 9 | "pods": "(cd ios && yarn dlx pod-install --non-interactive)", 10 | "buildAndroid": "(cd android && ./gradlew assemble)", 11 | "buildIos": "yarn pods && (cd ios && xcodebuild archive -workspace testapp.xcworkspace -scheme testapp -sdk iphoneos CODE_SIGN_IDENTITY=\"\" CODE_SIGNING_ALLOWED=NO)", 12 | "freshAndroid": "yarn android", 13 | "freshIos": "yarn pods && yarn ios", 14 | "lint": "eslint .", 15 | "format": "prettier -w ." 16 | }, 17 | "dependencies": { 18 | "react": "19.0.0", 19 | "react-native": "0.78.0", 20 | "react-native-config": "1.5.5", 21 | "react-native-powerauth-mobile-sdk": "workspace:*" 22 | }, 23 | "devDependencies": { 24 | "@babel/core": "^7.25.2", 25 | "@babel/preset-env": "^7.25.3", 26 | "@babel/runtime": "^7.25.0", 27 | "@react-native-community/cli": "15.0.1", 28 | "@react-native-community/cli-platform-android": "15.0.1", 29 | "@react-native-community/cli-platform-ios": "15.0.1", 30 | "@react-native/babel-preset": "0.78.0", 31 | "@react-native/eslint-config": "0.78.0", 32 | "@react-native/metro-config": "0.78.0", 33 | "@react-native/typescript-config": "0.78.0", 34 | "@types/react": "^19.0.0", 35 | "@types/react-test-renderer": "^19.0.0", 36 | "@typescript-eslint/eslint-plugin": "^7.0.0", 37 | "@typescript-eslint/parser": "^7.0.0", 38 | "eslint": "^8.57.0", 39 | "prettier": "^3.3.3", 40 | "react-test-renderer": "19.0.0", 41 | "typescript": "5.0.4" 42 | }, 43 | "engines": { 44 | "node": ">=18" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cordova-powerauth-mobile-sdk", 3 | "title": "PowerAuth Mobile JS SDK for Cordova Mobile Apps", 4 | "version": "", 5 | "description": "Wultra PowerAuth Mobile JS SDK for Cordova (iOS and Android)", 6 | "types": "typings.d.ts", 7 | "files": [ 8 | "README.md", 9 | "android/src/main/AndroidManifest.xml", 10 | "android/src/main/java/com/wultra/android/powerauth/cdv/*", 11 | "android/src/main/java/com/wultra/android/powerauth/bridge/*", 12 | "android/src/main/java/com/wultra/android/powerauth/js/*", 13 | "android/build.gradle", 14 | "lib/*", 15 | "ios/PowerAuth.xcodeproj/project.pbxproj", 16 | "ios/PowerAuth/Info.plist", 17 | "ios/PowerAuth/*.m", 18 | "ios/PowerAuth/*.mm", 19 | "ios/PowerAuth/*.c", 20 | "ios/PowerAuth/*.h", 21 | "plugin.xml", 22 | "typings.d.ts" 23 | ], 24 | "homepage": "https://www.wultra.com/mobile-security-suite", 25 | "repository": { 26 | "type": "git", 27 | "url": "https://github.com/wultra/react-native-powerauth-mobile-sdk.git" 28 | }, 29 | "keywords": [ 30 | "cordova", 31 | "powerauth", 32 | "security" 33 | ], 34 | "author": { 35 | "name": "Wultra s.r.o.", 36 | "email": "support@wultra.com" 37 | }, 38 | "license": "Apache 2.0", 39 | "licenseFilename": "LICENSE", 40 | "readmeFilename": "README.md", 41 | "scripts": { 42 | "cdv": "gulp cdv" 43 | }, 44 | "devDependencies": { 45 | "esbuild": "^0.25.12", 46 | "gulp": "^5.0.0", 47 | "gulp-concat": "^2.6.1", 48 | "gulp-filter": "^9.0.1", 49 | "gulp-replace": "^1.1.4", 50 | "gulp-strip-import-export": "^1.0.0", 51 | "gulp-typescript": "^6.0.0-alpha.1", 52 | "rimraf": "^6.0.1", 53 | "typescript": "^5.4.0" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /testapp/src/testbed/private/ObjectHelper.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2022 Wultra s.r.o. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | /** 18 | * Populate all method names defined in the provided object. 19 | * @param obj Input object. 20 | * @returns List of method names implemented in the object. 21 | */ 22 | export function getAllObjectMethods(obj: any) { 23 | let props: string[] = []; 24 | let parent: any; 25 | // Walk over the prototype chain, ignore `Object` methods (e.g. there's no parent prototype) 26 | while (obj && (parent = Object.getPrototypeOf(obj))) { 27 | // get all descriptors at once 28 | const allDescs = Object.getOwnPropertyDescriptors(obj); 29 | for (const prop in allDescs) { 30 | // Functions are writable unlike the getters. If we don't test for `writable`, then the next `obj[prop]` 31 | // statement will access the value of property via the getter function. In other words, it call the 32 | // getter function and that's not we want. 33 | if (allDescs[prop].writable === true && typeof obj[prop] === 'function' && prop !== 'constructor') { 34 | props.push(prop); 35 | } 36 | } 37 | obj = parent; 38 | } 39 | return props; 40 | } 41 | -------------------------------------------------------------------------------- /testapp-cordova/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | PowerAuthTest 4 | PowerAuth tests Cordova App 5 | 6 | Wultra 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /docs/Crypto-Utilities.md: -------------------------------------------------------------------------------- 1 | # Crypto Utilities 2 | 3 | The PowerAuth Mobile JS SDK offers additional crypto functions. These utilities are available through the `PowerAuthCryptoUtils` class. 4 | 5 | ## Available Methods 6 | 7 | ### hashSha256(data: string) 8 | 9 | Calculates SHA256 hash of a parameter encoded as Base64 string. 10 | 11 | **Usage:** 12 | 13 | ```typescript 14 | import { PowerAuthCryptoUtils } from 'react-native-powerauth-mobile-sdk'; 15 | 16 | async function hashSha256(data: string) { 17 | try { 18 | const base64 = btoa(unescape(encodeURIComponent(data))); 19 | const hash = await PowerAuthCryptoUtils.hashSha256(base64); 20 | // use hash 21 | } catch (error) { 22 | console.error('Failed to calculate SHA256 hash:', error); 23 | } 24 | } 25 | ``` 26 | 27 | **Response:** 28 | The method returns a Base64 encoded string with SHA256 hash of input parameter. 29 | 30 | ### randomBytes(length: number) 31 | 32 | Returns a random byte array of specified length encoded as Base64 string. 33 | 34 | **Usage:** 35 | 36 | ```typescript 37 | import { PowerAuthCryptoUtils } from 'react-native-powerauth-mobile-sdk'; 38 | 39 | async function randomBytes(length: number) { 40 | try { 41 | const randomBase64 = await PowerAuthCryptoUtils.randomBytes(length); 42 | const randomBytes = Uint8Array.from(atob(randomBase64), c => c.charCodeAt(0)); 43 | // use random bytes 44 | } catch (error) { 45 | console.error('Failed to get random bytes:', error); 46 | } 47 | } 48 | ``` 49 | 50 | **Response:** 51 | 52 | The method returns random bytes array encoded as Base64 string. In order to use the bytes, you need to convert the Base64 string to Uint8Array. (see provided sample code) 53 | 54 | ## Read Next 55 | 56 | - [Accessing the Native PowerAuthSDK](Accessing-Native-PowerAuthSDK.md) 57 | -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/cdv/PowerAuthPassphraseMeterModule.kt: -------------------------------------------------------------------------------- 1 | 2 | package com.wultra.android.powerauth.cordova.plugin 3 | 4 | import com.wultra.android.powerauth.bridge.getDynamic 5 | import com.wultra.android.powerauth.js.PowerAuthPassphraseMeterJsModule 6 | import com.wultra.android.powerauth.cdv.util.Promise 7 | import org.apache.cordova.CallbackContext 8 | import org.apache.cordova.CordovaInterface 9 | import org.apache.cordova.CordovaPlugin 10 | import org.apache.cordova.CordovaWebView 11 | import org.json.JSONArray 12 | import org.json.JSONException 13 | 14 | class PowerAuthPassphraseMeterModule : CordovaPlugin() { 15 | 16 | internal lateinit var powerAuthPassphraseMeterJsModule: PowerAuthPassphraseMeterJsModule 17 | 18 | override fun initialize(cordova: CordovaInterface, webView: CordovaWebView) { 19 | super.initialize(cordova, webView); 20 | val powerAuthPasswordModule = webView.pluginManager.getPlugin("PowerAuthPasswordModule") as PowerAuthPasswordModule 21 | powerAuthPassphraseMeterJsModule = PowerAuthPassphraseMeterJsModule(powerAuthPasswordModule.powerAuthPasswordJsModule) 22 | } 23 | 24 | @Throws(JSONException::class) 25 | override fun execute(action: String, args: JSONArray, callbackContext: CallbackContext): Boolean { 26 | val promise = Promise(callbackContext) 27 | when (action) { 28 | "testPin" -> { 29 | testPin(args, promise) 30 | return true 31 | } 32 | } 33 | return false // Returning false results in a "MethodNotFound" error. 34 | } 35 | 36 | private fun testPin(args: JSONArray, promise: Promise) { 37 | val password = args.getDynamic(0) 38 | powerAuthPassphraseMeterJsModule.testPin(password, promise); 39 | } 40 | } -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/cdv/util/NativeDynamic.kt: -------------------------------------------------------------------------------- 1 | package com.wultra.android.powerauth.cdv.util 2 | 3 | import org.json.JSONArray 4 | import org.json.JSONObject 5 | 6 | 7 | /** 8 | * Implementation of dynamic type. 9 | */ 10 | class NativeDynamic(val data: Any?) : Dynamic { 11 | 12 | private val resolvedType: ReadableType = when (data) { 13 | null -> ReadableType.Null 14 | is Boolean -> ReadableType.Boolean 15 | is Int -> ReadableType.Number 16 | is Double -> ReadableType.Number 17 | is String -> ReadableType.String 18 | is JSONArray -> ReadableType.Array 19 | is JSONObject -> ReadableType.Map 20 | is HashMap<*,*> -> ReadableType.Map 21 | else -> throw IllegalArgumentException("Unknown dynamic type ${data::class}") 22 | } 23 | 24 | override val type: ReadableType 25 | get() = resolvedType 26 | 27 | override val isNull: Boolean 28 | get() = false 29 | 30 | override fun asArray(): ReadableArray { 31 | return ReadableNativeArray(data as JSONArray) 32 | } 33 | 34 | override fun asBoolean(): Boolean { 35 | return data as Boolean 36 | } 37 | 38 | override fun asDouble(): Double { 39 | return data as Double 40 | } 41 | 42 | override fun asInt(): Int { 43 | return data as Int 44 | } 45 | 46 | override fun asMap(): ReadableMap { 47 | if (data is JSONObject) { 48 | return ReadableNativeMap(data) 49 | } else { 50 | @Suppress("UNCHECKED_CAST") 51 | return ReadableNativeMap(data as Map) 52 | } 53 | } 54 | 55 | override fun asString(): String { 56 | return data as String 57 | } 58 | 59 | override fun recycle() { 60 | // no op 61 | } 62 | } -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/react-native-powerauth-mobile-sdk.podspec: -------------------------------------------------------------------------------- 1 | require "json" 2 | 3 | package = JSON.parse(File.read(File.join(__dir__, "package.json"))) 4 | folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32' 5 | 6 | Pod::Spec.new do |s| 7 | s.name = package["name"] 8 | s.version = package["version"] 9 | s.summary = package["description"] 10 | s.homepage = package["homepage"] 11 | s.license = package["license "] 12 | s.authors = { package["author"]["name"] => package["author"]["email"] } 13 | s.platforms = { :ios => "13.4" } 14 | s.source = { :git => "https://github.com/wultra/react-native-powerauth-mobile-sdk.git", :tag => "#{s.version}" } 15 | 16 | s.source_files = "ios/PowerAuth/*.{h,m,c}" 17 | s.requires_arc = true 18 | 19 | s.dependency "PowerAuth2", "~> 1.9.5" 20 | 21 | # For RN > 0.74, this automatically resolves the architecture AND interop layer deps. 22 | if respond_to?(:install_modules_dependencies, true) 23 | install_modules_dependencies(s) 24 | else 25 | s.dependency "React-Core" 26 | 27 | # Don't install the dependencies when we run `pod install` in the old architecture. 28 | if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then 29 | s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1" 30 | s.pod_target_xcconfig = { 31 | "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"", 32 | "OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1", 33 | "CLANG_CXX_LANGUAGE_STANDARD" => "c++17" 34 | } 35 | s.dependency "React-Codegen" 36 | s.dependency "RCT-Folly" 37 | s.dependency "RCTRequired" 38 | s.dependency "RCTTypeSafety" 39 | s.dependency "ReactCommon/turbomodule/core" 40 | end 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /testapp/android/app/src/main/java/com/testapp/MainApplication.kt: -------------------------------------------------------------------------------- 1 | package com.testapp 2 | 3 | import android.app.Application 4 | import com.facebook.react.PackageList 5 | import com.facebook.react.ReactApplication 6 | import com.facebook.react.ReactHost 7 | import com.facebook.react.ReactNativeHost 8 | import com.facebook.react.ReactPackage 9 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load 10 | import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost 11 | import com.facebook.react.defaults.DefaultReactNativeHost 12 | import com.facebook.react.soloader.OpenSourceMergedSoMapping 13 | import com.facebook.soloader.SoLoader 14 | 15 | class MainApplication : Application(), ReactApplication { 16 | 17 | override val reactNativeHost: ReactNativeHost = 18 | object : DefaultReactNativeHost(this) { 19 | override fun getPackages(): List = 20 | PackageList(this).packages.apply { 21 | // Packages that cannot be autolinked yet can be added manually here, for example: 22 | // add(MyReactNativePackage()) 23 | } 24 | 25 | override fun getJSMainModuleName(): String = "index" 26 | 27 | override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG 28 | 29 | override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED 30 | override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED 31 | } 32 | 33 | override val reactHost: ReactHost 34 | get() = getDefaultReactHost(applicationContext, reactNativeHost) 35 | 36 | override fun onCreate() { 37 | super.onCreate() 38 | SoLoader.init(this, OpenSourceMergedSoMapping) 39 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 40 | // If you opted-in for the New Architecture, we load the native entry point for this app. 41 | load() 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/model/PowerAuthCreateActivationResult.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import {PowerAuthRecoveryActivationData} from "./PowerAuthRecoveryActivationData"; 18 | import {PowerAuthUserInfo} from "./PowerAuthUserInfo"; 19 | 20 | /** 21 | * Success object returned by the "createActivation" call. 22 | */ 23 | export interface PowerAuthCreateActivationResult { 24 | /** 25 | * Decimalized fingerprint calculated from device's and server's public keys. 26 | */ 27 | activationFingerprint: string 28 | /** 29 | * If supported and enabled on the server, then the object contains "Recovery Code" and PUK, 30 | * created for this particular activation. Your application should display that value to the user 31 | * and forget the values immediately. You should NEVER store values from the object persistently 32 | * on the device. 33 | */ 34 | activationRecovery?: PowerAuthRecoveryActivationData 35 | /** 36 | * When available, the contents of this object depend on your enrollment server configuration. 37 | */ 38 | customAttributes?: any 39 | 40 | /** 41 | * When available, contains user information claims like name, email, address, etc. 42 | */ 43 | userInfo?: PowerAuthUserInfo 44 | } -------------------------------------------------------------------------------- /testapp/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx512m -XX:MaxMetaspaceSize=256m 13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | 25 | # Use this property to specify which architecture you want to build. 26 | # You can also override it from the CLI using 27 | # ./gradlew -PreactNativeArchitectures=x86_64 28 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 29 | 30 | # Use this property to enable support to the new architecture. 31 | # This will allow you to use TurboModules and the Fabric render in 32 | # your application. You should enable this flag either if you want 33 | # to write custom TurboModules/Fabric components OR use libraries that 34 | # are providing them. 35 | newArchEnabled=true 36 | 37 | # Use this property to enable or disable the Hermes JS engine. 38 | # If set to false, you will be using JSC instead. 39 | hermesEnabled=true 40 | -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/cdv/PowerAuthCryptoUtilsModule.kt: -------------------------------------------------------------------------------- 1 | package com.wultra.android.powerauth.cordova.plugin 2 | 3 | import com.wultra.android.powerauth.cdv.util.Promise 4 | import com.wultra.android.powerauth.js.PowerAuthCryptoUtilsJsModule 5 | import org.apache.cordova.CallbackContext 6 | import org.apache.cordova.CordovaInterface 7 | import org.apache.cordova.CordovaPlugin 8 | import org.apache.cordova.CordovaWebView 9 | import org.json.JSONArray 10 | import org.json.JSONException 11 | 12 | class PowerAuthCryptoUtilsModule : CordovaPlugin() { 13 | 14 | private lateinit var powerAuthCryptoUtilsJsModule: PowerAuthCryptoUtilsJsModule 15 | 16 | override fun initialize(cordova: CordovaInterface, webView: CordovaWebView) { 17 | super.initialize(cordova, webView) 18 | powerAuthCryptoUtilsJsModule = PowerAuthCryptoUtilsJsModule() 19 | } 20 | 21 | @Throws(JSONException::class) 22 | override fun execute(action: String, args: JSONArray, callbackContext: CallbackContext): Boolean { 23 | val promise = Promise(callbackContext) 24 | when (action) { 25 | "hashSha256" -> { 26 | hashSha256(args, promise) 27 | return true 28 | } 29 | "randomBytes" -> { 30 | randomBytes(args, promise) 31 | return true 32 | } 33 | } 34 | return false // Returning false results in a "MethodNotFound" error. 35 | } 36 | 37 | private fun hashSha256(args: JSONArray, promise: Promise) { 38 | val base64Input = args.getString(0) 39 | powerAuthCryptoUtilsJsModule.hashSha256(base64Input, promise) 40 | } 41 | 42 | private fun randomBytes(args: JSONArray, promise: Promise) { 43 | val length = args.getInt(0) 44 | powerAuthCryptoUtilsJsModule.randomBytes(length, promise) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /testapp/ios/testapp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | testapp 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | $(CURRENT_PROJECT_VERSION) 25 | LSRequiresIPhoneOS 26 | 27 | NSAppTransportSecurity 28 | 29 | NSExceptionDomains 30 | 31 | localhost 32 | 33 | NSExceptionAllowsInsecureHTTPLoads 34 | 35 | 36 | 37 | NSFaceIDUsageDescription 38 | Using FaceID for the testing purposes 39 | NSLocationWhenInUseUsageDescription 40 | 41 | UILaunchStoryboardName 42 | LaunchScreen 43 | UIRequiredDeviceCapabilities 44 | 45 | arm64 46 | 47 | UISupportedInterfaceOrientations 48 | 49 | UIInterfaceOrientationPortrait 50 | UIInterfaceOrientationLandscapeLeft 51 | UIInterfaceOrientationLandscapeRight 52 | 53 | UIViewControllerBasedStatusBarAppearance 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/reactnative/PowerAuthReactPackage.java: -------------------------------------------------------------------------------- 1 | package com.wultra.android.powerauth.reactnative; 2 | 3 | import androidx.annotation.NonNull; 4 | 5 | import com.facebook.react.ReactPackage; 6 | import com.facebook.react.bridge.NativeModule; 7 | import com.facebook.react.bridge.ReactApplicationContext; 8 | import com.facebook.react.uimanager.ViewManager; 9 | 10 | import java.util.ArrayList; 11 | import java.util.Collections; 12 | import java.util.List; 13 | 14 | @SuppressWarnings("unused") 15 | public class PowerAuthReactPackage implements ReactPackage { 16 | 17 | @NonNull 18 | @Override 19 | public List createViewManagers(@NonNull ReactApplicationContext reactContext) { 20 | return Collections.emptyList(); 21 | } 22 | 23 | @NonNull 24 | @Override 25 | public List createNativeModules(@NonNull ReactApplicationContext reactContext) { 26 | // Object register 27 | final ObjectRegister objectRegister = new ObjectRegister(reactContext); 28 | // Password module 29 | final PowerAuthPasswordModule passwordModule = new PowerAuthPasswordModule(objectRegister); 30 | // Encryptor module 31 | final PowerAuthEncryptorModule encryptorModule = new PowerAuthEncryptorModule(reactContext, objectRegister); 32 | // Create a list of modules 33 | final List modules = new ArrayList<>(); 34 | modules.add(objectRegister); 35 | modules.add(passwordModule); 36 | modules.add(encryptorModule); 37 | modules.add(new PowerAuthModule(reactContext, objectRegister, passwordModule)); 38 | modules.add(new PowerAuthPassphraseMeterModule(passwordModule)); 39 | modules.add(new PowerAuthCryptoUtilsModule()); 40 | modules.add(new PowerAuthStorageUtilsModule(reactContext)); 41 | return modules; 42 | } 43 | } -------------------------------------------------------------------------------- /testapp/_tests/PowerAuth_TimeSync.test.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025 Wultra s.r.o. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | import { expect } from "../src/testbed"; 18 | import { TestWithActivation } from "./helpers/TestWithActivation"; 19 | 20 | export class PowerAuth_TimeSyncTests extends TestWithActivation { 21 | 22 | async testTimeSynchronization() { 23 | // time is synchronized during the activation 24 | expect(await this.sdk.timeSynchronizationService.isTimeSynchronized()).toBe(true) 25 | 26 | // desynchronize time 27 | expect(await this.sdk.timeSynchronizationService.resetTimeSynchronization()).toSucceed() 28 | expect(await this.sdk.timeSynchronizationService.isTimeSynchronized()).toBe(false) 29 | 30 | // sync again 31 | expect(await this.sdk.timeSynchronizationService.synchronizeTime()).toSucceed() 32 | expect(await this.sdk.timeSynchronizationService.isTimeSynchronized()).toBe(true) 33 | 34 | const timestamp = await this.sdk.timeSynchronizationService.currentTime() 35 | 36 | // just check if actual non-zero values are returned 37 | expect(timestamp).toNotBe(0) 38 | expect(await this.sdk.timeSynchronizationService.localTimeAdjustmentPrecision()).toNotBe(0) 39 | 40 | const date = new Date(timestamp) 41 | expect(date.getTime()).toBe(timestamp) 42 | } 43 | } -------------------------------------------------------------------------------- /testapp/src/testbed/private/ErrorHelper.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2022 Wultra s.r.o. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | import { PowerAuthError } from "react-native-powerauth-mobile-sdk"; 18 | 19 | /** 20 | * Function translate an error object into string. 21 | * @param error Error to describe. 22 | * @param curlyBrackets If true, then the description is wrapped into curly brackets. 23 | * @returns String description from given error. 24 | */ 25 | export function describeError(error: any, curlyBrackets: boolean = false): string { 26 | if (error instanceof PowerAuthError) { 27 | const components: string[] = [] 28 | if (error.code) components.push(error.code) 29 | if (error.message) components.push(error.message) 30 | if (error.errorData) components.push(`data=${JSON.stringify(error.errorData)}`) 31 | if (error.originalException) components.push(`reason=${describeError(error.originalException, true)}`) 32 | const msg = components.join(': ') 33 | return curlyBrackets ? `{ PowerAuthError: ${msg} }` : `PowerAuthError: ${msg}` 34 | } else if (error instanceof Error) { 35 | return curlyBrackets ? `{ ${error.name}: ${error.message} }` : `${error.name}: ${error.message}` 36 | } else if (typeof error === 'string') { 37 | return curlyBrackets ? `{ string: '${error}' }` : `'${error}'` 38 | } 39 | return JSON.stringify(error) 40 | } 41 | -------------------------------------------------------------------------------- /docs/Accessing-Native-PowerAuthSDK.md: -------------------------------------------------------------------------------- 1 | # Accessing the Native PowerAuthSDK 2 | 3 | 4 | __This feature is not available for Cordova.__ 5 | 6 | 7 | If you need to access the native PowerAuthSDK object (created in the JS/TS code) from Java/Kotlin or Objective-C/Swift, you can use the following snippets. 8 | 9 | 10 | Consider consultation with our technical support when accessing the native object. This technique should be used rarely and only for limited purposes as it might lead to unexpected behavior. 11 | 12 | 13 | ## iOS 14 | 15 | To access the native `PowerAuthSDK` object on iOS, use the `LiftPowerAuthSdk` helper method. 16 | 17 | ```objc 18 | #import "LiftPowerAuthSdk.h" 19 | #import 20 | 21 | // The `bridge` (of type `RCTBridge`) availability depends on the place, where you're trying to access the PowerAuthSDK object. 22 | // For example, you can access it in the AppDelegate that implements `RCTAppDelegate` or as property of an `RCTBridgeModule`. 23 | PowerAuthSDK * sdk = LiftPowerAuthSdk(@"myPowerauthInstance", bridge); 24 | if (sdk) { 25 | // Do something with the native instance 26 | } 27 | ``` 28 | 29 | ## Android 30 | 31 | To access the native `PowerAuthSDK` object on Android, use the `PowerAuthUtils.liftPowerAuthSdk` helper method. 32 | 33 | ```java 34 | import com.wultra.android.powerauth.reactnative.PowerAuthUtils; 35 | import io.getlime.security.powerauth.sdk.PowerAuthSDK; 36 | 37 | // The `reactNativeContext` (of type ReactContext) availability depends on the place, where you're trying to access the PowerAuthSDK object. 38 | // For example, you can pass it when creating our package when implementing `ReactPackage` interface. 39 | PowerAuthSDK sdk = PowerAuthUtils.liftPowerAuthSdk("test", reactNativeContext); 40 | if (sdk != null) { 41 | // Do something with the native instance 42 | } 43 | ``` 44 | 45 | ## Read Next 46 | 47 | - [Additional Utilities](Additional-Utilities.md) 48 | -------------------------------------------------------------------------------- /.prepare-release.json: -------------------------------------------------------------------------------- 1 | { 2 | "metadata": { 3 | "purpose": "This file is used as a definition file for the prepare-release script.", 4 | "info": "It defines files that contains version number that should be updated during the release preparation.", 5 | "customBuildscript": "If needed, in the library object, set \"buildscript\": \"your-custom-build-command\" command if your build command is different than 'npm i && npm run build'" 6 | }, 7 | "library": { 8 | "name": "digital-onboarding-js", 9 | "type": "yarn", 10 | "artifacts": [ 11 | "packages/cordova-powerauth-mobile-sdk/build/cdv/cordova-powerauth-mobile-sdk-%VERSION%.tgz", 12 | "packages/react-native-powerauth-mobile-sdk/react-native-powerauth-mobile-sdk-%VERSION%.tgz" 13 | ], 14 | "buildscript": "corepack enable && yarn install && yarn packReactNative && yarn build:cdv" 15 | }, 16 | "files": [ 17 | { 18 | "description": "React package definition file.", 19 | "path": "packages/react-native-powerauth-mobile-sdk/package.json", 20 | "type": "version_replace", 21 | "match": "\"version\": \"%VERSION%\",\n", 22 | "_comment": "Based on this version, all other versions are derived during the build." 23 | }, 24 | { 25 | "description": "Changelog", 26 | "path": "docs/Changelog.md", 27 | "type": "version_verify", 28 | "match": "## %VERSION%" 29 | }, 30 | { 31 | "description": "Compatibility in the documentation.", 32 | "path": "docs/Readme.md", 33 | "type": "versionstream_verify", 34 | "match": "| `%VERSION_STREAM%`" 35 | }, 36 | { 37 | "description": "Compatibility in the documentation.", 38 | "path": "README.md", 39 | "type": "versionstream_verify", 40 | "match": "| `%VERSION_STREAM%`" 41 | } 42 | ] 43 | } -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/reactnative/PowerAuthUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.wultra.android.powerauth.reactnative; 18 | 19 | import androidx.annotation.NonNull; 20 | import androidx.annotation.Nullable; 21 | import com.facebook.react.bridge.ReactContext; 22 | import io.getlime.security.powerauth.sdk.PowerAuthSDK; 23 | 24 | /** 25 | * PowerAuth React-Native Utilities. 26 | * @noinspection unused 27 | */ 28 | public class PowerAuthUtils { 29 | /** 30 | * Function that lifts PowerAuthSDK instance from the React-Native module if present (configured). If the object is not available, returns nil. 31 | * Might throw IllegalStateException from the RN layer. 32 | * 33 | * @param instanceId Id of the instance that was configured from the JS/TS layer. 34 | * @param reactContext React context obtained from your ReactNative module or app. 35 | * @return Native PowerAuthSDK or null if such instance is not configured. 36 | */ 37 | @Nullable 38 | public static PowerAuthSDK liftPowerAuthSdk(@NonNull String instanceId, @NonNull ReactContext reactContext) { 39 | ObjectRegister module = reactContext.getNativeModule(ObjectRegister.class); 40 | if (module == null) { 41 | return null; 42 | } 43 | return module.findObject(instanceId, PowerAuthSDK.class); 44 | } 45 | } -------------------------------------------------------------------------------- /testapp/_tests/helpers/PasswordHelper.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2022 Wultra s.r.o. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | import { PowerAuth, PowerAuthPassword } from "react-native-powerauth-mobile-sdk"; 18 | 19 | /** 20 | * Function creates PowerAuthPassword object and imports provided passphrase from the string. 21 | * In the regular app, you let user to type the password character by character, so don't use such 22 | * function in your application. 23 | * @param password String with password to import. 24 | * @param destroyOnUse Password will be destroyed on use. 25 | * @param owner If provided, then the password will be associated with given PowerAuth instance. 26 | * @param pass If provided, then the string will be imported to this object. 27 | * @returns PowerAuthPassword with imported passphrase. 28 | */ 29 | export async function importPassword(password: string, destroyOnUse: boolean = true, owner: PowerAuth | undefined = undefined, pass: PowerAuthPassword | undefined = undefined): Promise { 30 | const p = pass ?? owner?.createPassword(destroyOnUse) ?? new PowerAuthPassword(destroyOnUse) 31 | let pos = 0; 32 | while (pos < password.length) { 33 | const cp = password.codePointAt(pos) 34 | if (cp) { 35 | await p.addCharacter(cp) 36 | pos += String.fromCodePoint(cp).length 37 | } else { 38 | throw new Error('Failed to extract codepoint') 39 | } 40 | } 41 | return p 42 | } -------------------------------------------------------------------------------- /scripts/prepare-release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e # stop script when error occurs 4 | set -u # stop when undefined variable is used 5 | #set -x # print all execution (good for debugging) 6 | 7 | ######### USAGE ######### 8 | # 9 | # To prepare or verify release metadata of the library (settings proper version, updating changelog, etc.) 10 | # - this script runs the JavaScript script from Wultra infrastructure repository 11 | # - it uses data defined in `.prepare-release.json` file in the root of the repository 12 | # - it passes all parameters to the JavaScript script 13 | # 14 | # 15 | # It can be run in 3 modes: 16 | # 17 | # 1. With a version (-v X.Y.Z) argument: 18 | # - it will prepare the release with the current version 19 | # - use it when you're preparing a new release pull-request 20 | # - Example: sh scripts/prepare-release.sh -v 1.0.0 21 | # 22 | # 2. With a version argument and --verify: 23 | # - it will verify that the given release version is prepared. 24 | # - use it to make sure that the release pull-request is properly prepared (also used on CI) 25 | # - Example: sh scripts/prepare-release.sh -v 1.0.0 --verify 26 | # 27 | # 3. Without arguments: 28 | # - it will run the script in the root directory of the repository and verify that all files are prepared. 29 | # - use it to make sure that the current state of the repository is ready for release 30 | # - Example: sh scripts/prepare-release.sh 31 | # 32 | # Note: you can add --ignore-git-clean to ignore "git clean" errors (useful when testing things locally) 33 | # 34 | ######################### 35 | 36 | # path to the script folder 37 | SCRIPT_FOLDER=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 38 | 39 | # URL of the JavaScript prepare-release script in Wultra infrastructure repository 40 | URL="https://raw.githubusercontent.com/wultra/wultra-infrastructure/refs/heads/mobile-release/mobile-release/v1/prepare-release.js" 41 | 42 | # execute the remote node and pass all parameters to it + add path parameter to the root of the repository 43 | curl -fsSL "${URL}" | node - -p "${SCRIPT_FOLDER}/.." "${@}" -------------------------------------------------------------------------------- /docs/Additional-Utilities.md: -------------------------------------------------------------------------------- 1 | # Additional Utilities 2 | 3 | The PowerAuth Mobile JS SDK offers additional utility functions that can help with various tasks in your application. These utilities are available through the `PowerAuthUtils` class. 4 | 5 | ## Available Methods 6 | 7 | ### getEnvironmentInfo() 8 | 9 | Returns information about the current environment, including system details, device information, and SDK version. 10 | 11 | **Usage:** 12 | 13 | ```typescript 14 | import { PowerAuthUtils } from 'react-native-powerauth-mobile-sdk'; 15 | 16 | async function getDeviceInfo() { 17 | try { 18 | const environmentInfo = await PowerAuthUtils.getEnvironmentInfo(); 19 | console.log('Environment Info:', environmentInfo); 20 | 21 | // Access specific properties 22 | console.log('System:', environmentInfo.systemName); 23 | console.log('Version:', environmentInfo.systemVersion); 24 | console.log('App Version:', environmentInfo.applicationVersion); 25 | console.log('App ID:', environmentInfo.applicationIdentifier); 26 | console.log('Device ID:', environmentInfo.deviceId); 27 | console.log('Device Maker:', environmentInfo.deviceManufacturer); 28 | console.log('SDK Version:', environmentInfo.sdkVersion); 29 | } catch (error) { 30 | console.error('Failed to get environment info:', error); 31 | } 32 | } 33 | ``` 34 | 35 | **Response:** 36 | 37 | The method returns a `PowerAuthEnvironmentInfo` object with the following properties: 38 | 39 | - `systemName` (string): System name, for example "iOS", "Android", "iPadOS" 40 | - `systemVersion` (string): Version of the system 41 | - `applicationVersion` (string, optional): Application version, e.g. "1.0.0" 42 | - `applicationIdentifier` (string, optional): Host application identifier, for example "com.wultra.demoapp" 43 | - `deviceManufacturer` (string): Device manufacturer, for example "apple" or "Samsung" 44 | - `deviceId` (string): Device ID, for example "iPhone9,2" 45 | - `sdkVersion` (string): PowerAuth JS SDK version, for example "4.0.0" 46 | -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/cdv/util/WritableNativeMap.kt: -------------------------------------------------------------------------------- 1 | package com.wultra.android.powerauth.cdv.util 2 | 3 | /** 4 | * Cordova implementation of writable map. 5 | * 6 | * It's not in fact native, it's based on Kotlin collections. 7 | */ 8 | class WritableNativeMap(srcMap: Map = emptyMap()) : ReadableNativeMap(srcMap), WritableMap { 9 | 10 | override fun putMap(key: String, value: ReadableMap?) { 11 | if (!(value == null || value is ReadableNativeMap)) { 12 | throw IllegalArgumentException("Illegal type provided") 13 | } 14 | _mutableMap.put(key, value as ReadableNativeMap?) 15 | } 16 | 17 | override fun putArray(key: String, value: ReadableArray?) { 18 | if (!(value == null || value is ReadableNativeArray)) { 19 | throw IllegalArgumentException("Illegal type provided") 20 | } 21 | _mutableMap.put(key, value as ReadableNativeArray?) 22 | } 23 | 24 | override fun putBoolean(key: String, value: Boolean) { 25 | _mutableMap[key] = value 26 | } 27 | 28 | override fun putDouble(key: String, value: Double) { 29 | _mutableMap[key] = value 30 | } 31 | 32 | override fun putInt(key: String, value: Int) { 33 | _mutableMap[key] = value 34 | } 35 | 36 | override fun putLong(key: String, value: Long) { 37 | _mutableMap[key] = value 38 | } 39 | 40 | override fun putNull(key: String) { 41 | _mutableMap[key] = null 42 | } 43 | 44 | override fun putString(key: String, value: String?) { 45 | _mutableMap[key] = value 46 | } 47 | 48 | override fun merge(source: ReadableMap) { 49 | if (source !is ReadableNativeMap) { 50 | throw IllegalArgumentException("Illegal type provided") 51 | } 52 | val iter = source.entryIterator 53 | while (iter.hasNext()) { 54 | val entry = iter.next() 55 | _mutableMap[entry.key] = entry.value 56 | } 57 | } 58 | 59 | override fun copy(): WritableMap { 60 | val target = WritableNativeMap() 61 | target.merge(this) 62 | return target 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /testapp/android/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 22 | 23 | 24 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /testapp/ios/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment, if you want to build the app with the old architecture 2 | # ENV['RCT_NEW_ARCH_ENABLED'] = '0' 3 | 4 | # Resolve react_native_pods.rb with node to allow for hoisting 5 | require Pod::Executable.execute_command('node', ['-p', 6 | 'require.resolve( 7 | "react-native/scripts/react_native_pods.rb", 8 | {paths: [process.argv[1]]}, 9 | )', __dir__]).strip 10 | 11 | platform :ios, min_ios_version_supported 12 | prepare_react_native_project! 13 | 14 | linkage = ENV['USE_FRAMEWORKS'] 15 | if linkage != nil 16 | Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green 17 | use_frameworks! :linkage => linkage.to_sym 18 | end 19 | 20 | target 'testapp' do 21 | config = use_native_modules! 22 | 23 | use_react_native!( 24 | :path => config[:reactNativePath], 25 | # An absolute path to your application root. 26 | :app_path => "#{Pod::Config.instance.installation_root}/.." 27 | ) 28 | 29 | post_install do |installer| 30 | # https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202 31 | react_native_post_install( 32 | installer, 33 | config[:reactNativePath], 34 | :mac_catalyst_enabled => false, 35 | # :ccache_enabled => true 36 | ) 37 | 38 | # Wultra specific 39 | fix_dev_team(installer, 'KTT9G859MR') 40 | end 41 | end 42 | 43 | # Wultra specific. Fix dev team for all configurations and targets 44 | def fix_dev_team(installer, team_id) 45 | # https://github.com/CocoaPods/CocoaPods/issues/8891 46 | def fix_config_dev_team(config, team_id) 47 | if config.build_settings['DEVELOPMENT_TEAM'].nil? 48 | config.build_settings['DEVELOPMENT_TEAM'] = team_id 49 | end 50 | end 51 | installer.generated_projects.each do |project| 52 | project.build_configurations.each do |config| 53 | fix_config_dev_team(config, team_id) 54 | end 55 | project.targets.each do |target| 56 | target.build_configurations.each do |config| 57 | fix_config_dev_team(config, team_id) 58 | end 59 | end 60 | end 61 | end 62 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/reactnative/PowerAuthCryptoUtilsModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.wultra.android.powerauth.reactnative; 18 | 19 | import androidx.annotation.NonNull; 20 | 21 | import com.facebook.react.bridge.BaseJavaModule; 22 | import com.facebook.react.bridge.Promise; 23 | import com.facebook.react.bridge.ReactMethod; 24 | import com.facebook.react.module.annotations.ReactModule; 25 | import com.wultra.android.powerauth.js.PowerAuthCryptoUtilsJsModule; 26 | 27 | @SuppressWarnings("unused") 28 | @ReactModule(name = "PowerAuthCryptoUtils") 29 | public class PowerAuthCryptoUtilsModule extends BaseJavaModule { 30 | 31 | private final PowerAuthCryptoUtilsJsModule powerAuthCryptoUtilsJsModule; 32 | 33 | public PowerAuthCryptoUtilsModule() { 34 | super(); 35 | this.powerAuthCryptoUtilsJsModule = new PowerAuthCryptoUtilsJsModule(); 36 | } 37 | 38 | public PowerAuthCryptoUtilsJsModule getPowerAuthCryptoUtilsJsModule() { 39 | return powerAuthCryptoUtilsJsModule; 40 | } 41 | 42 | @NonNull 43 | @Override 44 | public String getName() { 45 | return powerAuthCryptoUtilsJsModule.getName(); 46 | } 47 | 48 | @ReactMethod 49 | void hashSha256(String input, Promise promise) { 50 | powerAuthCryptoUtilsJsModule.hashSha256(input, promise); 51 | } 52 | 53 | @ReactMethod 54 | void randomBytes(int length, Promise promise) { 55 | powerAuthCryptoUtilsJsModule.randomBytes(length, promise); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /testapp/_tests/PowerAuthUtils.test.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2022 Wultra s.r.o. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | import { PowerAuthUtils } from "react-native-powerauth-mobile-sdk"; 18 | import { TestSuite, expect } from "../src/testbed"; 19 | 20 | export class PowerAuthUtilsTests extends TestSuite { 21 | 22 | async iosTestEnvironmentInfo() { 23 | const deviceInfo = await PowerAuthUtils.getEnvironmentInfo(); 24 | console.log(`Device info: ${JSON.stringify(deviceInfo)}`); 25 | expect(deviceInfo).toBeDefined(); 26 | expect(deviceInfo.systemName).toBe("iOS"); 27 | expect(deviceInfo.systemVersion).toBeDefined(); 28 | expect(deviceInfo.deviceManufacturer).toBe("apple"); 29 | expect(deviceInfo.deviceId).toBeDefined(); 30 | expect(deviceInfo.sdkVersion).toBeDefined(); 31 | expect(deviceInfo.applicationVersion).toBe("1.0"); 32 | expect(deviceInfo.applicationIdentifier).toBeDefined(); 33 | } 34 | 35 | async androidTestEnvironmentInfo() { 36 | const deviceInfo = await PowerAuthUtils.getEnvironmentInfo(); 37 | console.log(`Device info: ${JSON.stringify(deviceInfo)}`); 38 | expect(deviceInfo).toBeDefined(); 39 | expect(deviceInfo.systemName).toBe("android"); 40 | expect(deviceInfo.systemVersion).toBeDefined(); 41 | expect(deviceInfo.deviceManufacturer).toBeDefined(); 42 | expect(deviceInfo.deviceId).toBeDefined(); 43 | expect(deviceInfo.sdkVersion).toBeDefined(); 44 | expect(deviceInfo.applicationVersion).toBe("1.0"); 45 | expect(deviceInfo.applicationIdentifier).toBeDefined(); 46 | } 47 | } -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth/wpm_types.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2018 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef wultra_wpm_types_h 18 | #define wultra_wpm_types_h 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif 23 | 24 | /// Result of WPM_testPasscode function that can result in multiple issues. 25 | typedef enum _WPM_PasscodeResult { 26 | /// The passcode is OK, no issues found 27 | WPM_PasscodeResult_Ok = 1 << 0, 28 | /// The passcode doesn't have enough unique digits 29 | WPM_PasscodeResult_NotUnique = 1 << 1, 30 | /// There is a significant amount of repeating characters in the passcode 31 | WPM_PasscodeResult_RepeatingChars = 1 << 2, 32 | /// A repeating pattern was found in the passcode 33 | WPM_PasscodeResult_HasPattern = 1 << 3, 34 | /// This passcode can be a date (and possible birthday of the user) 35 | WPM_PasscodeResult_PossiblyDate = 1 << 4, 36 | /// The passcode is in most used passcodes 37 | WPM_PasscodeResult_FrequentlyUsed = 1 << 5, 38 | /// Wrong input 39 | WPM_PasscodeResult_WrongInput = 1 << 6 40 | 41 | } WPM_PasscodeResult; 42 | 43 | /// Classification of the password strength 44 | typedef enum _WPM_PasswordResult { 45 | WPM_PasswordResult_VeryWeak = 0, 46 | WPM_PasswordResult_Weak = 1, 47 | WPM_PasswordResult_Moderate = 2, 48 | WPM_PasswordResult_Good = 3, 49 | WPM_PasswordResult_Strong = 4, 50 | WPM_PasswordResult_WrongInput = 5, 51 | } WPM_PasswordResult; 52 | 53 | #ifdef __cplusplus 54 | } 55 | #endif 56 | 57 | #endif /* wultra_wpm_types_h */ 58 | -------------------------------------------------------------------------------- /docs/Storage-Utilities.md: -------------------------------------------------------------------------------- 1 | # Storage Utilities 2 | 3 | The PowerAuth Mobile JS SDK provides a simple cache API via `PowerAuthStorageUtils` for string key–value storage. 4 | 5 | ## Storage Types 6 | 7 | - `PowerAuthStorageType.SECURE` 8 | - iOS: PowerAuth Keychain (Keychain service `com.wultra.powerauth.jssdk.storageutils.secure`) 9 | - Android: PowerAuth Keychain (encrypted, backed by Android Keystore) 10 | 11 | - `PowerAuthStorageType.STANDARD` 12 | - iOS: UserDefaults suite `com.wultra.powerauth.jssdk.storageutils.standard` 13 | - Android: SharedPreferences file `com.wultra.powerauth.jssdk.storageutils.standard` 14 | 15 | ## Available Methods 16 | 17 | ### setString(key: string, value: string, storageType: PowerAuthStorageType) 18 | Store a string value under a key. 19 | 20 | ### getString(key: string, storageType: PowerAuthStorageType) 21 | Retrieve a string value. Returns `undefined` when the key is missing. 22 | 23 | ### exists(key: string, storageType: PowerAuthStorageType) 24 | Check whether a key is present. 25 | 26 | ### remove(key: string, storageType: PowerAuthStorageType) 27 | Remove a key. Returns `true` if the key existed. 28 | 29 | ## Usage 30 | 31 | ```typescript 32 | import { PowerAuthStorageUtils, PowerAuthStorageType } from 'react-native-powerauth-mobile-sdk'; 33 | 34 | // Secure storage (Keychain / Android Keystore-backed) 35 | await PowerAuthStorageUtils.setString('session', '{"token":"abc"}', PowerAuthStorageType.SECURE); 36 | const secureValue = await PowerAuthStorageUtils.getString('session', PowerAuthStorageType.SECURE); 37 | 38 | // Standard storage (UserDefaults / SharedPreferences) 39 | await PowerAuthStorageUtils.setString('theme', 'dark', PowerAuthStorageType.STANDARD); 40 | const exists = await PowerAuthStorageUtils.exists('theme', PowerAuthStorageType.STANDARD); 41 | const removed = await PowerAuthStorageUtils.remove('theme', PowerAuthStorageType.STANDARD); 42 | ``` 43 | 44 | ## Errors 45 | 46 | - `WRONG_PARAMETER`: invalid input (e.g., empty key, invalid storage type) 47 | - `ENCRYPTION_ERROR`: secure storage operation failed 48 | 49 | ## Read Next 50 | 51 | - [Additional Utilities](Additional-Utilities.md) 52 | - [Accessing the Native PowerAuthSDK](Accessing-Native-PowerAuthSDK.md) 53 | -------------------------------------------------------------------------------- /testapp-cordova/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.wultra.pwatest", 3 | "displayName": "PowerAuthTest", 4 | "version": "1.0.0", 5 | "description": "A sample Cordova application that runs PowerAuth tests.", 6 | "main": "index.js", 7 | "scripts": { 8 | "android": "yarn dlx cordova run android", 9 | "ios": "yarn dlx cordova run ios", 10 | "pods": "(cd \"platforms/ios\" && yarn dlx pod-install --non-interactive)", 11 | "rebuildPlugin": "(cd .. && yarn workspace cordova-powerauth-mobile-sdk cdv)", 12 | "installPlugin": "npm_config_workspaces=false yarn dlx cordova plugin add cordova-powerauth-mobile-sdk --noregistry --searchpath ../packages/cordova-powerauth-mobile-sdk/build/cdv --force", 13 | "reinstallPlugin": "(npm_config_workspaces=false yarn dlx cordova plugin remove cordova-powerauth-mobile-sdk --no-save --force || true) && yarn rebuildPlugin && yarn installPlugin", 14 | "prepare": "node node_modules/gulp/bin/gulp.js", 15 | "buildAndroid": "yarn reinstallPlugin && yarn prepare && yarn dlx cordova build android", 16 | "buildIos": "yarn reinstallPlugin && yarn prepare && (cd platforms/ios && yarn dlx pod-install --non-interactive && xcodebuild archive -workspace PowerAuthTest.xcworkspace -scheme PowerAuthTest -sdk iphoneos CODE_SIGN_IDENTITY=\"\" CODE_SIGNING_ALLOWED=NO)", 17 | "freshAndroid": "yarn reinstallPlugin && yarn prepare && yarn android", 18 | "freshIos": "yarn reinstallPlugin && yarn prepare && yarn pods && yarn ios" 19 | }, 20 | "keywords": [ 21 | "ecosystem:cordova" 22 | ], 23 | "author": "Apache Cordova Team", 24 | "license": "Apache-2.0", 25 | "devDependencies": { 26 | "buffer": "^6.0.3", 27 | "chalk": "^4.1.2", 28 | "cordova-android": "^13.0.0", 29 | "cordova-ios": "^7.1.1", 30 | "dotenv": "^16.4.5", 31 | "esbuild": "^0.23.1", 32 | "gulp": "^5.0.0", 33 | "gulp-replace": "^1.1.4", 34 | "rimraf": "^6.0.1" 35 | }, 36 | "cordova": { 37 | "platforms": [ 38 | "ios", 39 | "android" 40 | ], 41 | "plugins": { 42 | "cordova-powerauth-mobile-sdk": {} 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/js/WrapperException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.wultra.android.powerauth.js; 18 | 19 | import androidx.annotation.NonNull; 20 | 21 | /** 22 | * Exception type used internally in this module to propagate error code and message 23 | * to promise's reject method. 24 | */ 25 | class WrapperException extends Exception { 26 | 27 | private final String errorCode; 28 | 29 | /** 30 | * @return Error code that should be reported to promise. 31 | */ 32 | @NonNull 33 | String getErrorCode() { 34 | return errorCode; 35 | } 36 | 37 | /** 38 | * Construct WrapperException with required error code and message. 39 | * @param errorCode Error code that should be reported to promise as failure. 40 | * @param message Message that should be reported to promise as failure. 41 | */ 42 | WrapperException(@NonNull String errorCode, @NonNull String message) { 43 | super(message, null); 44 | this.errorCode = errorCode; 45 | } 46 | 47 | /** 48 | * Construct WrapperException with required error code, message and optional cause of the failure. 49 | * @param errorCode Error code that should be reported to promise as failure. 50 | * @param message Message that should be reported to promise as failure. 51 | * @param cause Original cause of failure. 52 | */ 53 | WrapperException(@NonNull String errorCode, @NonNull String message, Throwable cause) { 54 | super(message, cause); 55 | this.errorCode = errorCode; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/src/internal/NativeCordovaModule.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | //@ts-nocheck 18 | 19 | import { NativePowerAuthIfc } from "./NativePowerAuthIfc"; 20 | import { Utils } from "./Utils.ts"; 21 | 22 | export abstract class NativeCordovaModule implements NativePowerAuthIfc { 23 | 24 | protected abstract readonly pluginName: string; 25 | 26 | callNative(name: string, args: any[]): Promise { 27 | return new Promise( 28 | (resolve, reject) => { 29 | cordova.exec( 30 | // success callback 31 | (response) => { 32 | if (Utils.detectPlatform() === "android") { 33 | resolve(response); 34 | } else { 35 | const parsed = JSON.parse(response); 36 | resolve(parsed.result); 37 | } 38 | }, 39 | // error callback 40 | (error) => { 41 | if (Utils.detectPlatform() === "android") { 42 | reject(error) 43 | } else { 44 | reject(JSON.parse(error)) 45 | } 46 | }, 47 | // native platform plugin name 48 | this.pluginName, 49 | // function name 50 | name, 51 | // function arguments 52 | args 53 | ); 54 | } 55 | ); 56 | } 57 | } -------------------------------------------------------------------------------- /testapp-cordova/src/App.tsx: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2024 Wultra s.r.o. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | // @ts-nocheck 18 | 19 | import { TestExecutor } from './TestExecutor' 20 | 21 | document.addEventListener('deviceready', onDeviceReady, false); 22 | 23 | function onDeviceReady() { 24 | 25 | // Cordova is now initialized. Have fun! 26 | 27 | // enable debug 28 | PowerAuthDebug.isEnabled = true; 29 | 30 | const statusEl = document.getElementById('tests-status'); 31 | const progressEl = document.getElementById('tests-progress'); 32 | const messageEl = document.getElementById("test-message"); 33 | 34 | console.log('Running cordova-' + cordova.platformId + '@' + cordova.version); 35 | document.getElementById('deviceready').classList.add('ready'); 36 | 37 | const executor = new TestExecutor(async (_context, message, duration) => { 38 | messageEl.innerHTML = message; 39 | await new Promise(resolve => setTimeout(resolve, duration)) 40 | }, (progress) => { 41 | progressEl.innerHTML = `${progress.succeeded} succeeded
${progress.failed} failed
${progress.skipped} skipped
out of total ${progress.total}`;; 42 | }, (finished) => { 43 | statusEl.innerHTML = finished ? "Tests running" : "Tests finished"; 44 | messageEl.innerHTML = ""; 45 | }) 46 | 47 | document.getElementById('tests-simple').addEventListener('click', (e) => { 48 | executor.runTests(false) 49 | }) 50 | document.getElementById('tests-full').addEventListener('click', (e) => { 51 | executor.runTests(true) 52 | }) 53 | document.getElementById('tests-stop').addEventListener('click', (e) => { 54 | executor.cancelTests() 55 | }) 56 | } -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/cdv/util/ReadableNativeArray.kt: -------------------------------------------------------------------------------- 1 | package com.wultra.android.powerauth.cdv.util 2 | 3 | import com.wultra.android.powerauth.bridge.toList 4 | import com.wultra.android.powerauth.bridge.toReadableType 5 | import org.json.JSONArray 6 | 7 | 8 | /** 9 | * Cordova implementation of readable array. 10 | * 11 | * It's not in fact native, it's based on Kotlin collections. 12 | */ 13 | open class ReadableNativeArray(srcList: List) : ReadableArray { 14 | 15 | protected val _mutableList = srcList.toMutableList() 16 | protected val list: List = _mutableList 17 | 18 | constructor(jsonArray: JSONArray) : this(jsonArray.toList()) 19 | 20 | override fun getArray(index: Int): ReadableArray { 21 | return ReadableNativeArray(list[index] as List) 22 | } 23 | 24 | override fun getBoolean(index: Int): Boolean { 25 | return list[index] as Boolean 26 | } 27 | 28 | override fun getDouble(index: Int): Double { 29 | return list[index] as Double 30 | } 31 | 32 | override fun getDynamic(index: Int): Dynamic { 33 | return list[index] as Dynamic 34 | } 35 | 36 | override fun getInt(index: Int): Int { 37 | return list[index] as Int 38 | } 39 | 40 | override fun getLong(index: Int): Long { 41 | return list[index] as Long 42 | } 43 | 44 | override fun getMap(index: Int): ReadableMap { 45 | @Suppress("UNCHECKED_CAST") 46 | return ReadableNativeMap(list[index] as Map) 47 | } 48 | 49 | override fun getString(index: Int): String { 50 | return list[index] as String 51 | } 52 | 53 | override fun getType(index: Int): ReadableType { 54 | return list[index].toReadableType() 55 | } 56 | 57 | override fun isNull(index: Int): Boolean { 58 | return list[index] == null 59 | } 60 | 61 | override fun size(): Int { 62 | return list.size 63 | } 64 | 65 | override fun toArrayList(): ArrayList { 66 | val l = list.filterNotNull().map { 67 | when (it) { 68 | is ReadableMap -> it.toHashMap() 69 | is ReadableArray -> it.toArrayList() 70 | else -> it 71 | } 72 | } 73 | return ArrayList(l) 74 | } 75 | } 76 | 77 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/reactnative/PowerAuthPassphraseMeterModule.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.wultra.android.powerauth.reactnative; 18 | 19 | import androidx.annotation.NonNull; 20 | 21 | import com.facebook.react.bridge.BaseJavaModule; 22 | import com.facebook.react.bridge.Dynamic; 23 | import com.facebook.react.bridge.Promise; 24 | import com.facebook.react.bridge.ReactMethod; 25 | import com.facebook.react.module.annotations.ReactModule; 26 | import com.wultra.android.powerauth.js.PowerAuthPassphraseMeterJsModule; 27 | 28 | @SuppressWarnings("unused") 29 | @ReactModule(name = "PowerAuthPassphraseMeter") 30 | public class PowerAuthPassphraseMeterModule extends BaseJavaModule { 31 | 32 | private final PowerAuthPasswordModule passwordModule; 33 | private final PowerAuthPassphraseMeterJsModule powerAuthPassphraseMeterJsModule; 34 | 35 | public PowerAuthPassphraseMeterModule(@NonNull PowerAuthPasswordModule passwordModule) { 36 | this.passwordModule = passwordModule; 37 | this.powerAuthPassphraseMeterJsModule = new PowerAuthPassphraseMeterJsModule(passwordModule.getPowerAuthPasswordJsModule()); 38 | } 39 | 40 | public PowerAuthPassphraseMeterJsModule getPowerAuthPassphraseMeterJsModule() { 41 | return powerAuthPassphraseMeterJsModule; 42 | } 43 | 44 | @NonNull 45 | @Override 46 | public String getName() { 47 | return powerAuthPassphraseMeterJsModule.getName(); 48 | } 49 | 50 | public static final String NAME = "PowerAuthPassphraseMeter"; 51 | 52 | @ReactMethod 53 | void testPin(Dynamic password, Promise promise) { 54 | powerAuthPassphraseMeterJsModule.testPin(password, promise); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/index.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // Main objects 18 | 19 | export * from './PowerAuth'; 20 | export * from './PowerAuthActivationCodeUtil'; 21 | export * from './PowerAuthUtils'; 22 | export * from './PowerAuthTokenStore'; 23 | export * from './PowerAuthPassphraseMeter'; 24 | export * from './PowerAuthCryptoUtils'; 25 | export * from './PowerAuthStorageUtils'; 26 | 27 | // Model objects 28 | 29 | export * from './model/PowerAuthActivation'; 30 | export * from './model/PowerAuthActivationState'; 31 | export * from './model/PowerAuthActivationStatus'; 32 | export * from './model/PowerAuthAuthentication'; 33 | export * from './model/PowerAuthAuthorizationHttpHeader'; 34 | export * from './model/PowerAuthEncryptionHttpHeader'; 35 | export * from './model/PowerAuthBiometryConfiguration'; 36 | export * from './model/PowerAuthBiometryInfo'; 37 | export * from './model/PowerAuthClientConfiguration'; 38 | export * from './model/PowerAuthConfiguration'; 39 | export * from './model/PowerAuthConfirmRecoveryCodeDataResult'; 40 | export * from './model/PowerAuthCreateActivationResult'; 41 | export * from './model/PowerAuthError'; 42 | export * from './model/PowerAuthKeychainConfiguration'; 43 | export * from './model/PowerAuthSharingConfiguration'; 44 | export * from './model/PowerAuthExternalPendingOperation'; 45 | export * from './model/PowerAuthRecoveryActivationData'; 46 | export * from './model/PowerAuthPassword'; 47 | export * from './model/PowerAuthEncryptor'; 48 | export * from './model/PowerAuthDataFormat'; 49 | export * from './model/PowerAuthUserInfo'; 50 | export * from './model/BaseNativeObject'; 51 | 52 | // Debug features 53 | 54 | export * from './debug/PowerAuthDebug'; 55 | export * from './debug/NativeObjectRegister'; 56 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/model/PowerAuthConfiguration.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /** 18 | * Interface that contains configuration data for a single `PowerAuth` instance. 19 | */ 20 | export interface PowerAuthConfigurationType { 21 | /** 22 | * String with the cryptographic configuration. 23 | */ 24 | readonly configuration: string 25 | /** 26 | * Base URL to the PowerAuth enrollment server. Usualky ends with `/enrollment-server`. 27 | */ 28 | readonly baseEndpointUrl: string 29 | } 30 | 31 | /** 32 | * Class representing a configuration of a single `PowerAuth` instance. The class implements 33 | * `ConfigurationType` interface, so can be used 34 | */ 35 | export class PowerAuthConfiguration implements PowerAuthConfigurationType { 36 | configuration: string 37 | baseEndpointUrl: string 38 | 39 | /** 40 | * Construct configuration with required parameters. 41 | * 42 | * @param configuration String with the cryptographic configuration. 43 | * @param baseEndpointUrl Base URL to the PowerAuth enrollment server. Usually ends with `/enrollment-server`. 44 | */ 45 | public constructor(configuration: string, baseEndpointUrl: string) { 46 | this.configuration = configuration 47 | this.baseEndpointUrl = baseEndpointUrl 48 | } 49 | } 50 | 51 | /** 52 | * Create frozen configuration from provided configuration object. 53 | * @param input Application provided configuration. 54 | * @returns Frozen configuration object. 55 | */ 56 | export function buildConfiguration(input: PowerAuthConfigurationType): PowerAuthConfigurationType { 57 | return Object.freeze({ 58 | configuration: input.configuration, 59 | baseEndpointUrl: input.baseEndpointUrl 60 | }) 61 | } 62 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/src/model/PowerAuthNativeTypes.ts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | import { PasswordType, PowerAuthBiometricPrompt } from '../index' 18 | 19 | /** 20 | * Interface representing a simple native object identified by string identifier. 21 | */ 22 | export interface PowerAuthRawNativeObject { 23 | /** 24 | * Object's identifier. 25 | */ 26 | objectId?: string 27 | } 28 | 29 | /** 30 | * Type representing a simple native password identifier wrapped in the object. 31 | * We need this auxiliary object due to a problematic call to passphrase meter. 32 | */ 33 | export type PowerAuthRawPassword = PowerAuthRawNativeObject; 34 | 35 | /** 36 | * Type representing a raw password object passable to native interface. 37 | */ 38 | export type PowerAuthRawPasswordType = PowerAuthRawPassword | string 39 | 40 | /** 41 | * Object representing a data pased to native methods requiring PowerAuthAuthentication 42 | * on imput. The `RawAuthentication` must be be created from `PowerAuthAuthentication` 43 | * instance. 44 | */ 45 | export interface PowerAuthRawAuthentication { 46 | readonly password?: string | PowerAuthRawPassword 47 | readonly biometricPrompt?: PowerAuthBiometricPrompt 48 | readonly isPersist?: boolean 49 | readonly isBiometry: boolean 50 | isReusable: boolean 51 | biometryKeyId?: string 52 | } 53 | 54 | /** 55 | * Convert public password type into type passable into native interface. 56 | * @param password Public password object type. 57 | * @returns Raw password object type. 58 | */ 59 | export function toPowerAuthRawPassword(password: PasswordType): Promise { 60 | if (typeof password === 'string') { 61 | return Promise.resolve(password) 62 | } 63 | return password.toRawPassword() 64 | } -------------------------------------------------------------------------------- /docs/Changelog.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## TBA 4 | - Added `PowerAuthCryptoUtils` with functions for hashing and random bytes generation (see [Crypto Utilities](./Crypto-Utilities.md) for more details) 5 | - Added helper method to create `PowerAuthPassword` from string (`PowerAuthPassword.fromString`) (see [Secure Password](./Secure-Password.md) for more details) 6 | - Added `PowerAuthStorageUtils` cache API with secure & standard storage (see [Storage Utilities](./Storage-Utilities.md)) 7 | - Fixed bridged native error processing on Cordova (issue[#302](https://github.com/wultra/react-native-powerauth-mobile-sdk/issues/302)) 8 | 9 | ## 4.1.3 (9/2025) 10 | - Token-based authentication now automatically synchronizes time if needed (see [Token-Based Authentication](./Token-Based-Authentication.md) for more details) 11 | 12 | ## 4.1.2 (9/2025) 13 | - Fixed Android Encryptor crashing on missing `putLong` JNI bindings (issue [#264](https://github.com/wultra/react-native-powerauth-mobile-sdk/issues/264)) 14 | - Added [Time Synchronization service](./Time-Synchronization.md) 15 | 16 | ## 4.1.1 (7/2025) 17 | 18 | - Upgraded the [PowerAuth native SDK to `1.9.5`](https://github.com/wultra/powerauth-mobile-sdk/releases/tag/1.9.5) 19 | - Biometric authentication offloaded to the background thread 20 | 21 | ## 4.1.0 (6/2025) 22 | - Opportunity to sign Base64 encoded data with `signDataWithDevicePrivateKey` 23 | - we added the `dataFormat` parameter with possible `UTF8` and `BASE64` values for the data to be signed 24 | - Added `PowerAuthUtils` that provides `getEnvironmentInfo` with device, system and app info 25 | - Fixed issue on Cordova when iPadOS was recognized as Android in some cases 26 | - Fixed `validatePassword` API on iOS that returned wrong value 27 | 28 | ## 3.2.0 (6/2025) 29 | - Added `PowerAuthUtils` that provides `getEnvironmentInfo` with device, system and app info 30 | - Fixed issue on Cordova when iPadOS was recognized as Android in some cases 31 | 32 | ## 4.0.0 (5/2025) 33 | - Migration to the latest native PowerAuthSDK stack (1.9.x) 34 | - Use [migration guide](Version-4.0.md) for a smooth migration 35 | 36 | ## 3.1.0 (5/2025) 37 | - Support for the new React Architecture 38 | 39 | ## 3.0.1 (4/2025) 40 | - Native PowerAuth SDK version raised to 1.7.12 41 | - Fixed build problems on Xcode 16.3 42 | - OpenSSL upgraded to version `1.1.1w` 43 | 44 | ## 3.0.0 (1/2025) 45 | 46 | - Library renamed to `PowerAuth Mobile JS` 47 | - Added Cordova support -------------------------------------------------------------------------------- /packages/cordova-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/cdv/PowerAuthObjectRegister.kt: -------------------------------------------------------------------------------- 1 | 2 | package com.wultra.android.powerauth.cordova.plugin 3 | 4 | import com.wultra.android.powerauth.bridge.getOptString 5 | import com.wultra.android.powerauth.bridge.getReadableMap 6 | import com.wultra.android.powerauth.js.ObjectRegisterJs 7 | import com.wultra.android.powerauth.cdv.util.Promise 8 | import org.apache.cordova.CallbackContext 9 | import org.apache.cordova.CordovaInterface 10 | import org.apache.cordova.CordovaPlugin 11 | import org.apache.cordova.CordovaWebView 12 | import org.json.JSONArray 13 | import org.json.JSONException 14 | 15 | 16 | class PowerAuthObjectRegister : CordovaPlugin() { 17 | 18 | internal lateinit var objectRegisterJs: ObjectRegisterJs 19 | 20 | override fun initialize(cordova: CordovaInterface, webView: CordovaWebView) { 21 | super.initialize(cordova, webView); 22 | objectRegisterJs = ObjectRegisterJs(cordova.context.applicationContext) 23 | } 24 | 25 | @Throws(JSONException::class) 26 | override fun execute(action: String, args: JSONArray, callbackContext: CallbackContext): Boolean { 27 | val promise = Promise(callbackContext) 28 | when (action) { 29 | "isValidNativeObject" -> { 30 | isValidNativeObject(args, promise) 31 | return true 32 | } 33 | "debugDump" -> { 34 | debugDump(args, promise) 35 | return true 36 | } 37 | "debugCommand" -> { 38 | debugCommand(args,promise) 39 | return true 40 | } 41 | } 42 | return false // Returning false results in a "MethodNotFound" error. 43 | } 44 | 45 | 46 | private fun isValidNativeObject(args: JSONArray, promise: Promise) { 47 | val objectId = args.getOptString(0) 48 | objectRegisterJs.isValidNativeObject(objectId, promise) 49 | } 50 | 51 | private fun debugDump(args: JSONArray, promise: Promise) { 52 | val instanceId = args.getOptString(0) 53 | objectRegisterJs.debugDump(instanceId, promise); 54 | } 55 | 56 | private fun debugCommand(args: JSONArray, promise: Promise) { 57 | // String command, ReadableMap options 58 | val command = args.getString(0) 59 | val options = args.getReadableMap(1) 60 | objectRegisterJs.debugCommand(command, options, promise); 61 | } 62 | } -------------------------------------------------------------------------------- /testapp/_tests/PowerAuth_ErrorData.test.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2025 Wultra s.r.o. 3 | // 4 | // Licensed under the Apache License, Version 2.0 (the "License"); 5 | // you may not use this file except in compliance with the License. 6 | // You may obtain a copy of the License at 7 | // 8 | // http://www.apache.org/licenses/LICENSE-2.0 9 | // 10 | // Unless required by applicable law or agreed to in writing, software 11 | // distributed under the License is distributed on an "AS IS" BASIS, 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | // See the License for the specific language governing permissions and 14 | // limitations under the License. 15 | // 16 | 17 | import { PowerAuthError, PowerAuthErrorCode } from "react-native-powerauth-mobile-sdk"; 18 | import { expect } from "../src/testbed"; 19 | import { TestWithActivation } from "./helpers/TestWithActivation"; 20 | 21 | export class PowerAuth_ErrorDataTests extends TestWithActivation { 22 | 23 | async testErrorContainsParsedData() { 24 | let errorThrown = false 25 | try { 26 | await this.sdk.validatePassword(this.credentials.invalidPassword) 27 | } catch (e) { 28 | errorThrown = true 29 | expect(e instanceof PowerAuthError).toBe(true) 30 | const error = e as PowerAuthError 31 | 32 | expect(error.code).toBe(PowerAuthErrorCode.AUTHENTICATION_ERROR) 33 | expect(error.errorData).toBeDefined() 34 | expect(typeof error.errorData.httpStatusCode).toBe('number') 35 | expect(error.errorData.httpStatusCode).toBe(401) 36 | expect(typeof error.errorData.responseBody).toBe('string') 37 | } 38 | expect(errorThrown).toBe(true) 39 | } 40 | 41 | async testResponseErrorContainsParsedData() { 42 | let errorThrown = false 43 | try { 44 | await this.sdk.confirmRecoveryCode('AAAAA-AAAAA-AAAAA-AAAAA', this.credentials.knowledge) 45 | } catch (e) { 46 | errorThrown = true 47 | expect(e instanceof PowerAuthError).toBe(true) 48 | const error = e as PowerAuthError 49 | 50 | expect(error.code === PowerAuthErrorCode.RESPONSE_ERROR || error.code === PowerAuthErrorCode.AUTHENTICATION_ERROR).toBe(true) 51 | expect(error.errorData).toBeDefined() 52 | expect(typeof error.errorData.httpStatusCode).toBe('number') 53 | } 54 | expect(errorThrown).toBe(true) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/ios/PowerAuth/PowerAuthEncryptorModule.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #import "PAJS.h" 18 | #import "Errors.h" 19 | 20 | @class PowerAuthCoreEciesEncryptor; 21 | 22 | /// Object containing all encryptor's data required for the request encryption. 23 | @interface PowerAuthJsEncryptor: NSObject 24 | 25 | - (nonnull instancetype) initWithEncryptor:(nonnull PowerAuthCoreEciesEncryptor*)encryptor 26 | powerAuthInstanceId:(nonnull NSString*)powerAuthInstanceId 27 | activationScoped:(BOOL)activationScoped; 28 | 29 | @property (nonatomic, readonly) BOOL activationScoped; 30 | @property (nonatomic, readonly, strong, nonnull) PowerAuthCoreEciesEncryptor * coreEncryptor; 31 | @property (nonatomic, readonly, strong, nonnull) NSString * powerAuthInstanceId; 32 | 33 | @end 34 | 35 | // "PowerAuthEncryptor" module 36 | 37 | PAJS_MODULE(PowerAuthEncryptorModule) 38 | 39 | /// Use native encryptor object with given identifier. 40 | /// - Parameters: 41 | /// - encryptorId: Encryptor's identifier. 42 | /// - reject: Reject function. 43 | /// - action: Action to execute when encryptor exists and can be used. 44 | - (void) useEncryptor:(nullable NSString*)encryptorId 45 | rejecter:(nonnull RCTPromiseRejectBlock)reject 46 | action:(NS_NOESCAPE void(^_Nonnull)(PowerAuthJsEncryptor * _Nonnull encryptor))action; 47 | 48 | /// Touch native encryptor object with given identifier in the object register. 49 | /// - Parameters: 50 | /// - encryptorId: Encryptor's identifier. 51 | /// - reject: Reject function. 52 | /// - action: Action to execute when encryptor exists and can be used. 53 | - (void) touchEncryptor:(nullable NSString*)encryptorId 54 | rejecter:(nonnull RCTPromiseRejectBlock)reject 55 | action:(NS_NOESCAPE void(^_Nonnull)(PowerAuthJsEncryptor * _Nonnull encryptor))action; 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/js/Constants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2022 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.wultra.android.powerauth.js; 18 | 19 | class Constants { 20 | /** 21 | * Default period in milliseconds for automatic objects cleanup job. 22 | */ 23 | static final int CLEANUP_PERIOD_DEFAULT = 10_000; 24 | /** 25 | * Minimum allowed period for automatic objects cleanup job. 26 | */ 27 | static final int CLEANUP_PERIOD_MIN = 100; 28 | /** 29 | * Maximum allowed period for automatic objects cleanup job. 30 | */ 31 | static final int CLEANUP_PERIOD_MAX = 60_000; 32 | /** 33 | * Keep object in memory for one more second after the explicit remove. 34 | */ 35 | static final int CLEANUP_REMOVE_DELAY = 1_000; 36 | /** 37 | * Time interval in milliseconds to keep pre-authorized biometric key in memory. 38 | */ 39 | static final int BIOMETRY_KEY_KEEP_ALIVE_TIME = 10_000; 40 | /** 41 | * Time interval in milliseconds to keep password object valid in memory. 42 | */ 43 | static final int PASSWORD_KEY_KEEP_ALIVE_TIME = 5 * 60 * 1_000; 44 | /** 45 | * Time interval in milliseconds to keep encryptor object valid in memory. 46 | */ 47 | static final int ENCRYPTOR_KEY_KEEP_ALIVE_TIME = 5 * 60 * 1_000; 48 | /** 49 | * Time interval in milliseconds to keep decryptor object valid in memory. 50 | */ 51 | static final int DECRYPTOR_KEY_KEEP_ALIVE_TIME = 5 * 60 * 1_000; 52 | /** 53 | * Upper limit for Unicode Code Point. 54 | */ 55 | static final int CODEPOINT_MAX = 0x10FFFF; 56 | 57 | // Fallback strings 58 | 59 | /** 60 | * Fallback string used in biometric authentication when no title is 61 | * provided to authentication dialog. 62 | */ 63 | static final String MISSING_REQUIRED_STRING = "< missing >"; 64 | } 65 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/build.gradle: -------------------------------------------------------------------------------- 1 | ext { 2 | // 3 | // Defaults for the standalone build 4 | 5 | PowerAuthSdkRN_kotlinVersion = "1.9.22" 6 | PowerAuthSdkRN_minSdkVersion = 21 7 | PowerAuthSdkRN_targetSdkVersion = 33 8 | PowerAuthSdkRN_compileSdkVersion = 33 9 | PowerAuthSdkRN_ndkversion = "21.4.7075529" 10 | PowerAuthSdkRN_reactNativeVersion = "0.78.1" 11 | } 12 | 13 | apply plugin: "com.android.library" 14 | apply plugin: "org.jetbrains.kotlin.android" 15 | 16 | buildscript { 17 | repositories { 18 | mavenCentral() 19 | google() 20 | } 21 | 22 | dependencies { 23 | classpath("com.android.tools.build:gradle") 24 | classpath("com.facebook.react:react-native-gradle-plugin") 25 | classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") 26 | } 27 | } 28 | 29 | def isNewArchitectureEnabled() { 30 | return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true" 31 | } 32 | 33 | if (isNewArchitectureEnabled()) { 34 | apply plugin: "com.facebook.react" 35 | } 36 | 37 | def getExtOrDefault(name) { 38 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.ext["PowerAuthSdkRN_" + name] 39 | } 40 | 41 | def getExtOrIntegerDefault(name) { 42 | return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.ext["PowerAuthSdkRN_" + name]).toInteger() 43 | } 44 | 45 | android { 46 | 47 | namespace = "com.wultra.android.powerauth.reactnative" 48 | compileSdkVersion getExtOrIntegerDefault("compileSdkVersion") 49 | 50 | buildFeatures { 51 | buildConfig true 52 | } 53 | 54 | defaultConfig { 55 | minSdkVersion getExtOrIntegerDefault("minSdkVersion") 56 | targetSdkVersion getExtOrIntegerDefault("targetSdkVersion") 57 | buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() 58 | } 59 | buildTypes { 60 | release { 61 | minifyEnabled false 62 | } 63 | } 64 | 65 | lintOptions { 66 | disable "GradleCompatible" 67 | } 68 | 69 | compileOptions { 70 | sourceCompatibility JavaVersion.VERSION_17 71 | targetCompatibility JavaVersion.VERSION_17 72 | } 73 | } 74 | 75 | repositories { 76 | mavenCentral() 77 | google() 78 | } 79 | 80 | dependencies { 81 | implementation("com.facebook.react:react-android") 82 | implementation("org.jetbrains.kotlin:kotlin-stdlib:1.9.22") 83 | api "com.wultra.android.powerauth:powerauth-sdk:1.9.5" 84 | } 85 | 86 | if (isNewArchitectureEnabled()) { 87 | react { 88 | jsRootDir = file("../src") 89 | libraryName = "PowerAuthReactNative" 90 | codegenJavaPackageName = "com.wultra.android.powerauth.reactnative" 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /packages/react-native-powerauth-mobile-sdk/android/src/main/java/com/wultra/android/powerauth/js/PowerAuthCryptoUtilsJsModule.kt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025 Wultra s.r.o. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.wultra.android.powerauth.js 17 | 18 | import com.wultra.android.powerauth.bridge.JsApiMethod 19 | import com.wultra.android.powerauth.bridge.Promise 20 | import io.getlime.security.powerauth.core.CryptoUtils 21 | import android.util.Base64 22 | 23 | class PowerAuthCryptoUtilsJsModule() : BaseJavaJsModule { 24 | override fun getName(): String { 25 | return "PowerAuthCryptoUtils" 26 | } 27 | 28 | @JsApiMethod 29 | fun hashSha256(input: String, promise: Promise) { 30 | try { 31 | val decodedBytes: ByteArray = Base64.decode(input, Base64.NO_WRAP) 32 | val hash = CryptoUtils.hashSha256(decodedBytes) 33 | val encodedHash = Base64.encodeToString(hash, Base64.NO_WRAP) 34 | promise.resolve(encodedHash) 35 | } catch (e: IllegalArgumentException) { 36 | Errors.rejectPromise(promise, WrapperException(Errors.EC_WRONG_PARAMETER, "Input is not valid Base64.", e)) 37 | } catch (t: Throwable) { 38 | Errors.rejectPromise(promise, t) 39 | } 40 | } 41 | 42 | @JsApiMethod 43 | fun randomBytes(length: Int, promise: Promise) { 44 | try { 45 | if (length < 0) { 46 | throw WrapperException(Errors.EC_WRONG_PARAMETER, "Length must be a non-negative integer") 47 | } 48 | // Handle zero-length explicitly to avoid calling underlying generator with 0, 49 | // and to return a valid Base64 for empty data (empty string) 50 | if (length == 0) { 51 | promise.resolve("") 52 | return 53 | } 54 | val randomBytes = CryptoUtils.randomBytes(length) 55 | val encodedBytes = Base64.encodeToString(randomBytes, Base64.NO_WRAP) 56 | promise.resolve(encodedBytes) 57 | } catch (t: Throwable) { 58 | Errors.rejectPromise(promise, t) 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /docs/Device-Activation-Removal.md: -------------------------------------------------------------------------------- 1 | # Device Activation Removal 2 | 3 | You can remove activation using several ways - the choice depends on the desired behavior. 4 | 5 | ## Simple Device-Only Removal 6 | 7 | You can clear activation data anytime from the Keychain. The benefit of this method is that it does not require help from the server, and the user does not have to be logged in. The issue with this removal method is simple: The activation still remains active on the server-side. This, however, does not have to be an issue in your case. 8 | 9 | To remove only data related to PowerAuth, use: 10 | 11 | ```javascript 12 | await powerAuth.removeActivationLocal(); 13 | ``` 14 | 15 | ## Removal via Authenticated Session 16 | 17 | Suppose your server uses an authenticated session for keeping the users logged in. In that case, you can combine the previous method with calling your proprietary endpoint to remove activation for the currently logged-in user. The advantage of this method is that activation does not remain active on the server. The issue is that the user has to be logged in (the session must be active and must have activation ID stored) and that you have to publish your own method to handle this use case. 18 | 19 | The code for this activation removal method is as follows: 20 | 21 | ```javascript 22 | // Use custom call to proprietary server endpoint to remove activation. 23 | // User must be logged in at this moment, so that session can find 24 | // associated activation ID 25 | httpClient.post(null, "/custom/activation/remove", async (error) => { 26 | if (error == null) { 27 | await powerAuth.removeActivationLocal(); 28 | } else { 29 | // Report error 30 | } 31 | }); 32 | 33 | ``` 34 | 35 | ## Removal via Signed Request 36 | 37 | PowerAuth Standard RESTful API has a default endpoint `/pa/v3/activation/remove` for an activation removal. This endpoint uses a signature verification for looking up the activation to be removed. The benefit of this method is that it is already present in both PowerAuth JS SDK and PowerAuth Standard RESTful API - nothing has to be programmed. Also, the user does not have to be logged in to use it. However, the user has to authenticate using 2FA with either password or biometry. 38 | 39 | Use the following code for an activation removal using signed request: 40 | 41 | ```javascript 42 | // 2FA signature, uses device related key and user PIN code 43 | const auth = PowerAuthAuthentication.password("1234"); 44 | try { 45 | await powerAuth.removeActivationWithAuthentication(auth); 46 | // activation removed 47 | } catch (e) { 48 | // failed to remove 49 | } 50 | ``` 51 | 52 | 53 | ## Read Next 54 | 55 | - [End-To-End Encryption](End-To-End-Encryption.md) 56 | 57 | --------------------------------------------------------------------------------