BOX API Integration With RubyOnRails(OAuth 2.0)

Login By Using OAuth 2.0

https://www.box.com/
Box | Secure Content & Online File Sharing for Businesses
Box offers secure content management and collaboration for individuals, teams, and businesses, enabling secure file sharing and access to your files online.

For OAuth2.0, please refer below link.
http://www.bubblecode.net/en/2016/01/22/understanding-oauth2/

To configure the application in BOX, follow the below step.
Step1: Create a developer account.
https://app.box.com/signup/o/default_developer_offer
If you have ignored.

Step2:
Follow the below link steps:-
https://box-content.readme.io/docs/oauth-20

Step3:
After completing the app setting in BOX, create a rails application.
Let us suppose,controller name is box_api_controller.rb
In box_api_controller.rb file,

##Create a make request on login button

```rb
def make_request
	#Check access token expire or not.
	check_access_token_expire = check_access_token_expire_dt
	if check_access_token_expire.split("-")[0] == "access_token"
		#Create client by passing Token
		@box_client = Boxr::Client.new(check_access_token_expire.split("-")[1])
		cookies[:token] = check_access_token_expire.split("-")[1]
	else
		if check_access_token_expire.split("-")[0] == "refresh_token"
			#Call method
			create_post_req_url("refresh_token","refresh_token",check_access_token_expire.split("-")[1])
		else
			# kick off authorization flow
			parameters = "response_type=code&client_id=<your client id>&redirect_uri=<your application url>/handle_user_decision/&state=security_token"
			url = "https://account.box.com/api/oauth2/authorize?#{parameters}"
			redirect_to url
		end
	end end
```
##After authorized the client id, get code in response

```
def handle_user_decision
	# kick off authorization flow
	#Get authorization code
	code_url = Rack::Utils.parse_query URI(request.original_url).query
	code = code_url["code"] 
	#Call method
	create_post_req_url("authorization_code","code", code) 
end
```
##Create a post URL

```rb
	def create_post_req_url(grant_type,header, code)
	#Set oauth2 url
	uri = URI.parse("https://api.box.com//oauth2//token")
	#Passing parameter
	data = "grant_type=#{grant_type}&#{header}=#{code}&client_id=<your client id>&client_secret=<your client secret key>"
	#Set header
	headers = {"Content-Type" => "application/x-www-form-urlencoded"}
	#Get http request
	http = Net::HTTP.new(uri.host,uri.port)
	http.use_ssl = true
	http.verify_mode = OpenSSL::SSL::VERIFY_NONE
	#Do post the URL
	response = http.post(uri.path,data.to_s,headers)
	#Check response
	if response.code != "200"
		flash[:alert] ="エラーが発生しました。管理者に連絡してください。エラーの内容：#{response.code}  #{JSON.parse(response.body)}"
	else
		#flash[:alert] ="#{response.body.to_json}"
		parsed = JSON.parse(response.body) # returns a hash
		token = parsed["access_token"]
		cookies[:token] = nil
		cookies[:token] = token      
		if grant_type == "authorization_code"
			#Insert BOX access token details
			user = "<your drive user name>"
			insert_access_token(user, token, parsed["refresh_token"], Time.now)
		else
			if grant_type == "refresh_token"
				#Update BOX access token 
				updt_access_token(user, token, code, parsed["refresh_token"], Time.now)
			end  
		end
		redirect_to box_api_index_path
	end
end
```
Other helper methods:-
##Check access_token expire or not.

```rb
	def check_access_token_expire_dt
	@access_token_time = BoxApiAccessToken.getaccesstokentime
	if !@access_token_time.blank?
		@access_token_time.each do |token_details |
			if token_details.access_token_dt != nil
				if token_details.new_access_token_dt.to_datetime.new_offset(Rational(9, 24)).strftime('%Y/%m/%d %H:%M') < Time.now.to_datetime.new_offset(Rational(9, 24)).strftime('%Y/%m/%d %H:%M')
					check_access_token_expire_dt = "refresh_token-#{token_details.refresh_access_token}"
					return check_access_token_expire_dt
				else
					check_access_token_expire_dt = "access_token-#{token_details.access_token}"
					return check_access_token_expire_dt
				end
			else
				check_access_token_expire_dt = "new_token-req_new_token"
				return check_access_token_expire_dt
			end
		end
	else
		check_access_token_expire_dt = "new_token-req_new_token"
		return check_access_token_expire_dt
	end
end
```
#Insert access_token details in DB

```rb
	def insert_access_token(user,access_token,refresh_access_token,access_token_dt)
	@box_access_token = BoxApiAccessToken.new(
			:user => user,
			:access_token => access_token,
			:refresh_access_token => refresh_access_token,
			:access_token_dt => access_token_dt)

			#Save User Device Data
			@box_access_token.save
end

#Update access_token,refresh_access_token,access_token_dt details in DB
	def updt_access_token(user,access_token, refresh_access_token,new_refresh_access_token,access_token_dt)
	#@box_access_token_updt = BoxApiAccessToken.find_refresh_access_token(refresh_access_token)
	@box_access_token_updt = BoxApiAccessToken.find_by_refresh_access_token(refresh_access_token)
	attributes = {:access_token => access_token,:access_token_dt => access_token_dt, :refresh_access_token => new_refresh_access_token, :updated_at => access_token_dt}
	#Update the object
	@box_access_token_updt.update_attributes(attributes)
end
```
In model,

```rb
class BoxApiAccessToken < ActiveRecord::Base
	scope :getaccesstokentime, lambda { 
select("id,access_token,refresh_access_token,substring(cast(access_token_dt as varchar),0,17) as access_token_dt,substring(cast(access_token_dt + interval '60 minute' as varchar),0,17) as new_access_token_dt ").order(:id => "desc").limit(1)
	}   
end
```
#In index.html.erb file

```html+erb
<%= form_tag(:controller => "box_api", :action => 'make_request') do |f| %>
<div class="form-group"><%= submit_tag("Box Login", class: "btn btn-primary") %></div><% end %>
```
#Here is my migration file

```rb
class CreateBoxApiAccessTokens < ActiveRecord::Migration
	def change
		create_table :box_api_access_tokens do |t|
			t.string :user, :limit => 100, :null => false
			t.string :access_token, :limit => 500
			t.string :refresh_access_token, :limit => 500
			t.datetime :access_token_dt, :limit => 50
			t.datetime :created_at, :null => false
			t.string :created_by, :limit => 50
			t.datetime :updated_at
			t.string :updated_by, :limit => 50
			t.boolean :del_flag, :default => false		
			end
		execute 'alter table box_api_access_tokens alter column created_at set default now()'
	end
end
```
Please note that,
Using the Access and Refresh Tokens
The access_token is the actual string needed to make API requests.Each access_token is valid for 1 hour.In order to get a new, valid token, you can use the accompanying refresh_token.Each refresh_token is valid for one use in 60 days.Every time you get a new access_token by using a refresh_token, 
we reset your timer for the 60 day period and hand you a new refresh_token. 
This means that as long as your users use your application once every 60 days, their login is valid forever.

For more details, please refer BOX API document.

Enjoy Coding.

Thanks & Best Regards,
Alok Rawat