Getting started with Box Node.js SDK with OAuth 2.0

Olga Stefaniuk
Box Developer Blog
Published in
8 min readMay 16, 2023

Client-side OAuth 2.0 is one of the easiest ways to authenticate a user for the Box API. It is an open standard designed to allow users to grant other applications access to their data.

Box has quite a broad range of SDKs, including Python, Java, .NET, iOS and Node.js. Let’s create a simple project using the Box Node.js SDK and create an app where users can authenticate with OAuth 2.0. The app will consist of a login page and a main page with basic Box user data, accessible after successful OAuth 2.0 authentication.

Steps to create the app

  1. 📦 Create a Box App
  2. 📥 Initiate the project and install dependencies
  3. 📄 Create templates for a login and main page
  4. 🔐 Initiate the Box SDK instance and provide credentials
  5. 🔗 Get an authorization url
  6. 🏎️💨 Create an Express app
  7. 🗝️ Get an authorization token and create a persistent client
  8. 🚀 Initiate the server

📦 Create Box App

A few weeks ago, we launched a new app creation process, so let’s go through it very briefly. In the Developer Console, click Create App and choose Custom App.

Box Developer Console view, creating a new custom App

In the new creation process, you’re asked to fill out some additional details, like the app name, a short description, and the purpose of your app (in our case, a custom portal). In the following select element, choose Customer if you are a Box customer or Partner if you are building the application to be used outside of your organisation.

In the last step, choose User Authentication with OAuth 2.0 and create the app. In the Configuration tab, you’ll find OAuth 2.0 credentials: the client ID and client secret. We’ll need these values later on.

Redirect URI and CORS Domain

Let’s define the redirect URI: http://localhost:8000/authorize_callback. Once the user authenticates in our app with OAuth 2.0, they will be redirected to this route with a temporary code parameter. We’ll go into details a few steps later.

Box Dev Console, OAuth 2.0. Redirect URI settings

Lastly, we need to define the CORS domain; for now, let’s just add http://localhost:8000.

Box Dev Console, CORS Domains settings

The default Box application scope is read all files and folders. This setting is sufficient for now; however, if you wish to add more advanced features to your custom app, you might need to check the write all files and folders checkbox.

📥 Initiate the project and install dependencies

Open a terminal, create a new folder and initiate a new project.

mkdir name-of-node-app
cd name-of-node-app
git init

We’ll keep it very simple and install some basic dependencies:

  • Dotenv allows you to read and embed variables from .env file,
npm install dotenv --save
npm install express --save
  • express-session is a module for creating session middleware. Keep in mind that express-session is not the best solution for production-ready apps, and it might be a good idea to use another more secure memory storage implementation like Redis,
npm install express-session --save
npm install hbs --save
npm install --save box-node-sdk

The dependencies in the package.json file are:

{
"dependencies": {
"dotenv": "^16.0.3",
"express": "^4.18.2",
"express-session": "^1.17.3",
"hbs": "^4.2.0"
"box-node-sdk": "^2.8.1",
}
}

Let’s create the index.js file and import those modules. The built-in path module will help us access the hbs template files.

require('dotenv').config();
const express = require('express');
const session = require('express-session');
const path = require('path');
const BoxSDK = require('box-node-sdk');

env file

Let’s also create .env file. It’ll consist of three key-value pairs. The client ID and client secret can be found in the Box Developer Console in the Configuration tab we visited in the previous step. The session secret is used to hash the session and generate a strong one yourself (for this example, it might be a long randomized string).

CLIENT_ID='BoxAppClientID'
CLIENT_SECRET='BoxAppClientSecret'
SESSION_SECRET='SessionSecrerKey'

Add the .gitignore file and include the node modules folder and the .env file.

📄 Create templates for a login and main page

Let’s create a folder for storing project handlebars templates. First, we need a default layout.hbs file. To make things a bit more eye-friendly ✨, I included a CDN link to Bootstrap 5, but this is totally optional.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Box node.js SDK and OAuth sample app</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</head>

<body>
{{{body}}}
</body>
</html>

The login page contains a generated login link, which will redirect to the OAuth 2.0 authentication process. Let’s define the link as the login_url parameter. We’ll generate it a bit later using the Box SDK and pass it in to the template.

