Skip to main content
The AuthenticationToken class represents an authentication token received from iOS Limited Login. It wraps an OpenID Connect token that can be used to verify a user’s identity but cannot access the Graph API.
AuthenticationToken is iOS only and is used with Limited Login. For traditional login, use AccessToken instead.

Import

import { AuthenticationToken } from 'react-native-fbsdk-next';

Static Methods

getAuthenticationTokenIOS

Retrieves the current authentication token (iOS only).
static getAuthenticationTokenIOS(): Promise<AuthenticationToken | null>

Returns

Promise<AuthenticationToken | null> - Resolves with an AuthenticationToken instance if Limited Login was used, or null otherwise. Platform: iOS only (returns null on Android)

Example

import { AuthenticationToken } from 'react-native-fbsdk-next';
import { Platform } from 'react-native';

async function checkAuthToken() {
  if (Platform.OS !== 'ios') {
    console.log('Authentication tokens are iOS only');
    return;
  }
  
  const authToken = await AuthenticationToken.getAuthenticationTokenIOS();
  
  if (authToken) {
    console.log('Limited Login detected');
    console.log('Auth Token:', authToken.authenticationToken);
    console.log('Nonce:', authToken.nonce);
    console.log('Graph Domain:', authToken.graphDomain);
    
    // Send to your server for validation
    await validateTokenOnServer(authToken);
  } else {
    console.log('No authentication token (using traditional login)');
  }
}

Checking Login Type

import { Platform } from 'react-native';
import {
  AccessToken,
  AuthenticationToken,
} from 'react-native-fbsdk-next';

async function getLoginType() {
  if (Platform.OS === 'ios') {
    const authToken = await AuthenticationToken.getAuthenticationTokenIOS();
    if (authToken) {
      return 'limited';
    }
  }
  
  const accessToken = await AccessToken.getCurrentAccessToken();
  if (accessToken) {
    return 'traditional';
  }
  
  return 'not_logged_in';
}

const loginType = await getLoginType();
console.log('Login type:', loginType);

Instance Properties

authenticationToken

The raw OpenID Connect token string from the authentication response.
authenticationToken: string
This token cannot be used to access the Facebook Graph API. Attempting to do so will result in an error: “Invalid OAuth access token - Cannot parse access token”

Example

const authToken = await AuthenticationToken.getAuthenticationTokenIOS();

if (authToken) {
  console.log('Token:', authToken.authenticationToken);
  
  // Send to your server for validation
  const response = await fetch('https://your-api.com/auth/facebook', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      token: authToken.authenticationToken,
      nonce: authToken.nonce,
    }),
  });
  
  const userData = await response.json();
  console.log('User verified:', userData);
}

nonce

The nonce from the decoded authentication response. Used for validating the authentication attempt.
nonce: string
The nonce is a unique string that prevents replay attacks. You should verify that this nonce matches the one you provided (or was generated) during login.

Example

import { AuthenticationToken } from 'react-native-fbsdk-next';

const authToken = await AuthenticationToken.getAuthenticationTokenIOS();

if (authToken) {
  console.log('Nonce:', authToken.nonce);
  
  // Verify nonce matches expected value
  const expectedNonce = await getStoredNonce();
  if (authToken.nonce !== expectedNonce) {
    console.error('Nonce mismatch - possible replay attack!');
    // Handle security issue
  }
}

graphDomain

The graph domain where the user is authenticated.
graphDomain: string
Typically this will be "facebook" for standard Facebook users.

Example

const authToken = await AuthenticationToken.getAuthenticationTokenIOS();

if (authToken) {
  console.log('Graph Domain:', authToken.graphDomain);
  // Usually: "facebook"
}

Types

AuthenticationTokenMap

type AuthenticationTokenMap = {
  authenticationToken: string;
  nonce: string;
  graphDomain: string;
}
Represents the raw authentication token data returned from the native SDK.
PropertyTypeDescription
authenticationTokenstringThe OpenID Connect token string
noncestringThe nonce used for validation
graphDomainstringThe graph domain (usually “facebook”)

Server-Side Validation

Authentication Tokens must be validated on your server. Here’s how to implement it:

Client Side: Send Token to Server

import { AuthenticationToken } from 'react-native-fbsdk-next';
import { Platform } from 'react-native';

