DEV Community

Cathy Lai
Cathy Lai

Posted on • Edited on

Login with Google on an iPhone (Local Metro server + Dev Build) - Part 6/7: Login Page

From the last session, we implemented the _layout.tsx file in Step 5. Now we will write the login.tsx page:

app/
├── (auth)/
│   └── login.tsx     <--- this tutorial 
├── (protected)/
│   └── protected.tsx
├── _layout.tsx       <--- done 
└── index.tsx
Enter fullscreen mode Exit fullscreen mode

Login page

This file will do the following things:

  1. Prepare the browser session
  2. Create deep link
  3. Start the OAuth flow
  4. Activate the session & redirect the user

1. Completing the browser auth session
We will tell Expo to finalize and clean up that browser session so the app can regain control.

WebBrowser.maybeCompleteAuthSession();
Enter fullscreen mode Exit fullscreen mode

2. Create deep link
Create the deep link that the OAuth provider will come back to

const redirectUrl = Linking.createURL("/oauth-native-callback");
Enter fullscreen mode Exit fullscreen mode

Expo automatically prefixes this path with our app’s scheme:

oauthpro2://oauth-native-callback
Enter fullscreen mode Exit fullscreen mode

Our app's scheme:

app.json

{"expo": 
    {"name": "oauth-pro2",
     "scheme": "oauthpro2",         <--- App's scheme name
      ...
Enter fullscreen mode Exit fullscreen mode

3. Start the OAuth flow

const { createdSessionId, setActive } =
  await startOAuthFlow({ redirectUrl });
Enter fullscreen mode Exit fullscreen mode

4. Make it active & redirects

if (createdSessionId) {
  // activate the created session
  await setActive({ session: createdSessionId });
  // redirect to the protected page
  router.replace("/protected");
}
Enter fullscreen mode Exit fullscreen mode

Complete source code

login.tsx

import { useOAuth } from "@clerk/clerk-expo";
import * as Linking from "expo-linking";
import { Link, useRouter } from "expo-router";
import * as WebBrowser from "expo-web-browser";
import React from "react";
import { ActivityIndicator, Text, TouchableOpacity, View } from "react-native";

WebBrowser.maybeCompleteAuthSession();

export default function Login() {
  const { startOAuthFlow } = useOAuth({ strategy: "oauth_google" });
  const router = useRouter();
  const [loading, setLoading] = React.useState(false);

  /// Google Login button handler////
  const onGoogleSignInPress = async () => {
    try {
      setLoading(true);

      // Creates a deep link by prefixing the path with the app scheme/host.
      // Example: myapp://oauth-native-callback (must match Clerk redirect config in Step 2).
      const redirectUrl = Linking.createURL("/oauth-native-callback");

      // Clerk's OAuth flow
      // Starts the OAuth browser flow and returns the created session (if any)
      // plus a helper to activate it in the Clerk client.
      const { createdSessionId, setActive } = await startOAuthFlow({redirectUrl, });

      if (createdSessionId) {
         // call the setActive helper with the createdSessionId to tell Clerk
         // which session should be active on the device
         await  setActive!({ session:  createdSessionId });
         router.replace("/protected");
      }
    } catch (err) {
      console.error("OAuth error:", JSON.stringify(err, null, 2));
    } finally {
      setLoading(false);
    }
  };

  return (
    <View>
      <Text>Login</Text>

      <TouchableOpacity
        onPress={onGoogleSignInPress}
        disabled={loading}
      >
        {loading ? (
          <ActivityIndicator color="#3A2F2F" />
        ) : (
          <Text> Sign in with Google </Text>
        )}
      </TouchableOpacity>
    </View>
  );
}
Enter fullscreen mode Exit fullscreen mode

Preview of the final flow!

Google Login

Google Login: Permission

Google Login Choose Account

Google Login Login Confirm

Protected Screen

Yes! It logged us in and landed us to the protected screen :)

For reference, the source code is hosted on:
GitHub: OAuth Prototype
https://github.com/pscientist/oauth-pro2

Next we will work on the Logout button so it completes the flow!

app/
├── (auth)/
│   └── login.tsx     <--- done 
├── (protected)/
│   └── protected.tsx <--- next to do
├── _layout.tsx       <--- done 
└── index.tsx
Enter fullscreen mode Exit fullscreen mode

Top comments (0)