react-native-google-signin / google-signin

Google Sign-in for your React Native applications
https://react-native-google-signin.github.io/
MIT License
3.12k stars 877 forks source link

Retrieve Refresh Token for Google Calendar in React Native #1279

Closed amalikmuhd closed 1 month ago

amalikmuhd commented 1 month ago

Hi,

I'm currently working on integrating Google Calendar into my React Native app. While attempting to access the refresh token, I utilized the following code snippet:

const tokens = await GoogleSignin.getTokens();
console.log(tokens)

However, upon execution, I noticed that only the accessToken and idToken are returned. I expected to also receive the refresh token, but it seems to be missing. Could you please advise me on how to obtain the refresh token?

Thank you!

import React from 'react';
import { View, Button, Text, StyleSheet } from 'react-native';
import {
  GoogleSignin,
  statusCodes
} from '@react-native-google-signin/google-signin';

const CalendarComponent = () => {
  const [userInfo, setUserInfo] = React.useState(null);
  const [events, setEvents] = React.useState([]);
  const [error, setError] = React.useState(null);

  const signIn = async () => {
    try {
      await GoogleSignin.hasPlayServices();
      const userInfo = await GoogleSignin.signIn();
      const tokens = await GoogleSignin.getTokens();
      setUserInfo(userInfo);
      await fetchCalendarEvents(tokens.accessToken);
    } catch (error) {
      if (error.code === statusCodes.SIGN_IN_CANCELLED) {
        // User cancelled the login flow
        setError('Sign in cancelled');
      } else if (error.code === statusCodes.IN_PROGRESS) {
        // Operation (e.g. sign in) is in progress already
        setError('Sign in operation in progress');
      } else if (error.code === statusCodes.PLAY_SERVICES_NOT_AVAILABLE) {
        // Play services not available or outdated
        setError('Google Play services not available');
      } else {
        // Some other error happened
        setError('Error signing in');
      }
    }
  };

  const fetchCalendarEvents = async accessToken => {
    try {
      const response = await fetch(
        'https://www.googleapis.com/calendar/v3/calendars/primary/events',
        {
          method: 'GET',
          headers: {
            Authorization: `Bearer ${accessToken}`,
            Accept: 'application/json'
          }
        }
      );

      if (!response.ok) {
        throw new Error('Failed to fetch events');
      }
      const data = await response.json();
      setEvents(data.items);
    } catch (error) {
      setError('Error fetching events');
    }
  };

  return (
    <View style={styles.container}>
      {!userInfo ? (
        <Button title="Sign in with Google" onPress={() => signIn()} />
      ) : (
        <>
          <Text>Welcome, {userInfo.user.name}</Text>
          {error && <Text style={styles.errorStyle}>{error}</Text>}
          <Button
            title="Sign out"
            onPress={() => {
              GoogleSignin.signOut();
              setUserInfo(null);
              setEvents([]);
              setError(null);
            }}
          />
          <Text>Your Calendar Events:</Text>
          <View>
            {events.map((event, index) => (
              <View key={index} style={{ marginVertical: 5 }}>
                <Text>{event.summary}</Text>
              </View>
            ))}
          </View>
        </>
      )}
    </View>
  );
};

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

  errorStyle: {
    color: 'red'
  }
});

export default CalendarComponent;
vonovak commented 1 month ago

Hello and thanks for asking,

I'm not aware of an native api that would expose the refresh token. You can (1) call getTokens() repeatedly or (2) request server-side access (offline access) and exchange the returned code for new tokens. If you find an android api that returns refresh token, please let me know.

Thank you 🙂