节点Google OAuth2 redirect_uri_mismatch [英] Node Google OAuth2 redirect_uri_mismatch

查看:118
本文介绍了节点Google OAuth2 redirect_uri_mismatch的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

附带的是我的Google凭据窗口的屏幕快照,其中包含我的重定向URI,右侧是它在请求中发送的由Nodejs Google OAuth2客户端注册的redirectURI,但我的响应仍返回 redirect_uri_mismatch

Attached is a screenshot of my google credentials window with my redirect URIs and on the right the redirectURI registered by the Nodejs Google OAuth2 client that it is sending in the request yet my the response still returns redirect_uri_mismatch

有什么主意吗?

推荐答案

出现问题是因为我试图交换通过我提供的非 offline access_type 前端google plus js api.我找不到一种方法,可以通过其弹出式窗口从Google检索完整的脱机访问 code ,然后将其发送到我的服务器以换取长期存在的令牌.

Turns out the problem arose because I was trying to exchange a non offline access_type provided to me via the frontend google plus js api. I could not find a way to retrieve a full offline access code from google via their popup to send to my server to exchange for a long living token.

我建立了自己的弹出式重定向流程.我没有找到任何资源来进行不带重定向的完整身份验证而没有重定向主页的正确方法,所以我即兴发挥了作用.我愿意改进,但这对我有用,无论如何,如果有人想这样做,这也是我的工作流程.

I built my own popup redirect flow. I could not find any resources for the correct way to do a full auth with a popup without redirecting the main page so I improvised. I'm open to improvements but this works for me, anyways if anyone wants to do this also here's my workflow.

如何设置自己的弹出式oauth身份验证流程

您将需要将auth URL传递到nodejs googleapis库可以轻松实现的前端:

You will need to pass the auth url to the front end which the nodejs googleapis library makes easy with:

url = this.oauth2Client.generateAuthUrl(access_type: 'offline', scope: myScope)

以某种方式将其传递给前端,然后当用户在网站上启动oauth按钮时,它将打开弹出窗口(请求1),同时发送一个请求(请求2),等待最终结果

Pass that to the front-end somehow, next when the user initiates the oauth button on the website it opens the popup (request 1), and at the same time sends a request (request 2) which waits for the final result

// Front end Angular function to initiate the popup
signup: function(callback) {
  this.$window.open(googleOauthURL, 'Authenticate Google', 'width=600, height=600');
  return this.$http.get('auth/google/awaiting').success(function(res) {
    return callback(res);
  });
}

在后端,这是响应请求2 的coffeescript代码.我添加了一个150秒的超时时间,该超时时间是:如果我们在150秒内未收到用户的身份验证凭据响应,请关闭连接. (我们不想挂断连接)

On the backend here's the coffeescript code which responds to request 2. I added a 150 second timeout, which says: if we don't get a response from the user with his auth credentials within 150 seconds then close the connection. (we don't want hanging connections)

exports.awaiting = (req, res) ->
    # Build a unique listener for the correct ip address
    listener = 'oauthAwait-' + req.ip

    # Clear any possible pre-existing listener
    google.removeAllListeners(listener)

    timeoutProtect = setTimeout ->
        google.removeAllListeners(listener)
        timeoutProtect = null

        res.json
            success: false
            error: 'Timedout'
            data: null
    , timeoutLength

    google.once listener, (result) ->
        if timeoutProtect
            clearTimeout(timeoutProtect)

            res.json(result)# return the data

接下来,我们等待用户验证弹出窗口.当他们这样做时,它将重定向到我们在开发控制台中指定的 redirect uri .我们的服务器将获取代码,并向Google发出寿命很长的 access_token 请求,并拥有我们所需要的.

Next we wait on the user to authenticate the popup. When they do it will redirect to the redirect uri we specified in our dev console. Our server will get the code, make a request to google for the long living access_token, with that we have what we need.

exports.oauthCallback = (req, res) ->
    listener = 'oauthAwait-' + req.ip

    successCallback = (user) ->
        user.success = true
        # trigger the request 2 listener with the data
        google.emit(listener, user)

    failCallback = (err) ->
        error.success = false
        google.emit(listener, error)

    exchangeToken(req, req.query.sessionState)
        .then(doSomethingWithToken, failCallback)
        .then(successCallback, failCallback)
        .fin ->
            # return a page that closes itself to the popup (request 1)
            res.render 'oauthPopupCallback'

在这里,我们交换令牌,然后对其进行处理.一旦获得用户,我们就会触发绑定在 exports.awaiting 部分的事件发射器侦听器,该侦听器会将我们的数据返回给应用程序,最后,我们将一个简单的html页面发送给带有javascript的弹出窗口一条标有window.close()

Here the we exchange the token then do something with it. Once we get the user we trigger the event emitter listener that we binded in the exports.awaiting section which will return our data to the application, and finally we send a simple html page to the popup with a javascript one liner that says window.close()

然后,我们在后端有一个经过完全身份验证的用户access_token.如果用户支持,可以使用Web套接字来代替挂起请求,从而改善这一点.

Then there we have a fully authenticated user access_token on the back end. This could be improved by using the web sockets if the user supported it, to replace the hanging request.

修改
发现在名为 window.opener 的弹出窗口中可以使用这种花哨的方法.打开了弹出窗口.从本质上讲,这取代了挂起并等待弹出窗口响应的请求2.

Edit
Found out there's this dandy method available on popups called window.opener which gives access to the window that opened the popup. Essentially this replaces the need for request 2 that hangs and waits for the response of the popup.

在弹出窗口中,您可以使用JavaScript将数据传递到主窗口,例如:

In your popup, you can have a javascript that passes the data along to the main window like:

var service = ResponseData,
    callback = 'on' + service.name + 'Auth';

window.onload = function () {
    window.opener[callback](service.data);
    window.close();
}

这篇关于节点Google OAuth2 redirect_uri_mismatch的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