Authenticating a Google Service Account

Thursday, April 26, 2012, at 11:34AM

By Eric Richardson

I spent a few hours at work today trying to make sense of Google's new OAuth2 service accounts, implementing code to generate the JSON Web Token it wants and then query Google's auth server to get the OAuth token. Google intends the accounts to be used by backend services, which makes a lot more sense than shoe-horning them into access via some user's account as is normally the case.

Only after I had all that and I tried to make an API request did I realize that Google doesn't support service accounts in Analytics yet, so all of that work was in vain. To try to keep it from going to waste, I figured I would post it here. Looking to authenticate a Google service account for a Ruby app? Hopefully this will save you a little time.

The JWT gem can be found here.

    require 'jwt'

    # -- Create JWT -- #

    # load in private key
    keydata = nil
    File.open(Rails.root.to_s+"/config/google_api_key.p12",:encoding => "binary") {|f| keydata = f.read(); }
    pk = OpenSSL::PKCS12.new(keydata,"notasecret")

    # generate the JWT
    jwt = JWT.encode({
      :iss    => "12345678@developer.gserviceaccount.com",
      :scope  => "https://www.googleapis.com/auth/someservice.readonly",
      :aud    => "https://accounts.google.com/o/oauth2/token",
      :exp    => (Time.now + 3600).to_i,
      :iat    => Time.now.to_i
    },pk.key,"RS256")

    # -- Convert into an OAUTH2 Token -- #

    uri = URI("https://accounts.google.com/o/oauth2/token")
    req = Net::HTTP::Post.new uri.path
    req.set_form_data(:grant_type => "assertion", :assertion_type => "http://oauth.net/grant_type/jwt/1.0/bearer", :assertion => jwt)

    conn = Net::HTTP.new uri.host, uri.port
    conn.use_ssl = true

    resp = conn.start do |http|
      http.request(req)
    end

    json = JSON.parse(resp.body)

    # token is at json['access_token']
    puts json