How to store facebook token in AsyncStorage React Native(Expo) - react-native

I am using Expo to Login User with Facebook, I am receiving token with Graph Api but when I try to add the token in Async Storage it is not working.
Please see the code below:
async logIn() {
try {
const {
type,
token,
} = await Facebook.logInWithReadPermissionsAsync('<APP_ID>', {
permissions: ['public_profile'],
});
if (type === 'success') {
// Get the user's name using Facebook's Graph API
fetch(`https://graph.facebook.com/me?access_token=${token}`)
.then((res) => res.json())
.then((tokenKey) => AsyncStorage.setItem('userToken',tokenKey))
.then(() => this.props.navigation.navigate('App'))
} else {
// type === 'cancel'
}
} catch ({ message }) {
alert(`Facebook Login Error: ${message}`);
}
}
I am receiving the token when I console it
fetch(`https://graph.facebook.com/me?access_token=${token}`)
.then((res) => res.json())
.then((tokenKey) => console.log('userToken',tokenKey))
.then(() => this.props.navigation.navigate('App'))
Please help, I am new to react native and asynchronous programming in JavaScript. TIA :)

Try this if you want to get item from AsyncStorage
AsyncStorage.getItem('userToken', (error, result) => {
if (result) {
//result
}
else {
//error
}
});

Are you getting token from AsyncStorage with getItem?
AsyncStorage.getItem('userToken').then((token) => {
this.setState({hasToken: token !== null,localToken : token})
});

Sorry folks the problem was from my side, I was trying to store an object directly into Async Storage, whereas Async Storage only accepts values in String format. I used
.then((tokenKey) => AsyncStorage.setItem('userToken',JSON.stringify(tokenKey)))
and it fixed the problem,Thanks all for your help

Related

node_modules/#tanstack/query-core/build/lib/mutation.js:153:10 in Mutation#execute react native expo

I'm buiding React Native Expo App with external rest api.
I have created reusable axios api call:
// axiosAPi.js
export const axiosApi = async (method, url, obj = {}) => {
try {
switch (method) {
case 'GET':
return await axios
.get(`${baseUrl}/${url}`, config)
.then((res) => res.data)
case 'POST':
return await axios
.post(`${baseUrl}/${url}`, obj, config)
.then((res) => res.data)
case 'PUT':
return await axios
.put(`${baseUrl}/${url}`, obj, config)
.then((res) => res.data)
case 'DELETE':
return await axios
.delete(`${baseUrl}/${url}`, config)
.then((res) => res.data)
}
} catch (error) {
throw error?.response?.data?.error
}
}
I have created a hook with login instance using react-query:
// api/index.js
export default function useApiHook() {
const login = useMutation((obj) => axiosApi('POST', `auth/login`, obj))
return { login }
}
Here is the implementation of login screen
// screens/login.js
const loginPostMutation = useApiHook()?.login
const submitHandler = (data) => {
loginPostMutation
?.mutateAsync(data)
?.then((res) => res)
.catch((err) => err)
}
When I send correct credentials is returns the data with no errors, but when I send incorrect credentials it returns the error + this warning in the console:
Invalid credentials
at node_modules/#tanstack/query-core/build/lib/mutation.js:153:10 in Mutation#execute
The line in question points towards react-query logging the error to the console in development mode. Invalid credentials is thus just an error that is returned from axios, very likely, a 401 - Unauthorized error.
You would very likely get the same error when making the axios request without react-query.

Nuxt apollo authentication

I try to build an an authentication with nuxt and apollo.
The login and signup is pretty easy, also to set up the jwt token, but when my token expire and I try to get a refresh token or to logout my user I getting following error.
Invariant Violation
Store reset while query was in flight (not completed in link chain)
Because my Error handler which I define in my nuxt.config.js do not work I try to build my own client.
So I set at apollo.clientConfigs.default my ~/graphql/config.ts which looks like
export default ({ app }: Context) => {
const errorLink = onError(({ graphQLErrors, networkError, operation, forward }) => {
if (graphQLErrors) {
graphQLErrors.map(async (err) => {
if (err?.extensions?.exception.status === 401) {
await app.$apolloHelpers.onLogout()
}
return err
})
return forward(operation)
}
if (networkError) {
console.log(networkError, 'and another one!')
return forward(operation)
}
return forward(operation)
})
return {
httpEndpoint: 'http://localhost:3001/graphql',
link: from([errorLink as any])
}
}

Is User already have Permissions FB SDK react native

