Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ gem "multipart-post"
gem "oauth2"
gem "json"
gem "addressable"
gem "sinatra"
gem "launchy"

group :development do
gem "rspec"
Expand Down
11 changes: 11 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ GEM
json (1.7.7)
jwt (0.1.5)
multi_json (>= 1.0)
launchy (2.1.0)
addressable (~> 2.2.6)
multi_json (1.6.0)
multipart-post (1.1.5)
oauth2 (0.8.0)
Expand All @@ -24,6 +26,8 @@ GEM
multi_json (~> 1.0)
rack (~> 1.2)
rack (1.4.5)
rack-protection (1.5.3)
rack
rake (0.9.2.2)
rspec (2.10.0)
rspec-core (~> 2.10.0)
Expand All @@ -33,6 +37,11 @@ GEM
rspec-expectations (2.10.0)
diff-lcs (~> 1.1.3)
rspec-mocks (2.10.1)
sinatra (1.4.5)
rack (~> 1.4)
rack-protection (~> 1.4)
tilt (~> 1.3, >= 1.3.4)
tilt (1.4.1)
webmock (1.8.7)
addressable (>= 2.2.7)
crack (>= 0.1.7)
Expand All @@ -45,7 +54,9 @@ DEPENDENCIES
bundler
jeweler (~> 1.6.4)
json
launchy
multipart-post
oauth2
rspec
sinatra
webmock
18 changes: 17 additions & 1 deletion README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,23 @@ RubyBox provides a simple, chainable, feature-rich client for [Box's 2.0 API](ht
Authorization
-------------

RubyBox uses Box's OAuth2 Implementaton, Here are the steps involved in authorizing a client:
RubyBox uses Box's OAuth2 Implementaton. For any UNIX based operating systems (including Linux, MacOS) you can authorize the application through Box's UI and generate the access code and refresh code automatically based on your client ID and client secret. For non UNIX based operating systems, you will have to manually generate the access token and refresh token and find a way to store the refresh token.

For UNIX based operating systems, here are the steps involved in authorizing a client:

```ruby
require 'ruby-box'

session = RubyBox::Session.new({
client_id: 'your-client-id',
client_secret: 'your-client-secret'
})
client = RubyBox::Client.new(session)
```
This should automatically generate the required access token and refresh token for the client to work. You will be required to grant access to the application through Box's UI, every time you run you invoke ruby-box. The access token will be automatically refreshed and there is no need to write any extra lines of code to store the refresh token.


For Non-UNIX based operating systems, here are the steps involved in authorizing a client:

__1)__ Get the authorization url.

Expand Down
16 changes: 16 additions & 0 deletions lib/ruby-box/box_authenticator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require 'sinatra'

code = nil

get '/' do
code = params[:code]
if !code.nil?
puts "code=#{code}"
body "Box access code captured. Please return to your program to continue. You can close this window."
end
end

after do
puts body
Process.kill 'TERM', Process.pid
end
34 changes: 31 additions & 3 deletions lib/ruby-box/session.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'oauth2'
require 'launchy'

module RubyBox
class Session
Expand All @@ -15,8 +16,25 @@ def initialize(opts={}, backoff=0.1)

if opts[:client_id]
@oauth2_client = OAuth2::Client.new(opts[:client_id], opts[:client_secret], OAUTH2_URLS.dup)
@access_token = OAuth2::AccessToken.new(@oauth2_client, opts[:access_token]) if opts[:access_token]
@refresh_token = opts[:refresh_token]

##Redirect to box to generate access key and refresh token only on UNIX based OS
if ::File.exist?('/bin/uname') || ::File.exist?('/usr/bin/uname')
Launchy.open("https://app.box.com/api/oauth2/authorize?response_type=code&client_id=#{opts[:client_id]}&redirect_uri=http://localhost:4567")
authTokenCodeOutput = `ruby #{::File.dirname(__FILE__)}/box_authenticator.rb 2> /dev/null`
if authTokenCodeOutput =~ /code=(\w+)/
authTokenCode = $1
#puts "Got Auth Code #{authTokenCode}"
else
puts "**ERROR** : Authorization Token Code is not available."
exit
end
@token = get_access_token(authTokenCode)
@access_token = @token
@refresh_token = @token.refresh_token
else
@access_token = OAuth2::AccessToken.new(@oauth2_client, opts[:access_token]) if opts[:access_token]
@refresh_token = opts[:refresh_token]
end
@as_user = opts[:as_user]
else # Support legacy API for historical reasons.
@api_key = opts[:api_key]
Expand All @@ -38,6 +56,7 @@ def get_access_token(code)
def refresh_token(refresh_token)
refresh_access_token_obj = OAuth2::AccessToken.new(@oauth2_client, @access_token.token, {'refresh_token' => refresh_token})
@access_token = refresh_access_token_obj.refresh!
@refresh_token = @access_token.refresh_token
end

def build_auth_header
Expand All @@ -60,15 +79,24 @@ def request(uri, request, raw=false, retries=0)

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.ssl_version = :SSLv3
http.ssl_version = :TLSv1_2
#http.ssl_version = :SSLv3
#http.set_debug_output($stdout)

##Clear the existing request fields to avoid duplicates
if request.key?('Authorization')
request.delete('Authorization')
end

if @access_token
request.add_field('Authorization', "Bearer #{@access_token.token}")
else
request.add_field('Authorization', build_auth_header)
end

if request.key?('As-User')
request.delete('As-User')
end

request.add_field('As-User', "#{@as_user}") if @as_user

Expand Down