I am trying to authenticate my users using laravel sanctum API in my react native application.
When the user logs in or registers I would store the information in AsyncStorage.
But it seems that it does not store the information or keep it persistent. For instance when i log in the information of the useState for userInfo is correct and allows me to log in, but whenever I console.log the AsyncStorage of the stored useState of the userInfo this is what is logged. and when i close the app and open it again it returns me back to the log in screen and not the dashboard screen.
How can I use AsyncStorage to keep my users logged in and log them out? As in remove the AsyncStorage that i have set? Because whenever i try to logout using my logout API route it gives me a 401 axios error.
What am I doing wrong, and how can I make my application utilize the AsyncStorage for Authentication (login,register,logout)?
Here is my code
Laravel Auth API:
public function login(Request $request){
$validator = Validator::make($request->all(),[
'email' => 'required|email|max:191',
'password' => 'required',
]);
if($validator->fails()){
return response()->json([
'validation_errors' => $validator->messages(),
]);
}else{
$user = User::where('email', $request->email)->first();
if(!$user || !Hash::check($request->password, $user->password)){
return response()->json([
'status' => 401,
'message' => "Incorret Email or Password",
]);
}else{
//1 means admin
if($user->role_as == 1){
$role = 'admin';
$token = $user->createToken($user->email . '_token',['server:admin'])->plainTextToken;
}else{
$role = '';
$token = $user->createToken($user->email . '_token',[''])->plainTextToken;
}
return response()->json([
'status' => 200,
'username' => $user->name,
'token' => $token,
'message' => 'Logged in Successfully',
'role' => $role
]);
}
}
}
public function logout(){
auth()->user()->tokens()->delete();
return response()->json([
'status' => 200,
'message' => 'Logged out Successfully',
]);
}
App.js
//andorid
axios.defaults.baseURL = "http://10.0.2.2:8000/";
//ios
// axios.defaults.baseURL = "http://localhost:8000/";
axios.defaults.headers.post["Accept"] = "application/json";
axios.defaults.headers.post["Content-Type"] = "application/json";
axios.defaults.withCredentials = true;
axios.interceptors.request.use(function (config) {
const token = AsyncStorage.getItem("auth_token");
config.headers.Authorization = token ? `Bearer ${token}` : "";
return config;
});
const App = () => {
return (
<Providers/>
)
}
Navigation.js
const Stack = createNativeStackNavigator();
const Navigation = () => {
const { userInfo } = useContext(AuthContext);
const user = AsyncStorage.getItem("userInfo");
console.log(user);
return (
<NavigationContainer>
{userInfo.username ? <AppStack /> : <AuthStack />}
</NavigationContainer>
);
};
AuthContext.js:
export const AuthContext = createContext();
export const AuthProvider = ({children}) => {
const [userInfo, setUserInfo] = useState([])
const [isLoading, setIsLoading] = useState(false)
const login = async (email,password) => {
axios.get("/sanctum/csrf-cookie").then((response) => {
setIsLoading(true)
axios.post("/api/login", {
email,
password
}).then( async (res) => {
if (res.data.status === 200) {
console.log(res.data)
setUserInfo(res.data)
AsyncStorage.setItem("userInfo", JSON.stringify(userInfo));
AsyncStorage.setItem("auth_token", res.data.token);
AsyncStorage.setItem("auth_name", res.data.username);
setIsLoading(false)
} else if (res.data.status === 401) {
setLoginError(res.data.message)
setIsLoading(false)
} else {
setLoginErrorList(res.data.validation_errors);
setIsLoading(false)
}
}).catch(e => {
setIsLoading(false)
});;
});
}
const logout = () => {
setIsLoading(true)
axios.post("/api/logout").then((res) => {
if (res.data.status === 200) {
console.log(res.data)
AsyncStorage.removeItem("auth_token")
setUserInfo([])
setIsLoading(false)
}else{
console.log("error")
}
}).catch(e => {
console.log(e)
setIsLoading(false)
});;
}
return (
<AuthContext.Provider value={{
isLoading,
userInfo,
registerErrorList,
loginErrorList,
loginError,
register,
login,
logout,
}}>
{children}
</AuthContext.Provider>
)
};
CodePudding user response:
@Osama Jamal , see the problem youre getting while console logging is that ,
AsyncStorage.getItem()
returns a promise, and if you dont await
for its result
,
the console.log
which youll get is a Promise
this is a promise.
what you need to do is here
const Stack = createNativeStackNavigator();
const Navigation = async() => {
const { userInfo } = useContext(AuthContext);
const user = await AsyncStorage.getItem("userInfo"); // add await here and on top make it an async function like i did in line 2
console.log(user);
return (
<NavigationContainer>
{userInfo.username ? <AppStack /> : <AuthStack />}
</NavigationContainer>
);
};
Hope it helps. feel free for doubts