Skip to content

Commit

Permalink
prettier and updates
Browse files Browse the repository at this point in the history
  • Loading branch information
moe-dev committed May 8, 2024
1 parent dc1ff11 commit ed96f9c
Show file tree
Hide file tree
Showing 15 changed files with 6,611 additions and 10,908 deletions.
16 changes: 10 additions & 6 deletions App.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import HomeScreen from './Home';
import AuthScreen from './Auth';
import React from "react";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import HomeScreen from "./Home";
import AuthScreen from "./Auth";

const Stack = createNativeStackNavigator();

Expand All @@ -11,7 +11,11 @@ function App() {
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home" component={HomeScreen} />
<Stack.Screen name="AuthScreen" component={AuthScreen} options={{ title: 'Authenticate' }} />
<Stack.Screen
name="AuthScreen"
component={AuthScreen}
options={{ title: "Authenticate" }}
/>
</Stack.Navigator>
</NavigationContainer>
);
Expand Down
75 changes: 45 additions & 30 deletions Auth.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,25 @@
import 'react-native-get-random-values'
import React, { useState, useEffect } from 'react';
import { View, Text, TextInput, Button, StyleSheet } from 'react-native';
import {signWithApiKey} from '@turnkey/api-key-stamper'
import {generateP256KeyPair, decryptBundle, getPublicKey, uint8ArrayFromHexString} from '@turnkey/crypto' // TODO: uint8arrayFromHexString Should live in /encoding
import {stringToBase64urlString, uint8ArrayToHexString} from '@turnkey/encoding'
import "react-native-get-random-values";
import React, { useState, useEffect } from "react";
import { View, Text, TextInput, Button, StyleSheet } from "react-native";
import { signWithApiKey } from "@turnkey/api-key-stamper";
import {
generateP256KeyPair,
decryptBundle,
getPublicKey,
} from "@turnkey/crypto";
import {
stringToBase64urlString,
uint8ArrayToHexString,
uint8ArrayFromHexString,
} from "@turnkey/encoding";

