diff --git a/package.json b/package.json
index 9dcfae4d87..cbd8d5437a 100644
--- a/package.json
+++ b/package.json
@@ -186,7 +186,7 @@
"react-native": "^0.79.3",
"react-native-compressor": "^1.11.0",
"react-native-date-picker": "^5.0.12",
- "react-native-device-attest": "^0.1.1",
+ "react-native-device-attest": "^0.1.4",
"react-native-drawer-layout": "^4.1.8",
"react-native-edge-to-edge": "^1.6.0",
"react-native-gesture-handler": "2.25.0",
diff --git a/src/screens/Signup/StepCaptcha/index.tsx b/src/screens/Signup/StepCaptcha/index.tsx
index c5d1a60e26..6a38fd9135 100644
--- a/src/screens/Signup/StepCaptcha/index.tsx
+++ b/src/screens/Signup/StepCaptcha/index.tsx
@@ -1,12 +1,13 @@
-import React from 'react'
-import {ActivityIndicator, View} from 'react-native'
+import React, {useEffect, useState} from 'react'
+import {ActivityIndicator, Platform, View} from 'react-native'
+import ReactNativeDeviceAttest from 'react-native-device-attest'
import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {nanoid} from 'nanoid/non-secure'
import {createFullHandle} from '#/lib/strings/handles'
import {logger} from '#/logger'
-import {isWeb} from '#/platform/detection'
+import {isAndroid, isIOS, isNative, isWeb} from '#/platform/detection'
import {ScreenTransition} from '#/screens/Login/ScreenTransition'
import {useSignupContext} from '#/screens/Signup/state'
import {CaptchaWebView} from '#/screens/Signup/StepCaptcha/CaptchaWebView'
@@ -16,9 +17,56 @@ import {BackNextButtons} from '../BackNextButtons'
const CAPTCHA_PATH = isWeb ? '/gate/signup' : '/gate/signup/attempt-attest'
-type
-
export function StepCaptcha() {
+ if (isWeb) {
+ return
+ } else {
+ return
+ }
+}
+
+export function StepCaptchaNative() {
+ const [token, setToken] = useState()
+ const [payload, setPayload] = useState()
+ const [ready, setReady] = useState(false)
+
+ useEffect(() => {
+ ;(async () => {
+ logger.debug('trying to generate attestation token...')
+ try {
+ if (isIOS) {
+ logger.debug('starting to generate devicecheck token...')
+ const token = await ReactNativeDeviceAttest.getDeviceCheckToken()
+ setToken(encodeURIComponent(token))
+ logger.debug(`generated devicecheck token: ${token}`)
+ } else {
+ const {token, payload} =
+ await ReactNativeDeviceAttest.getIntegrityToken('signup')
+ setToken(encodeURIComponent(token))
+ setPayload(encodeURIComponent(base64UrlEncode(payload)))
+ }
+ } catch (e: any) {
+ logger.error(e)
+ } finally {
+ setReady(true)
+ }
+ })()
+ }, [])
+
+ if (!ready) {
+ return
+ }
+
+ return
+}
+
+function StepCaptchaInner({
+ token,
+ payload,
+}: {
+ token?: string
+ payload?: string
+}) {
const {_} = useLingui()
const theme = useTheme()
const {state, dispatch} = useSignupContext()
@@ -27,6 +75,7 @@ export function StepCaptcha() {
const stateParam = React.useMemo(() => nanoid(15), [])
const url = React.useMemo(() => {
+ console.log(`service url: ${state.serviceUrl}`)
const newUrl = new URL(state.serviceUrl)
newUrl.pathname = CAPTCHA_PATH
newUrl.searchParams.set(
@@ -36,8 +85,26 @@ export function StepCaptcha() {
newUrl.searchParams.set('state', stateParam)
newUrl.searchParams.set('colorScheme', theme.name)
+ if (isNative && token) {
+ newUrl.searchParams.set('platform', Platform.OS)
+ newUrl.searchParams.set('token', token)
+ if (isAndroid && payload) {
+ newUrl.searchParams.set('payload', payload)
+ }
+ }
+
+ console.log(newUrl.href)
+
return newUrl.href
- }, [state.serviceUrl, state.handle, state.userDomain, stateParam, theme.name])
+ }, [
+ state.serviceUrl,
+ state.handle,
+ state.userDomain,
+ stateParam,
+ theme.name,
+ token,
+ payload,
+ ])
const onSuccess = React.useCallback(
(code: string) => {
@@ -108,3 +175,13 @@ export function StepCaptcha() {
)
}
+
+function base64UrlEncode(data: string): string {
+ const encoder = new TextEncoder()
+ const bytes = encoder.encode(data)
+
+ const binaryString = String.fromCharCode(...bytes)
+ const base64 = btoa(binaryString)
+
+ return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/[=]/g, '')
+}
diff --git a/yarn.lock b/yarn.lock
index 3fff9ffbde..cfb327c48a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -16787,10 +16787,10 @@ react-native-date-picker@^5.0.12:
resolved "https://registry.yarnpkg.com/react-native-date-picker/-/react-native-date-picker-5.0.12.tgz#12540b6a58500811ee7e4fc0244e3accc7cca9c1"
integrity sha512-R/mUnCKhcuxbhKPFwYdBQCxQt9HHLqpM4ruRUqlcBjiUZ3N2wdnwOMyc888Ps8qp8e7v29PrDHtUlG8LPuFn9w==
-react-native-device-attest@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/react-native-device-attest/-/react-native-device-attest-0.1.1.tgz#5aa55bad2fcc964228656d1b764fb87625afe888"
- integrity sha512-dOOaCWPzEISdMubtCbwExhjOe7izZmAUbdk790FCBVqq09Vqepxt/vn2zRKyy4EoUBG8LKLMg22kCko6TJNoPA==
+react-native-device-attest@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/react-native-device-attest/-/react-native-device-attest-0.1.4.tgz#221860443765422f6dfebf4d868f367cda2a61b1"
+ integrity sha512-jFogWXXl3NBEAA3U+f1NQwdeIysCu6bGEmMGzz6gw4uipe6ELxZmovx64cJJHessZs1gjYDaUcbXGncirwykYg==
react-native-dotenv@^3.4.11:
version "3.4.11"