-
Notifications
You must be signed in to change notification settings - Fork 4
/
Home.tsx
148 lines (137 loc) · 4.4 KB
/
Home.tsx
1
2
3
4
5
6
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
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";
const RPID = "passkeyapp.tkhqlabs.xyz";
export default function Home() {
const navigation = useNavigation();
const navigateToAuth = () => {
//@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 Demo" onPress={navigateToAuth}></Button>
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
title: {
fontSize: 24,
fontWeight: "600",
margin: 42,
},
});
async function onPasskeyCreate() {
if (!isSupported()) {
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,
);
// 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");
const authenticatorParams = await createPasskey({
// This doesn't matter much, it will be the name of the authenticator persisted on the Turnkey side.
// Won't be visible by default.
authenticatorName: "End-User Passkey",
rp: {
id: RPID,
name: "Passkey App",
},
user: {
id: userId,
// ...but name and display names are
// We insert a human-readable date time for ease of use
name: `Key @ ${humanReadableDateTime}`,
displayName: `Key @ ${humanReadableDateTime}`,
},
authenticatorSelection: {
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.error("error during passkey creation", e);
}
}
async function onPasskeySignature() {
try {
const stamper = await new PasskeyStamper({
rpId: RPID,
});
const client = new TurnkeyClient(
{ baseUrl: "https://api.turnkey.com" },
stamper,
);
const getWhoamiResult = await client.getWhoami({
organizationId: process.env.EXPO_PUBLIC_TURNKEY_ORGANIZATION_ID,
});
console.log("passkey authentication succeeded: ", getWhoamiResult);
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>>,
) {
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 data = await client.createSubOrganization({
type: "ACTIVITY_TYPE_CREATE_SUB_ORGANIZATION_V4",
timestampMs: String(Date.now()),
organizationId: process.env.EXPO_PUBLIC_TURNKEY_ORGANIZATION_ID,
parameters: {
subOrganizationName: `Sub-organization at ${String(Date.now())}`,
rootQuorumThreshold: 1,
rootUsers: [
{
userName: "Root User",
apiKeys: [],
authenticators: [authenticatorParams],
},
],
},
});
return data;
}