I have a simple Question i just want to know that is user first time trying to logged in or else.
I am using react native fb SDK and Im enable to find any way.
I already try but not getting success.
AccessToken.getCurrentAccessToken()
Thanks
This is my login facebook function:
Step is:
Get permission
User login
Get token
My code:
import { LoginManager, AccessToken } from 'react-native-fbsdk';
const loginFacebook = () => {
setTypeLogin(TYPE_LOGIN.FACEBOOK)
if (Platform.OS === "android") {
LoginManager.setLoginBehavior("web_only")
}
LoginManager.logInWithPermissions(['public_profile', 'email']).then(
function (result) {
if (result.isCancelled) {
} else {
AccessToken.getCurrentAccessToken()
.then((data) => {
setAccessToken(data.accessToken)
prepareCallApi()
})
.catch(error => {
console.log(error)
})
}
},
function (error) {
console.log('Login fail with error: ' + error);
},
);
};

Login With React Native using Asyncronous storage

I am implementing login in React Native using Asynchronous storage. Here, when users login successfully, i keep the user object in the Asynchronous storage then i access this information to get the Authentication Key for my API request anytime I want to do a request.
When I login and information is stored in the Asynchronous storage, the current app session fails to get the just stored information hence all my authenticated request fails in this session. When I close the app and restart, I can successfully get the information from the Async storage stored in the previous session and make successful authenticated request.
I do not know what I am missing out in my code as I believe I need to refresh or reload the app internally after a successful login but I do not know how to do this in React Native. Any information or help is needed. Here is my Login code.
HttpRequest.post('api/login', body)
.then((response) => response.json())
.then((responseJson) => {
if(responseJson.succcode == 201){ //successful login
var data = responseJson.user;
data.loggedIn = true;
AsyncStorage.setItem(USER_DATA, JSON.stringify(data)).then(val => {
console.log('just before reload in login')
Actions.menu(); //this solves the after login problem as it goes to the next page only after a successful AsyncStorage save
this.setState({ procesing: false });
})
.catch(err => {
this.setState({ procesing: false, error: "Couldn't log you in! Please try again" });
//console.log("\nCouldn't save to AsyncStorage: " + err + "\n");
});
}
else{
this.setState({ procesing: false, error: "Wrong Username and/or Password! Please try again" });
}
After I have login, my request looks like ;
//for making a post request
post: (url,body) => {
return fetch(url+'?access-token='+this.state.user.auth_key, {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/x-www-form-urlencoded',
//'Autorization': 'Bearer token2'
},
})
but the user object is gotten from the Async storage as
getUser(){
return AsyncStorage.getItem("USER_DATA").then(value => {
if(JSON.parse(value) == null) {
return false;
} else {
return JSON.parse(value)
}
});
},
Any Information, Ideas, proposed solutions are highly welcome
If you are receiving the information correctly, you can pass the information to the next screen or use the asynchronous repository as it is now.
If use navigation
HttpRequest.post('api/login', body)
.then((response) => response.json())
.then((responseJson) => {
if(responseJson.succcode == 201){ //successful login
var data = responseJson.user;
data.loggedIn = true;
this.setState({ procesing: false });
this.navigation.navigate("LoginScreen",{data: JSON.stringify(data) })
}
else{
this.setState({ procesing: false, error: "Wrong Username and/or Password! Please try again" });
}
LoginScreen
this.state={
data : this.props.navigation.state.params.data
}
If use AsyncStorge
HttpRequest.post('api/login', body)
.then((response) => response.json())
.then((responseJson) => {
if(responseJson.succcode == 201){ //successful login
var data = responseJson.user;
data.loggedIn = true;
AsyncStorage.setItem("USER_DATA", JSON.stringify(data));
this.setState({ procesing: false });
else{
this.setState({ procesing: false, error: "Wrong Username and/or Password! Please try again" });
}
LoginScreen
async componentDidMount() {
let data = await AsyncStorage.getItem("USER_DATA")
}

react-native facebook logout

I'm struggling to setup a logout action in my app, considering the User has logged in through Facebook provider (react-native-fbsdk). What is the proper way to setup a logout? So, when Users get back to my App and try to login, email and password should be requested again. pls help
To login I'm using:
LoginManager.logInWithReadPermissions(['public_profile', 'email']);
I have tried to call LoginManager.logOut(), LoginManager.setLoginBehavior('I have tried all types'), but did not revoke permissions.
I've also tried to call GraphRequest as per code below but I didn't get the desired result.
logoutFacebook = () => {
AccessToken.getCurrentAccessToken()
.then(data => {
return data.accessToken.toString();
})
.then(accessToken => {
const logout = new GraphRequest(
'me/permissions/',
{
accessToken,
httpMethod: 'DELETE'
},
(error, result) => {
if (error) {
console.log(`'Error fetching data: '${error.toString()}`);
} else {
console.log(result);
LoginManager.logOut();
}
}
);
new GraphRequestManager().addRequest(logout).start();
})
.catch(error => {
console.log(error);
});
}