Calm
Calm

Reputation: 51

How to get FB Access Token with Expo

I'm building app where i need to make Facebook Graph API requests in many places. But i dont know how to retrieve access token and then make Graph API request.

I'm using Expo, React Native and Firebase. I would like to do it without installing Xcode and/or Android Studio.

Login is working fine. My code is below:

async loginWithFacebook() {
try {
  const {
    type,
    token,
    expires,
    permissions,
    declinedPermissions,
  } = await Expo.Facebook.logInWithReadPermissionsAsync('<APP_ID', {
    permissions: ['email', 'public_profile'],
  });
  if (type === 'success') {
    const credential = f.auth.FacebookAuthProvider.credential(token)
    f.auth().signInAndRetrieveDataWithCredential(credential).catch((error) => {
      console.log(error)
    })
    var that = this;
    const response = await fetch(`https://graph.facebook.com/me/?fields=id,name&access_token=${token}`);
    const userInfo = await response.json();
    this.setState({userInfo});
    this.setState({
    dataSource: userInfo.data,
    isLoading: false,
    });
  } else {
    // type === 'cancel'
  }
} catch ({ message }) {
  alert(`Facebook Login Error: ${message}`);
}
}

Can someone help me and give me some tips how i can use access token everywhere in my app? Thank you in advance

Upvotes: 3

Views: 3306

Answers (1)

Andrew
Andrew

Reputation: 28539

Getting the token and saving it into AsyncStorage

Well the code that you have written is basically correct. You have successfully got the access token. It comes back to you when you make the Expo.Facebook.logInWithReadPermissionsAsync request. Once you have it you could then store it in Redux or AsyncStorage to be used at a later date.

logIn = async () => {
  let appID = '123456789012345' // <- you'll need to add your own appID here

  try {
    const {
      type,
      token, // <- this is your access token
      expires,
      permissions,
      declinedPermissions,
    } = await Expo.Facebook.logInWithReadPermissionsAsync(appID, { permissions: ['public_profile', 'email'], });

    if (type === 'success') {
      // Get the user's name using Facebook's Graph API
      const response = await fetch(`https://graph.facebook.com/me/?fields=id,name&access_token=${token}`); //<- use the token you got in your request
      const userInfo = await response.json();
      alert(userInfo.name);

      // you could now save the token in AsyncStorage, Redux or leave it in state
      await AsyncStorage.setItem('token', token); // <- save the token in AsyncStorage for later use
    } else {
      // type === 'cancel'
    }

  } catch ({ message }) {
    alert(`Facebook Login Error: ${message}`);
  }
}

app.json

Also remember to add the following to your app.json, obviously replacing the values with your own. You get these by registering your app with Facebook, you can see more about that here https://docs.expo.io/versions/latest/sdk/facebook/#registering-your-app-with-facebook

{ 
  "expo": {
    "facebookScheme": "fb123456789012345",
    "facebookAppId": "123456789012345",  // <- this is the same appID that you require above when making your initial request. 
    "facebookDisplayName": "you_re_facebook_app_name",
    ...
    }
}

Getting token from AsyncStorage

Then if you wanted to make another request at a later time you could have a function similar to this where you get the token out of AsyncStorage and then use it to make your request.

makeGraphRequest = async () => {
  try {
    let token = await AsyncStorage.getItem('token'); // <- get the token from AsyncStorage
    const response = await fetch(`https://graph.facebook.com/me/?fields=id,name&access_token=${token}`); // <- use the token for making the graphQL request
    const userInfo = await response.json();
    alert(userInfo.name)
  } catch (err) {
    alert(err.message)
  }
}

Snack

I would make a snack to show you this working however, snacks do not allow editing of the app.json file (as far as I can tell). So here is something that you could replace your App.js with and then if you added your appIDs etc to the app.json it should work.

import React from 'react';
import { AsyncStorage, Text, View, StyleSheet, SafeAreaView, Button } from 'react-native';


export default class App extends React.Component {

  logIn = async () => {
    let appID = '123456789012345' // <- you'll need to add your own appID here
    try {
      const {
        type,
        token, // <- this is your access token
        expires,
        permissions,
        declinedPermissions,
      } = await Expo.Facebook.logInWithReadPermissionsAsync(appID, {
        permissions: ['public_profile', 'email'],
      });
      if (type === 'success') {
        // Get the user's name using Facebook's Graph API
        const response = await fetch(`https://graph.facebook.com/me/?fields=id,name&access_token=${token}`); //<- use the token you got in your request
        const userInfo = await response.json();
        console.log(userInfo);
        alert(userInfo.name);
        // you could now save the token in AsyncStorage, Redux or leave it in state
        await AsyncStorage.setItem('token', token); // <- save the token in AsyncStorage for later use
      } else {
        // type === 'cancel'
      }
    } catch ({ message }) {
      alert(`Facebook Login Error: ${message}`);
    }
  }

    makeGraphRequest = async () => {
      try {
        let token = await AsyncStorage.getItem('token');
        // Get the user's name using Facebook's Graph API
        const response = await fetch(`https://graph.facebook.com/me/?fields=id,name&access_token=${token}`);
        const userInfo = await response.json();
        alert(userInfo.name)
      } catch (err) {
        alert(err.message)
      }
    }


  render() {
    return (
      <View style={styles.container}>
        <Button title={'Sign in to Facebook'} onPress={this.logIn} />
        <Button  title={'Make GraphQL Request'} onPress={this.makeGraphRequest} />
      </View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'white'
  }
});

Upvotes: 4

Related Questions