Twitter 3-legged authorization in Ruby

倖福魔咒の 提交于 2019-12-30 07:13:11

问题


I am trying my hand ruby on rails. Mostly I have written code in Sinatra. Anyway this question may not have to do anything with framework. And this question may sound a very novice question. I am playing with Twitter 1.1 APIs and OAuth first time.

I have created an app XYZ and registered it with Twitter. I got XYZ's consumer key i.e., CONSUMER_KEY and consumer secret i.e. CONSUMER_SECRET. I also got XYZ's own access token i.e ACCESS_TOKEN and access secret i.e. ACCESS_SECRET

XYZ application type: Read, Write and Access direct messages XYZ callback URL: http://www.mysite.com/cback And I have checked: Allow this application to be used to Sign in with Twitter

What I am trying to do is very simple:

1) Users come to my website and click a link Link your twitter account (not signin with twitter)
2) That opens twitter popup where user grants permission to XYZ to perform actions on his/her behalf
3) Once user permits and popup gets closed, XYZ app gets user's access token and secret and save in the database.
4) Then XYZ uses that user's token and secret to perform actions in future.

I may be moron that such work flow has been implemented on several thousands sites and Twitter API documentations explain this 3-legged authentication, still I am unable to figure it out.

I have read https://dev.twitter.com/docs/auth/3-legged-authorization and https://dev.twitter.com/docs/auth/implementing-sign-twitter Unfortunately no ruby code found on internet that explains with step by step example.

What link should be used to open twitter authentication page when user clicks Link your twitter account. Can anyone here, write some pseudo code with my pseduo credential above to achieve my goal from beging till end of this work flow? Thanks.

UPDATE:

I started with requesting request token as

require 'oauth'
consumer = OAuth::Consumer.new(CONSUMER_KEY, CONSUMER_SECRET,
{ site: "https://twitter.com"})
request_token = consumer.get_request_token oauth_callback: 'http://www.mysite.com/tauth'
redirect_to request_token.authorize_url


回答1:


I'm not familiar with ROR but here is the workflow of the OAuth 'dance' that you need to follow when the user clicks your button:

  1. Obtain an unauthorized request token from Twitter by sending a request to

    POST https://api.twitter.com/oauth/request_token

    signing the request using your consumer secret. This will be done in the background and will be transparent to the user.

  2. You will receive am oauth_token and oauth_token_secret back from twitter.

  3. Redirect the user to

    https://api.twitter.com/oauth/authorize?oauth_token=[token_received_from_twitter]

    using the oauth token value you received from Twitter in step 2.

  4. When the user authorizes your app they will be redirected to your callback url with oauth_token and oauth_verifier appended to the url. i.e.

    http://www.mysite.com/cback?oauth_token=NPcudxy0yU5T3tBzho7iCotZ3cnetKwcTIRlX0iwRl0&oauth_verifer=uw7NjWHT6OJ1MpJOXsHfNxoAhPKpgI8BlYDhxEjIBY

  5. Convert the request token into an access token by sending a signed request along with the oauth_verifier to

    POST https://api.twitter.com/oauth/access_token

    signing your request with your consumer secret and the token secret received in step 2.

  6. If everything goes ok, you will receive a new oauth_token and oauth_token_secret from Twitter. This is your access token for the user.

  7. Using the access token and secret received in step 6 you can make Twitter api calls on behalf the the user by sending signed requests to the appropriate api endpoints.




回答2:


Hope you solved your problem by this time, but I built this sample Sign in with Twitter ruby web app that provide all explanation you need to do this integration. Below there's a class that implements all necessary methods with comments:

require "net/https"
require "simple_oauth"

# This class implements the requests that should 
# be done to Twitter to be able to authenticate
# users with Twitter credentials
class TwitterSignIn

