Created
September 15, 2016 02:06
-
-
Save littlekbt/7e011495965682eba3309c85fa861a5b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# OAuth client side | |
# move on CUI | |
# oauth 1.0 Client | |
# | |
# 1: get request token | |
# return request token and request token secret | |
# | |
# 2: input verifier | |
# | |
# 3: get access token with request token and verifier | |
# return access token and access token secret | |
require 'faraday' | |
require 'faraday_middleware' | |
require 'uri' | |
require 'openssl' | |
require 'cgi' | |
require 'base64' | |
require 'pry' | |
class OauthCli | |
module Util | |
def request(host, path, method, params, keys, body=nil) | |
conn = Faraday.new(:url => host) do |builder| | |
builder.request :url_encoded | |
# builder.response :logger | |
builder.adapter :net_http | |
end | |
conn.response :xml, :content_type => /\bxml$/ | |
res = conn.send(method) do |req| | |
req.headers['Accept'] = 'application/xml' | |
req.headers['Content-Type'] = 'application/xml' | |
req.url path | |
req.params = params.merge({oauth_signature: create_signature(host, path, method, params, keys)}) | |
if body | |
req.body = body | |
end | |
end | |
res | |
end | |
def body_parse(res_body) | |
res_body | |
.split('&') | |
.map{|e| e.split('=')} | |
.map{|e| [e[0].to_sym, e[1]]} | |
.to_h | |
end | |
private | |
def create_signature(host, path, method, params, keys) | |
# key | |
key = keys.class == Array ? "#{CGI.escape(keys[0])}&#{keys[1]}" : CGI.escape(keys) + '&' | |
# data | |
http_method = method.upcase | |
url = host + path | |
params = params | |
.select{|k, v| !v.empty?} | |
.map{|k, v| [CGI.escape(k.to_s), CGI.escape(v)]} | |
.to_h | |
.sort{|(ka, _), (kb, _)| ka <=> kb} | |
.inject(''){|str, (k, v)| str += "#{k.to_s}=#{v}&"} | |
.chop | |
data = [http_method, url, params].map{|e| CGI.escape(e)}.join('&') | |
create_hmac_sha1(key, data) | |
end | |
def create_hmac_sha1(key, text) | |
digest = OpenSSL::Digest.new('sha1') | |
Base64.encode64(OpenSSL::HMAC.digest(digest, key, text)).chop | |
end | |
def refresh_nonce(env) | |
env[:oauth_nonce] = ((0..9).to_a + ("a".."z").to_a).sample(20).join | |
end | |
def refresh_timestamp(env) | |
env[:oauth_timestamp] = Time.now.gmtime.to_i.to_s | |
end | |
end | |
end | |
class OauthCli | |
include OauthCli::Util | |
def initialize(consumer_key: nil, consumer_secret: nil, oauth_token: nil, oauth_token_secret: nil, host: nil, path: nil, options: {}) | |
@env = { | |
host: host, | |
path: path, | |
oauth_callback: 'oob', | |
oauth_consumer_key: consumer_key, | |
oauth_consumer_secret: consumer_secret, | |
oauth_token: oauth_token, | |
oauth_token_secret: oauth_token_secret, | |
oauth_verifier: '', | |
oauth_nonce: ((0..9).to_a + ("a".."z").to_a).sample(20).join, | |
oauth_signature: '', | |
oauth_signature_method: "HMAC-SHA1", | |
oauth_timestamp: Time.now.gmtime.to_i.to_s, | |
oauth_version: "1.0", | |
}.merge(options) | |
end | |
def get_request_token(path: nil) | |
p = %i(oauth_consumer_key oauth_nonce oauth_signature_method oauth_timestamp oauth_version oauth_callback scope) | |
res = request(@env[:host], | |
path, | |
'post', | |
@env.select{|k, _| p.include?(k)}, | |
@env[:oauth_consumer_secret] | |
) | |
res_body = body_parse(res.body) | |
@env.merge!(res_body) | |
res_body | |
end | |
def get_access_token(path: nil, verifier: nil) | |
p = %i(oauth_consumer_key oauth_nonce oauth_signature_method oauth_timestamp oauth_version oauth_verifier oauth_token) | |
@env.merge!({oauth_verifier: verifier}) | |
res = request(@env[:host], | |
path, | |
'post', | |
@env.select{|k, _| p.include?(k)}.merge({oauth_token: CGI.unescape(@env[:oauth_token])}), | |
[@env[:oauth_consumer_secret], @env[:oauth_token_secret]] | |
) | |
body_parse(res.body) | |
end | |
def upload_image(path, body) | |
p = %i(oauth_consumer_key oauth_nonce oauth_signature_method oauth_timestamp oauth_version oauth_signature oauth_token) | |
refresh_nonce(@env) | |
refresh_timestamp(@env) | |
res = request(@env[:host], | |
path, | |
'post', | |
@env.select{|k, _| p.include?(k)}.merge({oauth_token: CGI.unescape(@env[:oauth_token])}), | |
[@env[:oauth_consumer_secret], @env[:oauth_token_secret]], | |
body=body | |
) | |
end | |
end | |
# sample | |
# for hatena api(http://developer.hatena.ne.jp/ja/documents/auth/apis/oauth/consumer) | |
require './oauth_cli' | |
oauth_cli = OauthCli.new( | |
consumer_key: 'consumer_key', | |
consumer_secret: 'consumer_secret', | |
host: 'https://www.hatena.com', | |
options: {scope: 'read_public,write_public,read_private,write_private'} | |
) | |
# get request_token | |
request_token = oauth_cli.get_request_token(path: '/oauth/initiate') | |
puts "response: #{request_token}" | |
# access to oauth page(https://www.hatena.ne.jp/oauth/authorize?oauth_token={request_token}) and get verifier | |
# input verifier | |
verifier = gets.chop | |
access_token = oauth_cli.get_access_token(path: '/oauth/token', verifier: verifier) | |
puts "response: #{access_token}" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment