CONNECTING TO
BOX API VERSION 2 USING OAUTH 2
Box is a cloud storage
provider that has an API for creating integrations. Box provides its own
AppExchange product for connecting custom and standard objects to files storage
at Box. Look for a whitepaper coming out soon that explains why there may
be times when it is the best choice to store your files outside of Salesforce.
Here are the steps for
connecting to Box’s REST API. In my reading I learned that there was a
direct connection option with a username and password with version 1 of the
API, but with version 2 of the API you must use OAuth 2 to authenticate.
1)
Sign-up for a free personal Box account by going to this page and clicking on the ‘Sign Up’ button.
2) During the sign-up
process an email will be sent to you and you will have to click on it to
confirm the email account.
3) Log into your new
Box account.
5)
Go to this page and click on the ‘register for an API key’
link.
a. Enter a new name for the application like ‘TestAPISundog’
b. You will now receive your new API Key. Copy that to a safe place.
a. Enter a new name for the application like ‘TestAPISundog’
b. You will now receive your new API Key. Copy that to a safe place.
6)
We need to allow Salesforce to make outbound web service calls to Box.
a. Log into Salesforce
b. Click on Your Name, Setup
c. Go to Administration Setup, Security Controls, Remote Site Settings
i. Click on New Remote Site
ii. Enter a name and the URL should be https://www.Box.com
iii. Create another Remote site for https://api.Box.com
a. Log into Salesforce
b. Click on Your Name, Setup
c. Go to Administration Setup, Security Controls, Remote Site Settings
i. Click on New Remote Site
ii. Enter a name and the URL should be https://www.Box.com
iii. Create another Remote site for https://api.Box.com
7)
This page walks through how to connect to Box and get
the OAuth code.
a. Note that the only supported production authentication method with version 2 of the Box API seems to be OAuth 2.
b. If you do not want to use OAuth 2 then this page gives some other options with using version one of the API.
c. This page walks through how to verify the OAuth credentials using Postman.
d. This page walks through all the steps with OAuth 2 for Box from authentication, to getting the access token, to making your first API call.
a. Note that the only supported production authentication method with version 2 of the Box API seems to be OAuth 2.
b. If you do not want to use OAuth 2 then this page gives some other options with using version one of the API.
c. This page walks through how to verify the OAuth credentials using Postman.
d. This page walks through all the steps with OAuth 2 for Box from authentication, to getting the access token, to making your first API call.
8) Now we are ready to
try to connect to our Box account via the Version 2 of the API using OAuth 2.
9) Log into Salesforce
10)
Create a Controller called BoxConnect.
See code at the bottom of this post for the APEX code for that Controller…
Again I tried to use as little code as possible to make the important pieces obvious. A lot more needs to be done to this code before it is production ready such as responding to errors from Box.
This code tries to do three things
a. Redirect to Box so that the user can enter his/her credentials
This is done in the boxConnect() method where a PageReference does this
This code is hit when the CommandButton is clicked on the Visualforce Page
b. Call Box to request an Access Token
This is done in getBoxToken()
c. Use the Access Token to make any API calls
The example API call here is in getBoxFolder() and it lists all of the files in the specified folder.
See code at the bottom of this post for the APEX code for that Controller…
Again I tried to use as little code as possible to make the important pieces obvious. A lot more needs to be done to this code before it is production ready such as responding to errors from Box.
This code tries to do three things
a. Redirect to Box so that the user can enter his/her credentials
This is done in the boxConnect() method where a PageReference does this
This code is hit when the CommandButton is clicked on the Visualforce Page
b. Call Box to request an Access Token
This is done in getBoxToken()
c. Use the Access Token to make any API calls
The example API call here is in getBoxFolder() and it lists all of the files in the specified folder.
11)
Create a Visualforce page called BoxConnect
See code at the bottom of this post for the markup for the Visualforce Page…
See code at the bottom of this post for the markup for the Visualforce Page…
12)
To run this code add apex/BoxConnect to the end of your Salesforce URL
13)
Click on the ‘Connect to Box’ CommandButton on the Visualforce Page
a. This will redirect to Box. Enter the Box credentials
a. This will redirect to Box. Enter the Box credentials
This is done in the boxConnect() method where a PageReference does this
14)
Fill in you username and password at Box
a. Box will automatically send the page back to your Visualforce page because of redirect_uri parameter in the call to authorize via OAuth 2.
b. Note that the redirect_uri parameter is optional as it can be setup in the app within Box too. If you do send it and it is not blank at Box, then it must match.
c. You may have to change your URL from c.na9.visual.force.com to whatever your URL is.
a. Box will automatically send the page back to your Visualforce page because of redirect_uri parameter in the call to authorize via OAuth 2.
b. Note that the redirect_uri parameter is optional as it can be setup in the app within Box too. If you do send it and it is not blank at Box, then it must match.
c. You may have to change your URL from c.na9.visual.force.com to whatever your URL is.
15)
Now Box will have redirected back to your page. Now all of the action
takes place in the Controller.
a. In the constructor we check if the ‘code’ query string parameter is there. If it is then we grab it and then try to ask for the access token.
b. The access token code is in getBoxToken(). A HTTP POST call is made with all the needed items in the body. Make sure you put them in the body and not as headers or query string parameters. The values must be urlEndcoded and the ‘Content-Type’ and ‘charset’ values are also required.
c. We now get back a JSON response that we can parse to get our access and refresh tokens.
d. Now that we have our access token we can make any calls that we want to the API.
e. The call in the code within getBoxFolder() is tohttps://api.box.com/2.0/folders/FOLDER_ID/items, which will return all of the items, files and folders in this folder. The only tricky part to this one is to get the Authorization header set correctly.
f. We again get a JSON value back which can be parsed using the built-in JSON parser in APEX.
g. We now have the files that were in that specific folder.
a. In the constructor we check if the ‘code’ query string parameter is there. If it is then we grab it and then try to ask for the access token.
b. The access token code is in getBoxToken(). A HTTP POST call is made with all the needed items in the body. Make sure you put them in the body and not as headers or query string parameters. The values must be urlEndcoded and the ‘Content-Type’ and ‘charset’ values are also required.
c. We now get back a JSON response that we can parse to get our access and refresh tokens.
d. Now that we have our access token we can make any calls that we want to the API.
e. The call in the code within getBoxFolder() is tohttps://api.box.com/2.0/folders/FOLDER_ID/items, which will return all of the items, files and folders in this folder. The only tricky part to this one is to get the Authorization header set correctly.
f. We again get a JSON value back which can be parsed using the built-in JSON parser in APEX.
g. We now have the files that were in that specific folder.
16) Now that we have the code to A) Authenticate B) Get the Access Token and C) Make our first API call, we are now able to make any API calls that we need.
17) More code will
have to be written to get a new access code using the refresh token as the
access token is only good for 1 hour. The refresh token also has a
certain lifetime so if that is up, then the user will have to authenticate at
Box again from the beginning of the OAuth 2.0 process.
APEX Controller Code…
|
public
with sharing class BoxConnect {
public
string valueToShow{get;set;}
private
final string boxClientID ='myBoxClientID';
private
final string boxSecretCode ='myBoxSecretCode';
private
string codeFromBox;
private
string accessToken;
private
string refreshToken;
public
BoxConnect(){
valueToShow
='Start';
//Check
if we received the authorization code from Box because the redirectUI
//
URI points to this page. It will look like this…
codeFromBox
= System.currentPageReference().getParameters().get('code');
if(codeFromBox
== null || codeFromBox ==''){
}else{
//Try to get a token and then make an
API call to Box
getBoxToken();
}
}
public
pageReference boxConnect(){
//Redirect
to the OAuth page at Box so the login credentials can be
entered.
'response_type=code'
+
'&client_id='
+ boxClientID +
'&redirect_uri='
+ redirectURI);
return
pr;
}
private
void getBoxToken(){
Http
h = new Http();
HttpRequest
req = new HttpRequest();
req.setEndpoint(endPointValue);
req.setBody('Content-Type='
+ EncodingUtil.urlEncode('application/x-www-form-urlencoded', 'UTF-8') +
'&charset='
+ EncodingUtil.urlEncode('UTF-8', 'UTF-8') +
'&grant_type='
+ EncodingUtil.urlEncode('authorization_code', 'UTF-8') +
'&code='
+ EncodingUtil.urlEncode(codeFromBox, 'UTF-8') +
'&client_id='
+ EncodingUtil.urlEncode(boxClientID, 'UTF-8') +
'&client_secret='
+ EncodingUtil.urlEncode(boxSecretCode, 'UTF-8') +
'&redirect_uri='
+ EncodingUtil.urlEncode(redirectURI, 'UTF-8'));
req.setMethod('POST');
HttpResponse
res = h.send(req);
//Get back this…
{"access_token":"RETURNED_ACCESS_TOKEN",
// "expires_in":3600,
// "refresh_token":"RETURNED_REFRESH_TOKEN",
// "token_type":"bearer"}
parseAuthJSON(res.getBody());
if(accessToken
!= null & accessToken !=''){
//Try to get items from a folder in Box
getBoxFolder();
}else{
//Just
some debug lines to see the request and response
valuetoShow
='Get Authorization Code Return: ' + res.getBody() + ' end point value: ' +
endPointValue + 'request: ' +
req.toString()
+'request headers: ' + req.getHeader('Content-Type') + '; ' +
req.getHeader('charset') +
'request
body: ' + req.getBody();
}
}
private
void getBoxFolder(){
Http
h = new Http();
HttpRequest
req = new HttpRequest();
//Returns
this: {"total_count":2,"entries":[
//
{"type":"file","id":"8308841816","sequence_id":"0","etag":"0","sha1":"6dce26ad1a3578a00a40722ec4472abc143313cf",
// "name":"Luschen
Quote for West Fargo Property.pdf"},
//
{"type":"file","id":"8308878690","sequence_id":"1","etag":"1","sha1":"5b595457a86396ddf45318d1ab9ddd6aa3b7bc1e",
// "name":"New
Google Doc 1.gdoc"}
//
],"offset":0,"limit":100,"order":[{"by":"type","direction":"ASC"},{"by":"name","direction":"ASC"}]}
//This
one works to get the properties for a specific
file
//endPointValue
='https://api.box.com/2.0/files/8308878690?fields=modified_at,path_collection,name';
//Returns
this
{"type":"file","id":"8308878690","etag":"1","modified_at":"2013-05-25T16:08:52-07:00",
// "path_collection":{"total_count":2,"entries":[
//
{"type":"folder","id":"0","sequence_id":null,"etag":null,"name":"All
Files"},
//
{"type":"folder","id":"904543862","sequence_id":"1","etag":"1","name":"Buy
Fargo Home"}
//
]},"name":"New Google Doc 1.gdoc"}
req.setEndpoint(endPointValue);
req.setHeader('Authorization',
'Bearer ' + accessToken);
req.setMethod('GET');
HttpResponse
res = h.send(req);
//Now
we could parse through the JSON again and get the values that we want
valuetoShow
='Get Folder: ' + res.getBody();
}
private
void parseAuthJSON(string JSONValue){
JSONParser
parser = JSON.createParser(JSONValue);
accessToken
='';
refreshToken
='';
while
(parser.nextToken() != null) {
if(parser.getCurrentToken()
== JSONToken.FIELD_NAME){
if(parser.getText()
=='access_token'){
parser.nextToken();
accessToken
= parser.getText();
}
if(parser.getText()
=='refresh_token'){
parser.nextToken();
refreshToken
= parser.getText();
}
}
if(accessToken
!='' && refreshToken != ''){
break;
}
}
}
}
|
Visualforce Code…
<apex:page
showheader="false" sidebar="false" cache="false" contenttype="text/html" controller="BoxConnect">
<apex:form>
<apex:commandbutton
id="connectToBox" value="Connect
to Box" action="{!boxConnect}">
</apex:commandbutton>
<apex:outputtext
id="outputText" value="{!valueToShow}">
</apex:outputtext>
</apex:form>
</apex:page>
|
No comments:
Post a Comment