Cannot get oAuth2 Access Token for Google Analytics API

偶尔善良 提交于 2019-12-04 09:46:37

I've soldiered through this over the last few weeks, so let me share what worked:

To use Oauth2 you need to get a 'refresh token' that you use to 're-authenticate' with google each time you make an API call. The steps for this are as follows:

1) Setup your account in the API console - https://code.google.com/apis/console/b/0/ (seems like you've done that well) 2) In your API account, make sure you have a redirect URI pointing back to your application:

http://some-url.com/auth/google_oauth2/callback
http://localhost:3000/auth/google_oauth2/callback

Note here that google won't let you call back to your local machine as 0.0.0.0:3000... so you'll need to use localhost explicitly

3) In your route file, tie that redirect url to an action in the controller where you're going to create the project or authentication

match '/auth/:provider/callback' => 'authentications#create'

The ':provider' simply lets you match on multiple types of oauth, but you could just put 'google_oauth2' there as well.

4) Now create that action in your controller

def create
  auth = request.env["omniauth.auth"] 
  params = request.env["omniauth.params"]
  project = Project.find(params['project_id'])

  Authentication.create(:project_id => project.id, :provider => auth['provider'], :uid => auth['uid'], :access_token => auth['credentials']['refresh_token'])
  flash[:notice] = "Authentication successful."
  redirect_to owner_view_project_path(project)
end

5) The controller action should retrieve the relevant fields from the response object (details of response object here: https://github.com/zquestz/omniauth-google-oauth2) - in particular, you need to get the 'refresh_token' and save that to your project or authentication object - if you haven't added an 'access_token' attribute to the desired object, go do that now with a migration, then start saving the refresh token to that attribute

6) Now when you're ready to call that particular authentication and get API data for it, you can load up that object where you saved the access token, and use that to get a new session with the google API as follows:

  @authentication = Authentications.find(params[:id])

  client = OAuth2::Client.new GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET,
                                  {
                                    :site => 'https://accounts.google.com',
                                    :authorize_url => "/o/oauth2/auth",
                                    :token_url => "/o/oauth2/token",
                                  }
  response = OAuth2::AccessToken.from_hash(client, :refresh_token => @authentication.access_token).refresh!
  Garb::Session.access_token = response
  @profiles = Garb::Management::Profile.all

What this code did was create an OAuth2 access token (response) by specifying the client and then a refresh_token, then calling 'refresh!' to get a refreshed access token... then use that access token to establish your Garb session, then call down all the profiles for a given account using the Gard::Management::Profile.all

Hope this helps - let me know if you have questions!

Just a note on what worked for me in:

For steps 3, 4 & 5 I used cURL instead to retrieve the Access/Refresh token. Step 6 is then the same for me (using the Sija branch of the Garb Gem). So using cURL:

Using the details associated with your Google app POST the following using cURL:

curl --data "code=<APP_CODE>&redirect_uri=http://localhost:3000/oauth2callback&client_id=<CLIENT_ID>.apps.googleusercontent.com&scope=&client_secret=<CLIENT_SECRET>&grant_type=authorization_code" https://accounts.google.com/o/oauth2/token

The response takes the form:

{
  "access_token" : "<ACCESS_TOKEN>",
  "token_type" : "Bearer",
  "expires_in" : 3600,
  "refresh_token" : "<REFRESH_TOKEN>"
}

which you can plug into the Garb Gem as per part 6.

Jean-Nicholas Hould

The answer by @CamNorgate is valid.

If you don't have a "refresh_token" back from Omniauth on the callback make sure you are correctly initializing :google_oauth2

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :google_oauth2, ENV["GOOGLE_CLIENT_ID"], ENV["GOOGLE_CLIENT_SECRET"],
    { :scope=>"https://www.google.com/m8/feeds, https://www.googleapis.com/auth/userinfo.email, https://www.googleapis.com/auth/userinfo.profile",
      :approval_prompt=>"force", access_type="offline"
    }

end

Make sure to include :approval_prompt=>"force", access_type="offline" in order for the refresh_token to be sent back. The refresh_token is only provided on the first authorization from the user.

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