async function loginAndVerify() {
  if (Platform.OS !== 'ios') {
    console.log('Authentication tokens are iOS only');
    return;
  }
  
  const authToken = await AuthenticationToken.getAuthenticationTokenIOS();
  
  if (!authToken) {
    console.log('No authentication token available');
    return;
  }
  
  try {
    // Send to your server for validation
    const response = await fetch('https://your-api.com/auth/verify-facebook', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        token: authToken.authenticationToken,
        nonce: authToken.nonce,
      }),
    });
    
    if (!response.ok) {
      throw new Error('Validation failed');
    }
    
    const userData = await response.json();
    console.log('User validated:', userData);
    
    return userData;
  } catch (error) {
    console.error('Token validation failed:', error);
    throw error;
  }
}

Server Side: Validate Token (Node.js Example)

// Server-side code (Node.js with Express)
const express = require('express');
const jwt = require('jsonwebtoken');
const jwksClient = require('jwks-rsa');

const app = express();
app.use(express.json());

// Configure JWKS client
const client = jwksClient({
  jwksUri: 'https://www.facebook.com/.well-known/oauth/openid/jwks/',
  cache: true,
  cacheMaxAge: 86400000, // 24 hours
});

function getKey(header, callback) {
  client.getSigningKey(header.kid, (err, key) => {
    if (err) {
      callback(err);
      return;
    }
    const signingKey = key.publicKey || key.rsaPublicKey;
    callback(null, signingKey);
  });
}

app.post('/auth/verify-facebook', async (req, res) => {
  const { token, nonce } = req.body;
  
  try {
    // Verify and decode the JWT
    const decoded = await new Promise((resolve, reject) => {
      jwt.verify(
        token,
        getKey,
        {
          algorithms: ['RS256'],
          audience: process.env.FACEBOOK_APP_ID,
          issuer: 'https://www.facebook.com',
        },
        (err, decoded) => {
          if (err) reject(err);
          else resolve(decoded);
        }
      );
    });
    
    // Verify nonce
    if (decoded.nonce !== nonce) {
      return res.status(400).json({ error: 'Invalid nonce' });
    }
    
    // Token is valid
    res.json({
      valid: true,
      userId: decoded.sub,
      email: decoded.email,
      name: decoded.name,
    });
  } catch (error) {
    console.error('Token validation failed:', error);
    res.status(401).json({ error: 'Invalid token' });
  }
});

app.listen(3000);
See Facebook’s validation documentation for complete details.

Complete Usage Example

import React, { useState, useEffect } from 'react';
import {
  View,
  Text,
  Button,
  StyleSheet,
  Platform,
  Alert,
} from 'react-native';
import {
  LoginManager,
  AuthenticationToken,
  AccessToken,
  Profile,
} from 'react-native-fbsdk-next';

