簡體   English   中英

Rails 4-帶有omniauth-google-oauth2的Google一次性代碼流,不斷獲取“無效代碼”

[英]Rails 4 - Google One Time Code Flow with omniauth-google-oauth2, keep getting “Invalid code”

我有一個Rails應用程序,我希望用戶能夠在其中登錄/注冊Google。 我正在使用以下寶石:

#gemfile
gem 'omniauth-google-oauth2'

我幾乎可以正常工作了(我實際上只收到一次訪問令牌,不知道為什么)-但是在獲取access_token之前,我經常遇到以下錯誤:

"error"=>"invalid_grant", "error_description"=>"Invalid code."

我已經檢查過了,以便每個請求的代碼都是唯一的,並且它不是nil。 收到一次性授權代碼后,我嘗試獲取access_token的方法的相關部分如下所示:

def google_authentication
  respond_to do |format|
    # authorisation code

    code = params[:code]
    unless code.blank?

      client_id = ENV["GOOGLE_CLIENT_ID"]
      client_secret = ENV["GOOGLE_CLIENT_SECRET"]
      redirect_uri = 'postmessage'
      grant_type = 'authorization_code'

      load = {client_id: client_id, client_secret: client_secret,  redirect_uri: redirect_uri, grant_type: grant_type, code: code}
      payload = load.to_json
      url = "https://www.googleapis.com/oauth2/v3/token"
      response = HTTParty.post(url, :query => load)

      json = JSON.parse(response.body)

      unless json.nil?
        unless json[:error].present?
          # TODO: Handle data      
          format.json { render :json => {:message => "Success"} }              
        else
          # ERROR "Invalid code" always happen
        end
      end
    end
  end
end

在Google開發人員控制台中,我具有以下憑據:

Client ID           [CLient ID]
Email address       [Email]
Client secret       [Secret]
Redirect URIs       http://127.0.0.1:3000/
JavaScript origins  http://127.0.0.1:3000

感謝任何想法或技巧。

更新完成

這是我設置omniauth-google-oauth2的方法:

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :google_oauth2, ENV["GOOGLE_CLIENT_ID"],  ENV["GOOGLE_CLIENT_SECRET"],
    {
      :scope => "email, profile",
      :prompt => "select_account",
      :provider_ignores_state => true
    }
end

更新2

如上所述,我曾經設法獲得訪問令牌一次,然后又設法重現了它。 我通過單擊登錄按鈕三次來做到這一點。

"error"=>"invalid_grant", "error_description"=>"Invalid code."

第二次點擊導致:

"error"=>"invalid_grant", "error_description"=>"Code was already redeemed."

第三次,我成功獲取了access_token 我有時有時會獲得access_token ,這真的很奇怪,但是大多數時候都會得到:

"error"=>"invalid_grant", "error_description"=>"Invalid code."

而且成功/錯誤的“比率”不是100%一致的。 有時需要超過三下單擊。 我感到很奇怪,它有時可以工作,有時會得到不同的錯誤響應,而無需更改代碼中的任何內容。

可能與代碼的時間/到期日期有關嗎?

更新3

額外完成。 這是用戶單擊Google登錄按鈕時我的Javascript(或Cof​​feeScript)的樣子:

$(document).ready ->
  $.ajax
    url: 'https://apis.google.com/js/client:plus.js?onload=gpAsyncInit'
    dataType: 'script'
    cache: true


window.gpAsyncInit = ->
  $('.googleplus-login').click (e) ->
    e.preventDefault()
    gapi.auth.authorize {
      immediate: false
      response_type: 'code'
      cookie_policy: 'single_host_origin'
      client_id: '[id]'
      scope: 'email profile'
    }, (response) ->
      if response and !response.error

        jQuery.ajax
          type: 'POST'
          url: '/auth/google_oauth2/callback'
          dataType: 'json'
          data: response
          success: (json) ->
            # response from server
            console.log "JSON: " + json
            return
      else
        # google authentication failed

