/
AuthScreen.main.tsx
113 lines (102 loc) · 3.83 KB
/
AuthScreen.main.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
import { SafeAreaView } from "react-native-safe-area-context";
import { Image, Text, Platform } from "react-native";
import React from "react";
import firebase from "firebase";
import { styles } from "./AuthScreen.styles";
import * as Crypto from "expo-crypto";
import * as AppleAuthentication from "expo-apple-authentication";
const logo = require("../../../assets/icon.png");
/* AuthScreen is the only "authentication" screen that this app has.
Usually, we'll want a couple of different screens in this stack
(e.g. Sign In, Sign Up, etc.) but for simplicity, this app only
has one screen. Here, we set up boilerplate code that deals with
Sign in with Apple. If you're going for something like this,
you'll probably want to look at the latest Sign in with Apple
code via Firebase/Expo - this might be a little outdated.
https://docs.expo.io/versions/latest/sdk/apple-authentication/
https://docs.expo.io/guides/using-firebase/#listening-for-authentication
At a high level, this is a two-step process:
1. Attempt to sign in with Apple. This returns a credential
if it succeeds (AppleAuthentication.signInAsync).
2. Pass the credential to Firebase, to tie the Apple account
to Firebase Authentication.
If any step of this fails, we simply log an error, but
you'll probably want to display an alert to the user.
*/
export const AuthScreen = () => {
const registerWithFirebase = async (
credential: firebase.auth.OAuthCredential,
name: string | null | undefined
) => {
try {
await firebase.auth().signInWithCredential(credential);
console.log("firebase signInWithCredential completed successfully.");
const displayName = firebase.auth().currentUser?.displayName;
if (!displayName) {
firebase.auth().currentUser?.updateProfile({
displayName: name,
});
}
} catch (error) {
console.log("firebase signInWithCredential failed: ", error);
}
};
const signInPressed = async () => {
const csrf = Math.random().toString(36).substring(2, 15);
const nonce = Math.random().toString(36).substring(2, 10);
const hashedNonce = await Crypto.digestStringAsync(
Crypto.CryptoDigestAlgorithm.SHA256,
nonce
);
try {
const credential = await AppleAuthentication.signInAsync({
requestedScopes: [
AppleAuthentication.AppleAuthenticationScope.FULL_NAME,
AppleAuthentication.AppleAuthenticationScope.EMAIL,
],
state: csrf,
nonce: hashedNonce,
});
const provider = new firebase.auth.OAuthProvider("apple.com");
const authCredential = provider.credential({
idToken: credential.identityToken!,
rawNonce: nonce,
});
await registerWithFirebase(
authCredential,
credential.fullName?.givenName
);
// At this point, this user should be signed in!
// The EntryStackScreen will automatically switch to the
// RootStack, so we don't need to explicitly
} catch (e) {
if (e.code === "ERR_CANCELED") {
console.log("User cancelled signInWithApple");
} else {
console.log("signInWithApple error: ", e);
}
}
};
const appleButton = () => {
if (Platform.OS == "ios") {
return (
<AppleAuthentication.AppleAuthenticationButton
buttonType={AppleAuthentication.AppleAuthenticationButtonType.SIGN_IN}
buttonStyle={AppleAuthentication.AppleAuthenticationButtonStyle.BLACK}
cornerRadius={5}
style={styles.appleButtonView}
onPress={signInPressed}
/>
);
} else {
return null;
}
};
return (
<SafeAreaView style={styles.container}>
<Image source={logo} style={styles.logo} />
<Text style={styles.title}>Feeds</Text>
{appleButton()}
</SafeAreaView>
);
};