Permalink
Browse files

Adding skeleton impl to get request + access OAuth tokens.

  • Loading branch information...
1 parent 588b668 commit 05a9e8b024ac6402d203b289263f457066d686be @webmonarch committed Mar 11, 2012
View
@@ -1,2 +1,8 @@
/.idea
/withings-api.iml
+*.gem
+.bundle
+Gemfile.lock
+pkg/*
+/doc
+/.yardoc
View
@@ -0,0 +1,4 @@
+source "http://rubygems.org"
+
+# Specify your gem's dependencies in withings-api.gemspec
+gemspec
File renamed without changes.
View
@@ -0,0 +1 @@
+require "bundler/gem_tasks"
View
@@ -0,0 +1,11 @@
+require "withings-api/version"
+
+require "withings-api/consts"
+require "withings-api/errors"
+require "withings-api/static_helpers"
+
+module Withings
+ module Api
+ extend StaticHelpers
+ end
+end
@@ -0,0 +1,13 @@
+module Withings
+ module Api
+ module Defaults
+ OAUTH_BASE_URL = "https://oauth.withings.com"
+ OAUTH_REQUEST_TOKEN_PATH = "/account/request_token"
+ OAUTH_AUTHORIZE_PATH = "/account/authorize"
+ OAUTH_ACCESS_TOKEN_PATH = "/account/access_token"
+
+ TESTING_CONSUMER_KEY = "08943c64c3ccfe86d5edb40c8db6ddbbc43b6f58779c77d2b02454284db7ec"
+ TESTING_CONSUMER_SECRET = "85949316f07fc41346be145fe8fbc18b73f954f280be958033571720510"
+ end
+ end
+end
@@ -0,0 +1,5 @@
+module Withings
+ module Api
+
+ end
+end
@@ -0,0 +1,102 @@
+require 'oauth'
+
+module Withings
+ module Api
+ # Simple API to ease the OAuth setup steps for Withing API client apps.
+ #
+ # Specifically, this class provides methods for OAuth access token creation.
+ #
+ # 1. Request request tokens - via {#create_request_token}
+ # 1. Redirect to authorization URL (this is handled outside of these methods, ie: by the webapp, etc.)
+ # 1. Request access tokens (for permanent access to Withings content) - via {#create_access_token}
+ module StaticHelpers
+ Defaults = Withings::Api::Defaults
+
+ # Issues the "request_token" oauth HTTP request to Withings.
+ #
+ # For call details @ Withings, see http://www.withings.com/en/api/oauthguide#access
+ #
+ # For details about registering your application with Withings, see http://www.withings.com/en/api/oauthguide#registration
+ #
+ # @param [String] consumer_token the consumer key Withings assigned on app registration
+ # @param [String] consumer_secret the consumer secret Withings assigned on app registration
+ # @param [String] callback_url the URL Withings should return the user to after authorization
+ #
+ # @return [RequestTokenResponse] something encapsulating the request response
+ #
+ # @raise [Timeout::Error] on connection, or read timeout
+ # @raise [SystemCallError] on low level system call errors (connection timeout, connection refused)
+ # @raise [ProtocolError] for HTTP 5XX error response codes
+ # @raise [OAuth::Unauthorized] for HTTP 4XX error reponse codes
+ # @raise [StandardError] for everything else
+ def create_request_token(consumer_token, consumer_secret, callback_url)
+ # TODO: warn if the callback URL isn't HTTPS
+ consumer = create_consumer(consumer_token, consumer_secret)
+ oauth_request_token = consumer.get_request_token({:oauth_callback => callback_url})
+
+ RequestTokenResponse.new oauth_request_token
+ end
+
+
+ # Issues the "access_token" oauth HTTP request to Withings
+ #
+ # @param [RequestTokenResponse] request_token request token returned from {#create_request_token}
+ # @param [String] user_id user id as returned from Withings via the {RequestTokenResponse#authorization_url}
+ #
+ # @return [] the shit
+ def create_access_token(request_token, user_id)
+ oauth_request_token = request_token.oauth_request_token
+
+ oauth_access_token = oauth_request_token.get_access_token({:access_token_path => oauth_request_token.consumer.access_token_path})
+
+ # test for unauthorized token, since oauth + withings doesn't turn this into an explicit
+ # error code / exception
+ if oauth_access_token.params.key?(:"unauthorized token")
+ raise StandardError, :"unauthorized token"
+ end
+
+ oauth_access_token
+ end
+
+ private
+
+ def create_consumer(consumer_key, consumer_secret)
+ OAuth::Consumer.new(consumer_key, consumer_secret, {
+ :site => Defaults::OAUTH_BASE_URL,
+ :scheme => :query_string,
+ :http_method => :get,
+ :signature_method => 'HMAC-SHA1',
+ :request_token_path => Defaults::OAUTH_REQUEST_TOKEN_PATH,
+ :authorize_path => Defaults::OAUTH_AUTHORIZE_PATH,
+ :access_token_path => Defaults::OAUTH_ACCESS_TOKEN_PATH,
+ })
+ end
+ end
+
+ # Simple wrapper class that encapsulates the results of a call to {StaticHelpers#create_request_token}
+ class RequestTokenResponse
+ def initialize(oauth_request_token)
+ self.oauth_request_token = oauth_request_token
+ end
+
+ # @return [String] the OAuth request token key
+ def token
+ self.oauth_request_token.token
+ end
+
+ alias :key :token
+
+ # @return [String] the OAuth request token secret
+ def secret
+ self.oauth_request_token.secret
+ end
+
+ # @return [String] URL to redirect the user to to authorize the access to their data
+ def authorization_url
+ self.oauth_request_token.authorize_url
+ end
+
+ attr_accessor :oauth_request_token
+ end
+ end
+end
@@ -0,0 +1,5 @@
+module Withings
+ module Api
+ VERSION = "0.0.1"
+ end
+end
View
@@ -0,0 +1,28 @@
+# -*- encoding: utf-8 -*-
+$:.push File.expand_path("../lib", __FILE__)
+require "withings-api/version"
+
+Gem::Specification.new do |s|
+ s.name = "withings-api"
+ s.version = Withings::Api::VERSION
+ s.authors = ["webmonarch"]
+ s.email = ["eric@collectivegenius.net"]
+ s.homepage = ""
+ s.summary = "A simple Ruby implementation of the Withings API."
+ s.description = "A simple Ruby implementation of the Withings API. See http://www.withings.com/en/api/wbsapiv2"
+
+ s.rubyforge_project = "withings-api"
+
+ s.files = `git ls-files`.split("\n")
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
+ s.require_paths = ["lib"]
+
+ # specify any dependencies here; for example:
+ s.add_runtime_dependency "oauth", "~> 0.4.5"
+ # s.add_runtime_dependency "rest-client"
+
+ s.add_development_dependency "rspec"
+ s.add_development_dependency "cucumber"
+
+end

0 comments on commit 05a9e8b

Please sign in to comment.