From e6d588d1cd06ca1202dfcfdca32cd2164a58fd7a Mon Sep 17 00:00:00 2001 From: Jared Perreault Date: Fri, 27 Mar 2026 16:21:22 -0400 Subject: [PATCH 01/20] feat: react-native TokenStorage --- .circleci/config.yml | 70 ++- e2e/apps/react-native-oidc/app.config.ts | 1 + .../react-native-oidc/app/(login)/_layout.tsx | 45 -- .../react-native-oidc/app/(login)/index.tsx | 85 ---- .../react-native-oidc/app/(login)/token.tsx | 106 ---- .../react-native-oidc/app/(tabs)/_layout.tsx | 15 +- .../app/(tabs)/credentials.tsx | 228 +++++++++ .../react-native-oidc/app/(tabs)/explore.tsx | 110 ----- .../react-native-oidc/app/(tabs)/index.tsx | 116 ++++- .../react-native-oidc/app/(tabs)/token.tsx | 296 +++++++++++ e2e/apps/react-native-oidc/app/_layout.tsx | 1 - e2e/apps/react-native-oidc/hooks/useAuth.ts | 27 +- e2e/apps/react-native-oidc/index.js | 2 + .../react-native-oidc/react-native.config.js | 3 + .../src/Credential/CredentialCoordinator.ts | 9 +- .../src/Credential/TokenStorage.ts | 10 +- packages/auth-foundation/src/FetchClient.ts | 2 + .../react-native-platform/android/.gitignore | 3 + .../android/build.gradle | 83 ++++ .../android/gradle.properties | 2 + .../android/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 43583 bytes .../gradle/wrapper/gradle-wrapper.properties | 7 + .../react-native-platform/android/gradlew | 251 ++++++++++ .../react-native-platform/android/gradlew.bat | 94 ++++ .../android/src/main/AndroidManifest.xml | 4 + .../OktaReactNativePlatformPackage.kt | 20 + .../BrowserSessionModule.kt.disabled | 58 +++ .../tokenStorage/TokenStorageModule.kt | 178 +++++++ .../BrowserSessionModuleTest.kt.disabled | 121 +++++ .../tokenStorage/TokenStorageModuleTest.kt | 326 +++++++++++++ packages/react-native-platform/ios/.gitignore | 5 + .../react-native-platform/ios/Package.swift | 32 ++ .../BrowserSessionBridge.h | 13 + .../BrowserSessionBridge.m | 5 + .../BrowserSessionBridge.swift | 95 ++++ .../RNTokenStorageBridge/TokenStorageBridge.h | 11 + .../RNTokenStorageBridge/TokenStorageBridge.m | 44 ++ .../TokenStorageBridge.swift | 302 ++++++++++++ .../BrowserSessionBridgeTests.swift | 110 +++++ .../KeychainHelperTests.swift | 327 +++++++++++++ .../TokenStorageBridgeTests.swift | 377 ++++++++++++++ packages/react-native-platform/jest.config.js | 29 ++ packages/react-native-platform/package.json | 13 +- .../react-native-platform.podspec | 27 ++ .../src/Credential/TokenStorage.ts | 205 ++++++++ packages/react-native-platform/src/index.ts | 8 + .../src/specs/NativeTokenStorageBridge.ts | 17 + .../test/jest.setupAfterEnv.ts | 8 + .../test/spec/TokenStorage.spec.ts | 459 ++++++++++++++++++ .../test/spec/foo.spec.ts | 5 + .../react-native-platform/test/tsconfig.json | 20 + .../babel.config.cjs | 1 - .../jest.config.js | 21 +- .../test/{jest.setup.js => jest.setup.ts} | 0 .../src/Credential/TokenStorage.ts | 4 + tooling/jest-helpers/package.json | 4 +- .../jest-helpers/react-native/babel.config.js | 9 + tooling/jest-helpers/react-native/helpers.ts | 1 + .../jest-helpers/react-native/jest-preset.js | 35 ++ 59 files changed, 4051 insertions(+), 409 deletions(-) delete mode 100644 e2e/apps/react-native-oidc/app/(login)/_layout.tsx delete mode 100644 e2e/apps/react-native-oidc/app/(login)/index.tsx delete mode 100644 e2e/apps/react-native-oidc/app/(login)/token.tsx create mode 100644 e2e/apps/react-native-oidc/app/(tabs)/credentials.tsx delete mode 100644 e2e/apps/react-native-oidc/app/(tabs)/explore.tsx create mode 100644 e2e/apps/react-native-oidc/app/(tabs)/token.tsx create mode 100644 packages/react-native-platform/android/.gitignore create mode 100644 packages/react-native-platform/android/build.gradle create mode 100644 packages/react-native-platform/android/gradle.properties create mode 100644 packages/react-native-platform/android/gradle/wrapper/gradle-wrapper.jar create mode 100644 packages/react-native-platform/android/gradle/wrapper/gradle-wrapper.properties create mode 100755 packages/react-native-platform/android/gradlew create mode 100644 packages/react-native-platform/android/gradlew.bat create mode 100644 packages/react-native-platform/android/src/main/AndroidManifest.xml create mode 100644 packages/react-native-platform/android/src/main/java/com/okta/reactnativeplatform/OktaReactNativePlatformPackage.kt create mode 100644 packages/react-native-platform/android/src/main/java/com/okta/reactnativeplatform/browserSession/BrowserSessionModule.kt.disabled create mode 100644 packages/react-native-platform/android/src/main/java/com/okta/reactnativeplatform/tokenStorage/TokenStorageModule.kt create mode 100644 packages/react-native-platform/android/src/test/kotlin/com/okta/reactnativeplatform/browserSession/BrowserSessionModuleTest.kt.disabled create mode 100644 packages/react-native-platform/android/src/test/kotlin/com/okta/reactnativeplatform/tokenStorage/TokenStorageModuleTest.kt create mode 100644 packages/react-native-platform/ios/.gitignore create mode 100644 packages/react-native-platform/ios/Package.swift create mode 100644 packages/react-native-platform/ios/Sources/RNBrowserSessionBridge/BrowserSessionBridge.h create mode 100644 packages/react-native-platform/ios/Sources/RNBrowserSessionBridge/BrowserSessionBridge.m create mode 100644 packages/react-native-platform/ios/Sources/RNBrowserSessionBridge/BrowserSessionBridge.swift create mode 100644 packages/react-native-platform/ios/Sources/RNTokenStorageBridge/TokenStorageBridge.h create mode 100644 packages/react-native-platform/ios/Sources/RNTokenStorageBridge/TokenStorageBridge.m create mode 100644 packages/react-native-platform/ios/Sources/RNTokenStorageBridge/TokenStorageBridge.swift create mode 100644 packages/react-native-platform/ios/Tests/RNBrowserSessionBridgeTests/BrowserSessionBridgeTests.swift create mode 100644 packages/react-native-platform/ios/Tests/RNTokenStorageBridgeTests/KeychainHelperTests.swift create mode 100644 packages/react-native-platform/ios/Tests/RNTokenStorageBridgeTests/TokenStorageBridgeTests.swift create mode 100644 packages/react-native-platform/jest.config.js create mode 100644 packages/react-native-platform/react-native-platform.podspec create mode 100644 packages/react-native-platform/src/Credential/TokenStorage.ts create mode 100644 packages/react-native-platform/src/specs/NativeTokenStorageBridge.ts create mode 100644 packages/react-native-platform/test/jest.setupAfterEnv.ts create mode 100644 packages/react-native-platform/test/spec/TokenStorage.spec.ts create mode 100644 packages/react-native-platform/test/spec/foo.spec.ts create mode 100644 packages/react-native-platform/test/tsconfig.json delete mode 100644 packages/react-native-webcrypto-bridge/babel.config.cjs rename packages/react-native-webcrypto-bridge/test/{jest.setup.js => jest.setup.ts} (100%) create mode 100644 tooling/jest-helpers/react-native/babel.config.js create mode 100644 tooling/jest-helpers/react-native/helpers.ts create mode 100644 tooling/jest-helpers/react-native/jest-preset.js diff --git a/.circleci/config.yml b/.circleci/config.yml index 6c98d46..4237dfd 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -20,7 +20,7 @@ executors: resource_class: m4pro.medium jobs: - test-android: + test-rn-webcrypto-android: executor: name: android/android_machine resource_class: large @@ -52,7 +52,7 @@ jobs: path: packages/react-native-webcrypto-bridge/android/build/reports destination: android-test-reports - test-ios: + test-rn-webcrypto-ios: executor: macos steps: - checkout @@ -80,9 +80,71 @@ jobs: path: packages/react-native-webcrypto-bridge/ios/.build destination: ios-build-artifacts + test-rn-platform-android: + executor: + name: android/android_machine + resource_class: large + tag: default + steps: + - checkout + + - restore_cache: + keys: + - gradle-rn-platform-{{ checksum "packages/react-native-platform/android/build.gradle" }} + - gradle-rn-platform- + + - run: + name: Run React Native Platform Android Tests + command: | + cd packages/react-native-platform/android + ./gradlew testDebugUnitTest --info + + - save_cache: + key: gradle-rn-platform-{{ checksum "packages/react-native-platform/android/build.gradle" }} + paths: + - ~/.gradle + - .gradle + + - store_test_results: + path: packages/react-native-platform/android/build/test-results + + - store_artifacts: + path: packages/react-native-platform/android/build/reports + destination: react-native-platform-android-test-reports + + test-rn-platform-ios: + executor: macos + steps: + - checkout + + - restore_cache: + keys: + - swift-spm-rn-platform-{{ checksum "packages/react-native-platform/ios/Package.swift" }} + - swift-spm-rn-platform- + + - run: + name: Run React Native Platform iOS Tests + command: | + cd packages/react-native-platform/ios + swift test --verbose + + - save_cache: + key: swift-spm-rn-platform-{{ checksum "packages/react-native-platform/ios/Package.swift" }} + paths: + - packages/react-native-platform/ios/.build + + - store_test_results: + path: packages/react-native-platform/ios/.build/test-results + + - store_artifacts: + path: packages/react-native-platform/ios/.build + destination: react-native-platform-ios-build-artifacts + workflows: version: 2 build_and_test: jobs: - - test-android - - test-ios + - test-rn-webcrypto-android + - test-rn-webcrypto-ios + - test-rn-platform-android + - test-rn-platform-ios diff --git a/e2e/apps/react-native-oidc/app.config.ts b/e2e/apps/react-native-oidc/app.config.ts index 7509c40..2c4f6b7 100644 --- a/e2e/apps/react-native-oidc/app.config.ts +++ b/e2e/apps/react-native-oidc/app.config.ts @@ -18,6 +18,7 @@ export default ({ config }: ConfigContext) => ({ extra: { env }, + newArchEnabled: true, "android": { "package": "com.anonymous.reporeactnativeoidc" }, diff --git a/e2e/apps/react-native-oidc/app/(login)/_layout.tsx b/e2e/apps/react-native-oidc/app/(login)/_layout.tsx deleted file mode 100644 index aa7f199..0000000 --- a/e2e/apps/react-native-oidc/app/(login)/_layout.tsx +++ /dev/null @@ -1,45 +0,0 @@ -import { Tabs } from 'expo-router'; -import React from 'react'; -import { Platform } from 'react-native'; - -import { HapticTab } from '@/components/HapticTab'; -import { IconSymbol } from '@/components/ui/IconSymbol'; -import TabBarBackground from '@/components/ui/TabBarBackground'; -import { Colors } from '@/constants/Colors'; -import { useColorScheme } from '@/hooks/useColorScheme'; - -export default function TabLayout() { - const colorScheme = useColorScheme(); - - return ( - - , - }} - /> - , - }} - /> - - ); -} diff --git a/e2e/apps/react-native-oidc/app/(login)/index.tsx b/e2e/apps/react-native-oidc/app/(login)/index.tsx deleted file mode 100644 index e3fd92d..0000000 --- a/e2e/apps/react-native-oidc/app/(login)/index.tsx +++ /dev/null @@ -1,85 +0,0 @@ -import { useCallback, useEffect, useState } from 'react'; -import { StyleSheet, Button } from 'react-native'; -import { Image } from 'expo-image'; -import Constants from 'expo-constants'; -import { useAuth } from '@/hooks/useAuth'; - -import ParallaxScrollView from '@/components/ParallaxScrollView'; -import { ThemedText } from '@/components/ThemedText'; -import { ThemedView } from '@/components/ThemedView'; -import { HelloWave } from '@/components/HelloWave'; - - -export default function LoginScreen () { - const { signIn } = useAuth(); - const [ authError, setAuthError ] = useState(null); - - const signInFunc = useCallback(async () => { - try { - await signIn('/(login)/token'); - } - catch (err) { - setAuthError(err as Error); - } - }, [signIn, setAuthError]); - - useEffect(() => { - (async () => { - await signInFunc(); - })(); - }, [signInFunc]); - - let view = ( - <> - Loading... - - - ); - - if (authError) { - view = ( - <> - Error - {authError.message} -