class << self
    def configure
    @oauth = YAML.load_file(TWITTER)
    end

    # See https://dev.twitter.com/docs/auth/implementing-sign-twitter (Step 1)
    def request_token

    # The request to get request tokens should only
    # use consumer key and consumer secret, no token
    # is necessary
    response = TwitterSignIn.request(
        :post, 
        "https://api.twitter.com/oauth/request_token",
        {},
        @oauth
    )

    obj = {}
    vars = response.body.split("&").each do |v|
        obj[v.split("=").first] = v.split("=").last
    end

    # oauth_token and oauth_token_secret should
    # be stored in a database and will be used
    # to retrieve user access tokens in next requests
    db = Daybreak::DB.new DATABASE
    db.lock { db[obj["oauth_token"]] = obj }
    db.close

    return obj["oauth_token"]
    end

    # See https://dev.twitter.com/docs/auth/implementing-sign-twitter (Step 2)
    def authenticate_url(query) 
    # The redirection need to be done with oauth_token
    # obtained in request_token request
    "https://api.twitter.com/oauth/authenticate?oauth_token=" + query
    end

    # See https://dev.twitter.com/docs/auth/implementing-sign-twitter (Step 3)
    def access_token(oauth_token, oauth_verifier)

    # To request access token, you need to retrieve
    # oauth_token and oauth_token_secret stored in 
    # database
    db = Daybreak::DB.new DATABASE
    if dbtoken = db[oauth_token]

        # now the oauth signature variables should be
        # your app consumer keys and secrets and also
        # token key and token secret obtained in request_token
        oauth = @oauth.dup
        oauth[:token] = oauth_token
        oauth[:token_secret] = dbtoken["oauth_token_secret"]

        # oauth_verifier got in callback must 
        # to be passed as body param
        response = TwitterSignIn.request(
        :post, 
        "https://api.twitter.com/oauth/access_token",
        {:oauth_verifier => oauth_verifier},
        oauth
        )

        obj = {}
        vars = response.body.split("&").each do |v|
        obj[v.split("=").first] = v.split("=").last
        end

        # now the we got the access tokens, store it safely
        # in database, you're going to use it later to
        # access Twitter API in behalf of logged user
        dbtoken["access_token"] = obj["oauth_token"]
        dbtoken["access_token_secret"] = obj["oauth_token_secret"]
        db.lock { db[oauth_token] = dbtoken }

    else
        oauth_token = nil
    end

    db.close
    return oauth_token
    end

    # This is a sample Twitter API request to 
    # make usage of user Access Token
    # See https://dev.twitter.com/docs/api/1.1/get/account/verify_credentials
    def verify_credentials(oauth_token)
    db = Daybreak::DB.new DATABASE

    if dbtoken = db[oauth_token]

        # see that now we use the app consumer variables
        # plus user access token variables to sign the request
        oauth = @oauth.dup
        oauth[:token] = dbtoken["access_token"]
        oauth[:token_secret] = dbtoken["access_token_secret"]

        response = TwitterSignIn.request(
        :get, 
        "https://api.twitter.com/1.1/account/verify_credentials.json",
        {},
        oauth
        )

        user = JSON.parse(response.body)

        # Just saving user info to database
        user.merge! dbtoken 
        db.lock { db[user["screen_name"]] = user }

        result = user

    else
        result = nil
    end

    db.close
    return result
    end

    # Generic request method used by methods above
    def request(method, uri, params, oauth)
    uri = URI.parse(uri.to_s)

    # always use SSL, you are dealing with other users data
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    # uncomment line below for debug purposes
    #http.set_debug_output($stdout)

    req = (method == :post ? Net::HTTP::Post : Net::HTTP::Get).new(uri.request_uri)
    req.body = params.to_a.map { |x| "#{x[0]}=#{x[1]}" }.join("&")
    req["Host"] = "api.twitter.com"

    # Oauth magic is done by simple_oauth gem.
    # This gem is enable you to use any HTTP lib
    # you want to connect in OAuth enabled APIs.
    # It only creates the Authorization header value for you
    # and you can assign it wherever you want
    # See https://github.com/laserlemon/simple_oauth
    req["Authorization"] = SimpleOAuth::Header.new(method, uri.to_s, params, oauth)

    http.request(req)
    end

  end
end

More detailed explanation at: https://github.com/lfcipriani/sign_in_with_twitter_sample



来源:https://stackoverflow.com/questions/16516398/twitter-3-legged-authorization-in-ruby

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