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
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
"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;
}
| Property | Type | Description |
|---|---|---|
authenticationToken | string | The OpenID Connect token string |
nonce | string | The nonce used for validation |
graphDomain | string | The 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);
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:
- Cannot access Graph API - Authentication Tokens cannot be used to make Graph API requests
- iOS only - This feature is not available on Android
- Limited user data - You can only get basic profile information through the Profile API
- Server validation required - Tokens must be validated on your backend
- 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