const AuthScreen = () => {
const [embeddedKey, setEmbeddedKey] = useState<any>(null);
const [credentialBundle, setCredentialBundle] = useState('');
const [payload, setPayload] = useState('');
const [publicKey, setPublicKey] = useState('');
const [decryptedData, setDecryptedData] = useState('');
const [signature, setSignature] = useState('');
const [credentialBundle, setCredentialBundle] = useState("");
const [payload, setPayload] = useState("");
const [publicKey, setPublicKey] = useState("");
const [decryptedData, setDecryptedData] = useState("");
const [signature, setSignature] = useState("");

useEffect(() => {
handleGenerateKey();
Expand All @@ -22,42 +30,49 @@ const AuthScreen = () => {
const key = generateP256KeyPair();
setEmbeddedKey(key.privateKey);
const targetPubHex = key.publicKeyUncompressed;
console.log(targetPubHex)
console.log("Target Public key:", targetPubHex); // this is your target public key - use this value in email auth
setPublicKey(targetPubHex!);
} catch (error) {
console.error('Error generating key:', error);
console.error("Error generating key:", error);
}
};

const handleInjectBundle = () => {
try{
const decryptedData = decryptBundle(credentialBundle, embeddedKey) as Uint8Array
try {
const decryptedData = decryptBundle(
credentialBundle,
embeddedKey,
) as Uint8Array;

setDecryptedData(uint8ArrayToHexString(decryptedData));
}
catch (error) {
console.error('Error injecting bundle:', error);
setDecryptedData(uint8ArrayToHexString(decryptedData));
} catch (error) {
console.error("Error injecting bundle:", error);
}
};

const handleStampPayload = async () => {
try {
const publicKey = uint8ArrayToHexString(getPublicKey(uint8ArrayFromHexString(decryptedData), true))
const privateKey = decryptedData
const signature = await signWithApiKey({content: payload, publicKey, privateKey} )
const publicKey = uint8ArrayToHexString(
getPublicKey(uint8ArrayFromHexString(decryptedData), true),
);
const privateKey = decryptedData;
const signature = await signWithApiKey({
content: payload,
publicKey,
privateKey,
});
setSignature(signature);
const stamp = {
publicKey: publicKey,
scheme: "SIGNATURE_SCHEME_TK_API_P256",
signature: signature,
};
console.log(stringToBase64urlString(JSON.stringify(stamp)))
console.log("X-Stamp:", stringToBase64urlString(JSON.stringify(stamp))); // use this as your X-Stamp in your requests
} catch (error) {
console.error('Error stamping payload:', error);
console.error("Error stamping payload:", error);
}
};


return (
<View style={styles.container}>
<Text>Email Authentication</Text>
Expand All @@ -76,7 +91,7 @@ const AuthScreen = () => {
placeholder="Enter Payload"
/>
<Button title="Stamp Payload" onPress={handleStampPayload} />
<Text>Decrypted Data: {decryptedData}</Text>
<Text>Decrypted Key: {decryptedData}</Text>
<Text>Signature: {signature}</Text>
</View>
);
Expand All @@ -85,16 +100,16 @@ const AuthScreen = () => {
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
justifyContent: "center",
alignItems: "center",
padding: 20,
},
input: {
height: 40,
margin: 12,
borderWidth: 1,
padding: 10,
width: '100%',
width: "100%",
},
});

Expand Down
90 changes: 56 additions & 34 deletions Home.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
import { StatusBar } from 'expo-status-bar';
import { Button, StyleSheet, Text, View } from 'react-native';
import { PasskeyStamper, createPasskey, isSupported } from "@turnkey/react-native-passkey-stamper";
import { StatusBar } from "expo-status-bar";
import { Button, StyleSheet, Text, View } from "react-native";
import {
PasskeyStamper,
createPasskey,
isSupported,
} from "@turnkey/react-native-passkey-stamper";
import { ApiKeyStamper } from "@turnkey/api-key-stamper";
import { TurnkeyClient } from "@turnkey/http";
import { Buffer } from "buffer";
import { useNavigation } from '@react-navigation/native';
import { useNavigation } from "@react-navigation/native";

const RPID = "passkeyapp.tkhqlabs.xyz"
const RPID = "passkeyapp.tkhqlabs.xyz";

export default function Home() {
const navigation = useNavigation(); // Hook to get the navigation objec
const navigation = useNavigation();
const navigateToAuth = () => {
navigation.navigate('AuthScreen'); // Use the navigate function with the screen name
//@ts-ignore
navigation.navigate("AuthScreen"); // Use the navigate function with the screen name
};

return (
<View style={styles.container}>
<Text style={styles.title}>Native Passkeys + Turnkey</Text>
<Button title='Sign Up' onPress={onPasskeyCreate}></Button>
<Button title='Sign In & get your ID' onPress={onPasskeySignature}></Button>
<Button title='Auth' onPress={navigateToAuth}></Button>
<Button title="Sign Up" onPress={onPasskeyCreate}></Button>
<Button
title="Sign In & get your ID"
onPress={onPasskeySignature}
></Button>
<Button title="Auth Demo" onPress={navigateToAuth}></Button>
<StatusBar style="auto" />
</View>
);
Expand All @@ -28,27 +36,29 @@ export default function Home() {
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
title: {
fontSize: 24,
fontWeight: '600',
fontWeight: "600",
margin: 42,
},
});


async function onPasskeyCreate() {
if (!isSupported()) {
alert("Passkeys are not supported on this device")
alert("Passkeys are not supported on this device");
}

try {
const now = new Date()
const humanReadableDateTime = `${now.getFullYear()}-${now.getMonth()}-${now.getDay()}@${now.getHours()}h${now.getMinutes()}min`
console.log("creating passkey with the following datetime: ", humanReadableDateTime);
const now = new Date();
const humanReadableDateTime = `${now.getFullYear()}-${now.getMonth()}-${now.getDay()}@${now.getHours()}h${now.getMinutes()}min`;
console.log(
"creating passkey with the following datetime: ",
humanReadableDateTime,
);

// ID isn't visible by users, but needs to be random enough and valid base64 (for Android)
const userId = Buffer.from(String(Date.now())).toString("base64");
Expand All @@ -72,13 +82,15 @@ async function onPasskeyCreate() {
residentKey: "required",
requireResidentKey: true,
userVerification: "preferred",
}
})
},
});
console.log("passkey registration succeeded: ", authenticatorParams);
const response = await createSubOrganization(authenticatorParams);
console.log("created sub-org", response)
alert(`Sub-org created! Your ID: ${response.activity.result.createSubOrganizationResultV4?.subOrganizationId}`);
} catch(e) {
console.log("created sub-org", response);
alert(
`Sub-org created! Your ID: ${response.activity.result.createSubOrganizationResultV4?.subOrganizationId}`,
);
} catch (e) {
console.error("error during passkey creation", e);
}
}
Expand All @@ -88,23 +100,33 @@ async function onPasskeySignature() {
const stamper = await new PasskeyStamper({
rpId: RPID,
});
const client = new TurnkeyClient({baseUrl: "https://api.turnkey.com"}, stamper);
const client = new TurnkeyClient(
{ baseUrl: "https://api.turnkey.com" },
stamper,
);
const getWhoamiResult = await client.getWhoami({
organizationId: process.env.EXPO_PUBLIC_TURNKEY_ORGANIZATION_ID
})
organizationId: process.env.EXPO_PUBLIC_TURNKEY_ORGANIZATION_ID,
});
console.log("passkey authentication succeeded: ", getWhoamiResult);
alert(`Successfully logged into sub-organization ${getWhoamiResult.organizationId}`)
} catch(e) {
alert(
`Successfully logged into sub-organization ${getWhoamiResult.organizationId}`,
);
} catch (e) {
console.error("error during passkey signature", e);
}
}

async function createSubOrganization(authenticatorParams: Awaited<ReturnType<typeof createPasskey>>) {
async function createSubOrganization(
authenticatorParams: Awaited<ReturnType<typeof createPasskey>>,
) {
const stamper = new ApiKeyStamper({
apiPublicKey: process.env.EXPO_PUBLIC_TURNKEY_API_PUBLIC_KEY,
apiPrivateKey: process.env.EXPO_PUBLIC_TURNKEY_API_PRIVATE_KEY,
});
const client = new TurnkeyClient({baseUrl: "https://api.turnkey.com"}, stamper);
const client = new TurnkeyClient(
{ baseUrl: "https://api.turnkey.com" },
stamper,
);

const data = await client.createSubOrganization({
type: "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V4",
Expand All @@ -117,10 +139,10 @@ async function createSubOrganization(authenticatorParams: Awaited<ReturnType<typ
{
userName: "Root User",
apiKeys: [],
authenticators: [authenticatorParams]
authenticators: [authenticatorParams],
},
],
}
},
});
return data
return data;
}
Loading

0 comments on commit ed96f9c

Please sign in to comment.