Redirect_uri fetch 和 gapi 不匹配

Redirect_uri mismatch in fetch and gapi

正在努力将用户连接到 google,我们正在尝试从 google api 获取他们的访问和刷新令牌,我们在交换令牌的 OAuth2 代码。两组代码都有同样的错误。

我初始化 gapi 客户端并像这样填写所需的信息:

gapi.load('client:auth2', _ => {
        gapi.client.init({
            'apiKey': 'omitted for security',
            clientId: 'omitted for security',
            'scope': 'https://www.googleapis.com/auth/drive',
            'discoveryDocs': ['https://www.googleapis.com/discovery/v1/apis/drive/v3/rest']    
        }).then(_ => {
            gapi.auth2.getAuthInstance().grantOfflineAccess().then(resp => {
                if(resp.code){
                    gapi.client.request({
                        path: 'https://www.googleapis.com/oauth2/v4/token',
                        method: 'post',
                        params: {code: resp.code},
                        body: {
                            code: resp.code,
                            client_id: opts.clientId,
                            client_secret: 'omitted for security',
                            grant_type: 'authorization_code',
                            redirect_uri: 'omitted for security',
                            access_type: 'offline'
                        },
                    }).then((onfulfill, onreject, context) => {
                        console.log('fulfilled', onfulfill);
                        console.log('rejected: ', onreject);
                        console.log('context', context);
                    }).catch(err => console.error(err.body));
                }
            });

        });
    });

我在 .then() 中尝试做的是调用令牌端点以交换响应中的代码以获取刷新和访问令牌以存储在我的后端和用户的本地存储中。

我从两个版本的代码中都得到了这个错误响应。 (这里提供了更好、更可靠的代码。)

{ "error": "redirect_uri_mismatch", "error_description": "Bad Request" }

我还有一个后端设置作为最后的手段隐藏起来,它接受来自 gapi.auth2.getAuthInstance().grantOfflineAccess() 的代码调用令牌端点,并且 returns access_tokenrefresh_token 到客户。

此代码类似,但不完全相同。我没有使用 google api 库,而是使用了 fetch,它工作正常。 (前端的Fetch和XHR和gapi.client.request函数有同样的问题....)

const gConfig = require('./basic.json');
const scopes = ['https://www.googleapis.com/auth/drive'];

const { client_id, client_secret, redirect_uris } = gConfig.web;
const authClient = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);

app.post('/', (req, res) => {
    const { code } = req.body;
    console.log('Received Code From Request: ', code);

    let data = { code , client_id, client_secret,redirect_uri: redirect_uris[0], grant_type: 'refresh_token'};

    let encodedParams = Object.keys(data).map(k => encodeURIComponent(k) + '=' + encodeURIComponent(data[k])).join('&');


    fetch(
        `https://www.googleapis.com/oauth2/v4/token?code=${code}`,
        { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: encodedParams }
    ).then((res) => {
        console.log('called the api with fetch');
        console.dir(res.json());
    });

    authClient.getToken(code, (err, token) => {
        if (err) {
            console.error(err);
            res.status(500).json(err);
        }
        // console.dir(token);
        console.log('TOKEN: =>', token);
        res.json(token);
    });
});

有没有人在前端成功做到这一点?

您无法在浏览器中获取刷新令牌。您的示例代码只能在服务器上运行。要在客户端进行 oauth,您应该请求 "token" 而不是 "code".