LoginSignup
5
4

More than 3 years have passed since last update.

BOX API Integration With RubyOnRails(OAuth 2.0)

Last updated at Posted at 2016-08-04

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

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

    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.

    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

    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,

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

<%= 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

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

5
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4