I am quite new in app development with Expo (react native). 我正在尝试从我的应用程序(供私人使用)访问Google Drive API,以使该应用程序读取一些在我的Google Drive中特定文件夹中的文件。 I have a google service account active for my app with editor's role. I have shared a specific google drive folder with this service account. 我正在开发构建中使用Expo(不是Expo Go)。
您可以帮助我了解如何在没有用户登录的情况下正确使用Expo应用程序的Google Drive API? 非常感谢!我阅读了很多文档,并在Chatgpt的帮助下尝试了不同的代码。 建议我使用“ Google-auth-library”(请参见下面的代码),但是在启动应用程序时,我总是会遇到以下错误(我正在在Web浏览器上进行测试):“ Uncaucht TypeError: 原型可能仅是一个对象或null:未定义”。 (删除该代码时,我没有这个错误,所以它确实来自那里)
博览会文档始终将重定向到“@react-native-google-signin/google-signin”库,但chatgpt告诉我,只有在我希望我的用户登录时才可以使用它,情况并非如此(我确实如此)不需要任何用户身份验证,因此使用服务帐户)。
这里是我的代码:
import Constants from 'expo-constants';
import { GoogleAuth } from 'google-auth-library';
import axios from 'axios';
// Extraction des informations du compte de service depuis app.json
const {
GOOGLE_PROJECT_ID,
GOOGLE_CLIENT_EMAIL,
GOOGLE_PRIVATE_KEY,
GOOGLE_PRIVATE_KEY_ID,
GOOGLE_CLIENT_ID,
} = Constants.expoConfig?.extra || {};
// Correction de la clé privée qui peut contenir des caractères échappés
const privateKeyFormatted = GOOGLE_PRIVATE_KEY.replace(/\\n/g, '\n');
/**
* Fonction pour authentifier et obtenir un jeton d'accès Google Drive
* @returns {Promise<string>} Jeton d'accès à utiliser pour les appels API
*/
export const authenticateGoogleDrive = async (): Promise<string> => {
try {
if (!GOOGLE_CLIENT_EMAIL || !GOOGLE_PRIVATE_KEY || !GOOGLE_PROJECT_ID) {
throw new Error('Les informations du compte de service sont manquantes');
}
console.log("Before GoogleAuth");
console.log("GOOGLE_CLIENT_EMAIL: ", GOOGLE_CLIENT_EMAIL);
console.log("privateKeyFormatted: ", privateKeyFormatted);
console.log("GOOGLE_PROJECT_ID: ", GOOGLE_PROJECT_ID);
// Création de l'objet d'authentification avec uniquement les champs nécessaires
const auth = new GoogleAuth({
credentials: {
type: 'service_account',
project_id: GOOGLE_PROJECT_ID,
private_key: privateKeyFormatted,
client_email: GOOGLE_CLIENT_EMAIL,
},
scopes: ['https://www.googleapis.com/auth/drive'],
});
const client = await auth.getClient();
const token = await client.getAccessToken();
if (!token.token) {
throw new Error('Impossible d’obtenir le jeton d’accès');
}
return token.token;
} catch (error) {
console.error('Erreur d’authentification Google:', error);
throw error;
}
};
there终于有效的地方:
import Constants from 'expo-constants';
import { KJUR } from 'jsrsasign';
// Charger les variables d'environnement
const GOOGLE_PROJECT_ID = Constants.expoConfig?.extra?.GOOGLE_PROJECT_ID || '';
const GOOGLE_CLIENT_ID = Constants.expoConfig?.extra?.GOOGLE_CLIENT_ID || '';
const GOOGLE_CLIENT_EMAIL = Constants.expoConfig?.extra?.GOOGLE_CLIENT_EMAIL || '';
const GOOGLE_PRIVATE_KEY = (Constants.expoConfig?.extra?.GOOGLE_PRIVATE_KEY || '');
const GOOGLE_PRIVATE_KEY_ID = (Constants.expoConfig?.extra?.GOOGLE_PRIVATE_KEY_ID || '');
const GOOGLE_FOLDER_ID = Constants.expoConfig?.extra?.GOOGLE_FOLDER_ID || '';
const SERVICE_ACCOUNT_EMAIL = GOOGLE_CLIENT_EMAIL;
const PRIVATE_KEY = GOOGLE_PRIVATE_KEY;
const TOKEN_URI = 'https://oauth2.googleapis.com/token';
export async function getAccessToken() {
const now = Math.floor(Date.now() / 1000);
const jwtHeader = { alg: 'RS256', typ: 'JWT' };
const jwtPayload = {
iss: SERVICE_ACCOUNT_EMAIL,
scope: 'https://www.googleapis.com/auth/drive.readonly',
aud: TOKEN_URI,
exp: now + 3600, // expiration dans 1 heure
iat: now,
};
// Générer le JWT signé en RS256
const sHeader = JSON.stringify(jwtHeader);
const sPayload = JSON.stringify(jwtPayload);
const jwt = KJUR.jws.JWS.sign('RS256', sHeader, sPayload, PRIVATE_KEY);
// Construire le corps de la requête en x-www-form-urlencoded
const body = new URLSearchParams();
body.append('grant_type', 'urn:ietf:params:oauth:grant-type:jwt-bearer');
body.append('assertion', jwt);
const response = await fetch(TOKEN_URI, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: body.toString(),
});
const data = await response.json();
if (!data.access_token) {
throw new Error(`Erreur lors de la récupération du token : ${JSON.stringify(data)}`);
}
return data.access_token;
}