Expo Auth Session

55.0.15 · active · verified Wed Apr 22

Expo Auth Session is a foundational module within the Expo ecosystem for implementing web browser-based authentication flows, such as OAuth 2.0 and OpenID Connect, across Android, iOS, and web platforms. It provides a unified API to manage the complexities of these authentication methods, leveraging `expo-web-browser` for browser interaction and `expo-crypto` for secure operations like Proof Key for Code Exchange (PKCE), which is now the recommended grant type over implicit flow due to enhanced security. The current stable version is 55.0.15, with releases typically synchronized with major Expo SDK updates, occurring approximately three times per year. Key differentiators include its seamless integration with Expo development builds and managed workflow capabilities, simplifying the setup of deep linking and redirect URIs across various environments, and providing hooks like `useAuthRequest` for easy React component integration.

Common errors

Warnings

Install

Imports

Quickstart

This example demonstrates a basic GitHub OAuth login flow using the `useAuthRequest` hook and `makeRedirectUri`. It showcases how to initiate the authentication process, handle success and error responses, and securely retrieve an authorization code for backend exchange. It also includes the necessary `WebBrowser.maybeCompleteAuthSession()` call for web compatibility and deep linking setup for native platforms.

import React, { useEffect } from 'react';
import { Button, View, Text, StyleSheet } from 'react-native';
import * as WebBrowser from 'expo-web-browser';
import { makeRedirectUri, useAuthRequest } from 'expo-auth-session';

// Required for WebBrowser.maybeCompleteAuthSession() on web
WebBrowser.maybeCompleteAuthSession();

const discovery = {
  authorizationEndpoint: 'https://github.com/login/oauth/authorize',
  tokenEndpoint: 'https://github.com/login/oauth/access_token',
  revocationEndpoint: 'https://api.github.com/applications/YOUR_CLIENT_ID/token',
};

export default function GitHubLogin() {
  const redirectUri = makeRedirectUri({
    scheme: 'your-app-scheme',
    // useProxy: true, // Only for testing with Expo Go, deprecated since SDK 48
  });

  const [request, response, promptAsync] = useAuthRequest(
    {
      clientId: process.env.GITHUB_CLIENT_ID ?? '', // Replace with your GitHub OAuth App Client ID
      scopes: ['user', 'repo', 'gist'],
      redirectUri,
    },
    discovery
  );

  useEffect(() => {
    if (response?.type === 'success') {
      const { code } = response.params;
      console.log('Authorization code:', code);
      // In a real app, you would exchange the 'code' for an access token on your backend server.
      // For local testing, you might fetch it directly if safe and for demonstration.
    } else if (response?.type === 'cancel') {
      console.log('Authentication flow canceled.');
    } else if (response?.type === 'error') {
      console.error('Authentication error:', response.error?.message);
    }
  }, [response]);

  return (
    <View style={styles.container}>
      <Text style={styles.header}>GitHub OAuth Example</Text>
      <Button
        disabled={!request}
        title="Login with GitHub"
        onPress={() => promptAsync()}
      />
      {response && response.type === 'success' && (
        <Text style={styles.status}>Logged in successfully!</Text>
      )}
      {response && response.type === 'error' && (
        <Text style={styles.error}>Login failed: {response.error?.message}</Text>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  header: {
    fontSize: 24,
    marginBottom: 20,
  },
  status: {
    marginTop: 20,
    color: 'green',
  },
  error: {
    marginTop: 20,
    color: 'red',
  },
});

view raw JSON →