對於紅寶石部分,我無法解決,但也許可以幫助您找出問題所在。

實際上,Google的身份驗證服務器返回了3個代碼。 授權代碼,訪問令牌和刷新令牌。

  • 授權代碼只能使用一次才能獲得第一個刷新令牌。
  • 用於訪問api上數據的訪問令牌會在一個小時后過期。
  • 刷新令牌,用於在過期時獲取新的訪問令牌。 直到用戶刪除訪問權限為止。

授權碼

這是當用戶點擊接受您的應用程序時返回的代碼。

例:

將此URI中的客戶端ID,密碼和范圍更改為您正在使用的客戶端ID,密碼和范圍。 然后將其粘貼到瀏覽器位置欄中。

https://accounts.google.com/o/oauth2/auth?client_id={clientid}.apps.googleusercontent.com&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope={scope}&response_type=code

在此處輸入圖片說明

它將提示您進行身份驗證。 如果單擊,則會出現另一個帶有長代碼的窗口,看起來像這樣。

在此處輸入圖片說明

這就是身份驗證代碼,其唯一的目的就是讓您使用它來獲取訪問令牌和刷新令牌。 它只能使用一次 ,雖然我從未測試過它們適合使用多長時間,但它可能壽命很短。

在上面的uri中注意:響應類型代碼。

交換:

獲得該驗證碼后,您需要將其交換為訪問令牌和刷新令牌。 這是HTTP POST,因此不能放在瀏覽器窗口中。

https://accounts.google.com/o/oauth2/token
code=4/X9lG6uWd8-MMJPElWggHZRzyFKtp.QubAT_P-GEwePvB8fYmgkJzntDnaiAI&client_id={ClientId}.apps.googleusercontent.com&client_secret={ClientSecret}&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=authorization_code

注意:grant_type = authorization_code告訴服務器您正在向其發送授權碼。

響應

{
"access_token" : "ya29.1.AADtN_VSBMC2Ga2lhxsTKjVQ_ROco8VbD6h01aj4PcKHLm6qvHbNtn-_BIzXMw",
"token_type" : "Bearer",
"expires_in" : 3600,
"refresh_token" : "1/J-3zPA8XR1o_cXebV9sDKn_f5MTqaFhKFxH-3PUPiJ4"
}

現在,您有了一個可用於訪問Google API的訪問令牌,該令牌的壽命很短,僅持續3600秒或1個小時。 之后,您必須使用刷新令牌才能再次訪問。

使用refreshtoken

https://accounts.google.com/o/oauth2/token
client_id={ClientId}.apps.googleusercontent.com&client_secret={ClientSecret}&refresh_token=1/ffYmfI0sjR54Ft9oupubLzrJhD1hZS5tWQcyAvNECCA&grant_type=refresh_token

響應

{
"access_token" : "ya29.1.AADtN_XK16As2ZHlScqOxGtntIlevNcasMSPwGiE3pe5ANZfrmJTcsI3ZtAjv4sDrPDRnQ",
"token_type" : "Bearer",
"expires_in" : 3600
}

現在您已經了解了所有這些

"error"=>"invalid_grant", "error_description"=>"Code was already redeemed."

表示您要再次發送授權碼,則只能在應該再次發送刷新令牌時使用它。 您的身份驗證流程有問題。 再次抱歉,我無法幫助紅寶石部分。

代碼從Google 3的oauth2流中剝離出來

因此...如其寫道:

授權的重定向URI每行一個URI。 需要具有協議,沒有URL片段和相對路徑。 不能是公共IP地址。

您的設置:

重定向URI http://127.0.0.1:3000/ JavaScript起源http://127.0.0.1:3000/

...是錯的。

它應該是:

重定向URI: http://my.true.domain/users/auth/google/callback

 provider :google_oauth2, ENV["GOOGLE_CLIENT_ID"],  ENV["GOOGLE_CLIENT_SECRET"],
    {
      :scope => "email, profile",
      :name => "google",
      ...

希望對您有所幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM