Google API: токен доступа не обновляется - PullRequest
0 голосов
/ 18 января 2020

Я пытаюсь реализовать следующую логику c:

  1. Пользователь открывает страницу моего сайта и нажимает кнопку

  2. всплывающее окно показывает запрос согласия на загрузку файлов на его диск Google

  3. Пользователи соглашаются, я беру auth_code, получаю доступ и повторно получаю sh токены

  4. Когда обязательно позже, я загружаю некоторые документы на его диск Google, не спрашивая разрешения.

Первые 3 пункта, наконец, работают. Код на стороне клиента (ReactJS):

componentWillMount() {
    let script = document.createElement('script');
    script.setAttribute('id', 'google_script');
    const self = this;
    script.onload = function() {
        gapi.load('auth2', ()=>{
            const clientId = window.googleClientId;
            const scope = 'https://www.googleapis.com/auth/drive https://www.googleapis.com/auth/drive.file';
            let config = {
                clientId: clientId,
                scope: scope
            };
            self.googleAuth = gapi.auth2.init(config);
        });
    };
    script.src = "https://apis.google.com/js/platform.js";
    document.getElementsByTagName('head')[0].appendChild(script);
};

// Затем

buttonClick(){
    this.googleAuth.grantOfflineAccess().then((data)=>{ //<== Offline access
        if (data.code){
            this.saveGoogleDriveToken(data.code); //<-- Sends to the server
        } else {

        }
    });
}

Серверная часть, обменивающая код на токены.

def get_tokens(auth_code):
    json_path = os.path.join(static_folder_path, "client_secrets.json")
    credentials = None
    try:
        credentials = client.credentials_from_clientsecrets_and_code(
            json_path,
            scopes,
            auth_code)
    except Exception as ex:
        print(ex)
        return None
    return {
        'access_token': credentials.access_token,
        'refresh_token': credentials.refresh_token
    }

Я сохраняю эти 2 токена в базе данных. Позже, когда я хочу загрузить документы:

    credentials = google.oauth2.credentials.Credentials(user_access_token,
                                                        refresh_token = user_refresh_token,
                                                        token_uri = 'https://oauth2.googleapis.com/token',
                                                        client_id = get_config_var('GOOGLE_CLIENT_ID'),
                                                        client_secret = get_config_var('GOOGLE_CLIENT_SECRET')
    )

drive_service = build('drive', 'v3', credentials=credentials)
fd = io.BytesIO(invoice_file_bytes)
body = {'name': invoice_file_name, 'mimeType': 'application/pdf'}
media_body = MediaIoBaseUpload(fd = fd, mimetype='application/pdf')
file = drive_service.files().create(body=body,
                                            media_body=media_body,
                                            fields='id').execute() #<== When hit here

Но я не могу заставить его работать. Это сработало вскоре после того, как пользователь дал согласие, но не через 1 час (я думаю, что после истечения срока действия токена доступа) у меня есть 'invalid_client: Unauthorized', '{\ n "error": "invalid_client", \ n "error_description": "Unauthorized" \ n} ')

Я читаю google api, могу самостоятельно обновить sh токен доступа, но не могу понять, как заставить его работать.

1 Ответ

0 голосов
/ 18 января 2020

Используемая вами библиотека API Google не позволяет вам обновить sh токен доступа из кода на стороне клиента по соображениям безопасности. Вам придется обновить sh токен с вашего сервера python кода, если срок его действия истек в get_tokens.

    credentials = google.oauth2.credentials.Credentials(user_access_token,
                                                        refresh_token = user_refresh_token,
                                                        token_uri = 'https://oauth2.googleapis.com/token',
                                                        client_id = get_config_var('GOOGLE_CLIENT_ID'),
                                                        client_secret = get_config_var('GOOGLE_CLIENT_SECRET')
    )
http = cred.authorize(httplib2.Http())
credentials.refresh(http)
drive_service = build('drive', 'v3', credentials=credentials)
fd = io.BytesIO(invoice_file_bytes)
body = {'name': invoice_file_name, 'mimeType': 'application/pdf'}
media_body = MediaIoBaseUpload(fd = fd, mimetype='application/pdf')
file = drive_service.files().create(body=body,
                                            media_body=media_body,
                                            fields='id').execute() #<== When hit here
...