<main class="container">
<h1>Log in to Box Node SDK with OAuth sample app</h1>
<a class="btn btn-primary" href={{login_url}}>Login</a>
</main>

The main app view will include a Box user id, a Box user name pulled dynamically using the Box node.js SDK, and a logout link.

<main class="container">
<section>
<h1>Your account</h1>
<h2>Box user name: </h2>
{{ name }}
<h2>Box User id: </h2>
{{ id }}
<section>
<section>
<a class="btn btn-primary" href="/logout">Logout</a>
</section>
</main>

In the folder structure, I also included a static folder for serving images. Now the project structure should look like this:

Project folder structure

🔐 Initiate the Box SDK instance and provide credentials

In the index.js file, initiate the Box Node.js SDK by providing the variables from the .env file.

const sdk = new BoxSDK({
clientID: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET
});

🔗 Get an authorisation url

As mentioned earlier, we need a login url to redirect users to the OAuth 2.0 authorisation process. Let’s generate it in our index.js file. Also define a port here and make sure it matches the one passed in the Box configuration settings.

const PORT = process.env.PORT || 8000;

const authURL = sdk.getAuthorizeURL({
response_type: 'code',
redirect_uri: `http://localhost:${PORT}/authorize_callback`
});

🏎️💨 Create Express app

Now the fun part begins. We need to create the Express app, create a user session, and define the logic for the login page and main app view.

const app = express();

app.use(
// For production ready apps use other more secure memory storage implementation like Redis
session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: true,
// Secure will set cookies only on https but we in localhost here
// cookie: { secure: true }
})
);

// Optional - for static images and files loading
app.use(express.static(__dirname + '/static'));

// Use the hbs engine and pass the views folder
app.set('view engine', 'hbs');
app.set('views', path.join(__dirname, 'views'));

For the login page, let’s pass the authURL created in the previous step and render the login template.

app.get('/login', (req, res) => {
res.render('login', { login_url: authURL });
});
App login page

The main app page should be available only after a successful login. To achieve this, we need middleware that will check whether the user has an active session; otherwise, there is a redirect back to the login page.

const auth_middleware = (req, res, next) => {
if (req.session.user) return next();

res.redirect('/login');
};

Let’s pass the auth_middleware as a parameter to the main page handler. Render the main index.hbs template and pass user details.

app.get('/', auth_middleware, (req, res) => {
const user = req.session.user;

res.render('index', {
name: user.name,
id: user.id
})
});

🗝️ Get an authorization token and create a persistent client

Let’s handle the authorization callback. Catch the temporary code, and if it exists, create a token and a persistent client. Grab the user details and store them in the session. Once that is successful, redirect the user to the main app page. If the user denies granting access, they get an “Access denied” message.

app.get('/authorize_callback', async (req, res) => {
// Get the temporaty code
const { code } = req.query;

if (!code) return res.status(401).send("Access denied");

const tokenInfo = await sdk.getTokensAuthorizationCodeGrant(code);
const client = sdk.getPersistentClient(tokenInfo);
// Get user details
const user = await client.users.get(client.CURRENT_USER_ID);

// Save user in session for persistence, this is basic of auth middleware implementation
req.session.user = user;
// Split storing access token and refresh token for production
req.session.user_token = tokenInfo;

res.redirect('/');
});

Once you run the server, click the login link. You should be redirected to authorization page:

Authorization page
Grant access to Box view

Additionally, add logic for the logout link and destroy the user session.

app.get('/logout', (req, res) => {
req.session.destroy();
res.redirect('/login');
})

Lastly, create a 404 page with a Page not found! message.

app.use('*', (req, res) => {
res.setHeader('Content-type', 'text/html')
res.status(404).header().end('<h1>Page not found!</h1>');
})

🚀 Initiate the server

And finally, let’s initiate the server!

app.listen(PORT, () => {
console.log(`Listening to requests on port http://localhost:${PORT}`);
});

You can now run the application in the terminal by typing:

node index.js

Also, you may define the start script in the package.json file. Once you log in with your Box credentials and grant access to Box, you should be redirected to the account page.

Account page avaliable after successful login

Congratulations! 🎉 Now you can take your app to the next level with Box Node.js SDK.

Get more details:

Follow our Box Developers profile on Twitter to stay up-to-date!

Cheers!

--

--