function LimitedLoginExample() {
  const [user, setUser] = useState(null);
  const [loginType, setLoginType] = useState(null);
  const [tokenInfo, setTokenInfo] = useState(null);
  
  useEffect(() => {
    checkLoginStatus();
  }, []);
  
  const checkLoginStatus = async () => {
    try {
      const profile = await Profile.getCurrentProfile();
      
      if (profile) {
        setUser(profile);
        
        // Check which login type
        if (Platform.OS === 'ios') {
          const authToken = await AuthenticationToken.getAuthenticationTokenIOS();
          
          if (authToken) {
            setLoginType('limited');
            setTokenInfo({
              type: 'Authentication Token',
              token: authToken.authenticationToken.substring(0, 20) + '...',
              nonce: authToken.nonce,
              graphDomain: authToken.graphDomain,
            });
          } else {
            const accessToken = await AccessToken.getCurrentAccessToken();
            if (accessToken) {
              setLoginType('traditional');
              setTokenInfo({
                type: 'Access Token',
                token: accessToken.accessToken.substring(0, 20) + '...',
                userId: accessToken.userID,
              });
            }
          }
        } else {
          const accessToken = await AccessToken.getCurrentAccessToken();
          if (accessToken) {
            setLoginType('traditional');
            setTokenInfo({
              type: 'Access Token',
              token: accessToken.accessToken.substring(0, 20) + '...',
              userId: accessToken.userID,
            });
          }
        }
      }
    } catch (error) {
      console.error('Error checking login status:', error);
    }
  };
  
  const handleLogin = async () => {
    try {
      const result = await LoginManager.logInWithPermissions(
        ['public_profile', 'email'],
        Platform.OS === 'ios' ? 'limited' : undefined
      );
      
      if (result.isCancelled) {
        return;
      }
      
      await checkLoginStatus();
      
      // If using Limited Login, verify token on server
      if (Platform.OS === 'ios') {
        const authToken = await AuthenticationToken.getAuthenticationTokenIOS();
        if (authToken) {
          await verifyTokenOnServer(authToken);
        }
      }
    } catch (error) {
      console.error('Login failed:', error);
      Alert.alert('Login Failed', error.message);
    }
  };
  
  const verifyTokenOnServer = async (authToken) => {
    try {
      const response = await fetch('https://your-api.com/auth/verify', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          token: authToken.authenticationToken,
          nonce: authToken.nonce,
        }),
      });
      
      const data = await response.json();
      
      if (data.valid) {
        console.log('Token verified successfully');
        Alert.alert('Success', 'Login verified!');
      } else {
        throw new Error('Invalid token');
      }
    } catch (error) {
      console.error('Token verification failed:', error);
      Alert.alert('Error', 'Token verification failed');
    }
  };
  
  const handleLogout = () => {
    LoginManager.logOut();
    setUser(null);
    setLoginType(null);
    setTokenInfo(null);
  };
  
  return (
    <View style={styles.container}>
      {user ? (
        <>
          <Text style={styles.title}>Welcome, {user.name}!</Text>
          <Text style={styles.subtitle}>User ID: {user.userID}</Text>
          
          <View style={styles.infoBox}>
            <Text style={styles.infoTitle}>Login Information</Text>
            <Text style={styles.infoText}>
              Type: {loginType === 'limited' ? 'Limited Login' : 'Traditional Login'}
            </Text>
            {loginType === 'limited' && Platform.OS === 'ios' && (
              <Text style={styles.warningText}>
                ⚠️ Limited features available - Graph API not accessible
              </Text>
            )}
          </View>
          
          {tokenInfo && (
            <View style={styles.tokenBox}>
              <Text style={styles.tokenTitle}>Token Info</Text>
              <Text style={styles.tokenText}>Type: {tokenInfo.type}</Text>
              <Text style={styles.tokenText}>Token: {tokenInfo.token}</Text>
              {tokenInfo.nonce && (
                <Text style={styles.tokenText}>Nonce: {tokenInfo.nonce}</Text>
              )}
              {tokenInfo.graphDomain && (
                <Text style={styles.tokenText}>
                  Domain: {tokenInfo.graphDomain}
                </Text>
              )}
            </View>
          )}
          
          <Button title="Logout" onPress={handleLogout} />
        </>
      ) : (
        <>
          <Text style={styles.title}>Facebook Login Example</Text>
          <Text style={styles.description}>
            This example demonstrates iOS Limited Login.
            {Platform.OS === 'ios'
              ? ' Limited Login will be used automatically if ATT is denied.'
              : ' Android always uses traditional login.'}
          </Text>
          <Button title="Login with Facebook" onPress={handleLogin} />
        </>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
    justifyContent: 'center',
    backgroundColor: '#f5f5f5',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 10,
    textAlign: 'center',
  },
  subtitle: {
    fontSize: 16,
    color: '#666',
    marginBottom: 20,
    textAlign: 'center',
  },
  description: {
    fontSize: 14,
    color: '#666',
    marginBottom: 30,
    textAlign: 'center',
  },
  infoBox: {
    backgroundColor: 'white',
    padding: 15,
    borderRadius: 8,
    marginBottom: 15,
  },
  infoTitle: {
    fontSize: 18,
    fontWeight: 'bold',
    marginBottom: 10,
  },
  infoText: {
    fontSize: 16,
    marginBottom: 5,
  },
  warningText: {
    fontSize: 14,
    color: '#ff9800',
    marginTop: 10,
  },
  tokenBox: {
    backgroundColor: '#e3f2fd',
    padding: 15,
    borderRadius: 8,
    marginBottom: 20,
  },
  tokenTitle: {
    fontSize: 16,
    fontWeight: 'bold',
    marginBottom: 10,
  },
  tokenText: {
    fontSize: 12,
    fontFamily: 'monospace',
    marginBottom: 5,
  },
});

export default LimitedLoginExample;

Limitations

Important Limitations of Authentication Tokens:
  1. Cannot access Graph API - Authentication Tokens cannot be used to make Graph API requests
  2. iOS only - This feature is not available on Android
  3. Limited user data - You can only get basic profile information through the Profile API
  4. Server validation required - Tokens must be validated on your backend
  5. No permission scopes - Cannot request extended permissions like user_photos, user_posts, etc.

See Also

Limited Login

Learn about iOS Limited Login

AccessToken

Traditional login access tokens

Authentication Concepts

Understand authentication in React Native FBSDK

Login Methods

Different ways to implement Facebook Login

Build docs developers (and LLMs) love