Skip to content

Instantly share code, notes, and snippets.

@eladkehat
Created December 20, 2011 21:29
Show Gist options
  • Save eladkehat/1503368 to your computer and use it in GitHub Desktop.
Save eladkehat/1503368 to your computer and use it in GitHub Desktop.
Sinatra code that gets your Google contacts through OAuth. Wrote this because OmniAuth was giving me trouble with the contacts data api scope for some reason, so I decided to go 'raw'.
require 'sinatra'
require 'net/http'
require 'json'
ENDPOINT = 'https://accounts.google.com/o/oauth2/auth'
TOKEN_ENDPOINT = 'https://accounts.google.com/o/oauth2/token'
CLIENT_ID = '<your app client id>'
CLIENT_SECRET = '<your app client secret>'
REDIRECT_URI = 'http://localhost:4567/auth/google_oauth2/callback'
SCOPE = 'https://www.google.com/m8/feeds/'
ACCESS_TYPE = 'offline'
#ACCESS_TYPE = 'online'
APPROVAL_PROMPT = 'auto'
#APPROVAL_PROMPT = 'force' # ensures we get a refresh token
STATE = 'contacts'
RESPONSE_TYPE = 'code'
GRANT_TYPE = 'authorization_code'
GRANT_TYPE_REFRESH = 'refresh_token'
ME = 'elad...@...'
def output_response(res)
puts res.class
puts res.message
puts res.code
res.each_header {|k, v| puts "#{k} = #{v}" }
#puts res.body
end
def step1
params = {
:scope => SCOPE,
:state => STATE,
:redirect_uri => REDIRECT_URI,
:response_type => RESPONSE_TYPE,
:client_id => CLIENT_ID,
:approval_prompt => APPROVAL_PROMPT,
:access_type => ACCESS_TYPE,
}
uri = URI(ENDPOINT)
res = Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
uri.query = URI.encode_www_form(params)
req = Net::HTTP::Get.new uri.request_uri
http.request(req)
end
output_response res
res['location']
end
get '/' do
<<-HTML
<a href='/auth/google_oauth2'>Connect with Google</a>
HTML
end
get '/auth/google_oauth2' do
params = {
:scope => SCOPE,
:state => STATE,
:redirect_uri => REDIRECT_URI,
:response_type => RESPONSE_TYPE,
:client_id => CLIENT_ID,
:approval_prompt => APPROVAL_PROMPT,
:access_type => ACCESS_TYPE,
}
query = URI.encode_www_form(params)
puts "Query: #{query}"
location = "#{ENDPOINT}?#{query}"
puts "Redirecting to #{location}"
redirect location
end
def form_html(code)
<<-HTML
<p>
<form method='post' action='#{TOKEN_ENDPOINT}'>
<input type='text' name='code' value='#{code}'/><br/>
<input type='text' name='client_id' value='#{CLIENT_ID}'/><br/>
<input type='text' name='client_secret' value='#{CLIENT_SECRET}'/><br/>
<input type='text' name='redirect_uri' value='#{REDIRECT_URI}'/><br/>
<input type='text' name='grant_type' value='#{GRANT_TYPE}'/>
<input type='submit' value="Submit">
</form>
</p>
HTML
end
def get_token_redirect(code)
<<-HTML
<p>
<a href='/get_token?code=#{code}'>Get Token in Background</a>
</p>
HTML
end
get '/auth/google_oauth2/callback' do
code = params[:code]
puts "Code: #{code}"
form_html(code) + get_token_redirect(code)
end
def data_html(data)
contacts_link = "<p><a href='https://www.google.com/m8/feeds/contacts/#{ME}/full?access_token=#{data['access_token']}'>All my Google Contacts</a></p>"
refresh_link = "<p><a href='/refresh_token?token=#{data['refresh_token']}'>Refresh</a></p>"
data.to_a.map{|kv| kv.join(": ") }.join("<br/>") + refresh_link + contacts_link
end
def get_token(code)
params = {
:code => code,
:client_id => CLIENT_ID,
:client_secret => CLIENT_SECRET,
:redirect_uri => REDIRECT_URI,
:grant_type => GRANT_TYPE,
}
uri = URI(TOKEN_ENDPOINT)
req = Net::HTTP::Post.new uri.path
req.set_form_data params
res = Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
http.request(req)
end
output_response res
data = JSON.parse(res.body)
data_html(data)
end
get '/get_token' do
code = params[:code]
puts "Code: #{code}"
get_token(code)
end
def refresh_token(token)
params = {
:refresh_token => token,
:client_id => CLIENT_ID,
:client_secret => CLIENT_SECRET,
:grant_type => GRANT_TYPE_REFRESH,
}
uri = URI(TOKEN_ENDPOINT)
req = Net::HTTP::Post.new uri.path
req.set_form_data params
res = Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
http.request(req)
end
output_response res
res.body
end
def refresh_token_form_html(token)
<<-HTML
<p>
<form method='post' action='#{TOKEN_ENDPOINT}'>
<input type='text' name='refresh_token' value='#{token}'/><br/>
<input type='text' name='client_id' value='#{CLIENT_ID}'/><br/>
<input type='text' name='client_secret' value='#{CLIENT_SECRET}'/><br/>
<input type='text' name='grant_type' value='#{GRANT_TYPE_REFRESH}'/>
<input type='submit' value="Submit">
</form>
</p>
HTML
end
get '/refresh_token' do
token = params[:token]
refresh_token(token)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment