Google Authentication Token return doesn't contain refresh_token

五迷三道 提交于 2019-12-22 09:49:51

问题


I write an example about google api using. Google NodeJS Client library. I have followed the instruction set access_type : 'offline', however the object return doesn't contains refresh_token.

My Code:

var http = require('http');
var express = require('express');
var Session = require('express-session');
var google = require('googleapis');
var plus = google.plus('v1');
var OAuth2 = google.auth.OAuth2;
const ClientId = "251872680446-rvkcvm5mjn1ps32iabf4i2611hcg086e.apps.googleusercontent.com";
const ClientSecret = "F1qG9fFS-QwcrEfZbT8VmUnx";
const RedirectionUrl = "http://localhost:8081/oauthCallback";

var app = express();
app.use(Session({
    secret: 'raysources-secret-19890913007',
    resave: true,
    saveUninitialized: true
}));

function getOAuthClient () {
    return new OAuth2(ClientId ,  ClientSecret, RedirectionUrl);
}

function getAuthUrl () {
    var oauth2Client = getOAuthClient();
    // generate a url that asks permissions for Google+ and Google Calendar scopes
    var scopes = [
      'https://www.googleapis.com/auth/plus.me'
    ];

    var url = oauth2Client.generateAuthUrl({
        access_type: 'offline',
        scope: scopes // If you only need one scope you can pass it as string
    });

    return url;
}

app.use("/oauthCallback", function (req, res) {
    var oauth2Client = getOAuthClient();
    var session = req.session;
    var code = req.query.code;
    oauth2Client.getToken(code, function(err, tokens) {
        console.log("tokens : ", tokens); 
          // Now tokens contains an access_token and an optional refresh_token. Save them.
          if(!err) {
            oauth2Client.setCredentials(tokens);
            session["tokens"]=tokens;
            res.send(`
                <html>
                <body>
                    <h3>Login successful!!</h3>
                    <a href="/details">Go to details page</a>
                <body>
                <html>
            `);
          }
          else{
            res.send(`
                <html>
                <body>
                    <h3>Login failed!!</h3>
                </body>
                </html>
            `);
          }
    });
});

app.use("/details", function (req, res) {
    var oauth2Client = getOAuthClient();
    oauth2Client.setCredentials(req.session["tokens"]);

    var p = new Promise(function (resolve, reject) {
        plus.people.get({ userId: 'me', auth: oauth2Client }, function(err, response) {
            console.log("response : " , response);
            resolve(response || err);
        });
    }).then(function (data) {
        res.send(`<html><body>
            <img src=${data.image.url} />
            <h3>Hello ${data.displayName}</h3>
            </body>
            </html>
        `);
    })
});

app.use("/", function (req, res) {
    var url = getAuthUrl();
    res.send(`
        <html>
        <body>
<h1>Authentication using google oAuth</h1>
        <a href=${url}>Login</a>
        </body>
        </html>
    `)
});


var port = 8081;
var server = http.createServer(app);
server.listen(port);
server.on('listening', function () {
    console.log(`listening to ${port}`);
});

回答1:


The refresh token is only sent once the first time user login to your application after approving the scopes you have specified.

Edit 08/2018 : Using approval_prompt:'force' no longer works, you need to use prompt:'consent' (check @Alexander's answer)

If you want to get the refresh token each time user login (even if user has already login before and approved the scopes), you have to specify prompt:'consent' in Oauth2Client configuration :

var url = oauth2Client.generateAuthUrl({
    access_type: 'offline',
    scope: scopes,
    prompt : 'consent'
});

Note that this will require user to accept the specified scope each time he/she will click on your link to authenticate :

You can also disable manually the application in your account permission settings, this will revoke the application and the user will have to accept the scopes again that will trigger the refresh_token to be sent the next time you authenticate :

FYI, if you need to use access_token offline, you have to store the refresh_token server side, and refresh the access_token with the stored refresh_token when you receive status 401 from Google API. So, if you store refresh_token as you should, there is actually no need to use prompt:'consent' and force user to approve the scopes each time he/she connects to your application.




回答2:


According the documentation the refresh_token is only returned on the first authorization.

You can remove the permissions manually on: https://myaccount.google.com/permissions

Also you can force the user to see the consent screen again by passing &prompt=consent in the authorization URL, just add this parameter:

var url = oauth2Client.generateAuthUrl({
  access_type: 'offline',
  scope: scopes,
  prompt: 'consent'
});

It worked just fine for me :)




回答3:


In some cases (Web clients mostly) the refresh token is only sent the first time the user is authenticated.

If you go to apps connected to your account remove the app in question. Then try and authenticated again. Check and there should now be a refresh token.



来源:https://stackoverflow.com/questions/42522749/google-authentication-token-return-doesnt-contain-refresh-token

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!