Share
BLOG

IEX Cloud OAuth

Summary:
In this post, we'll use IEX Cloud OAuth to apply back-end authentication, along with front-end token extraction.

Quick Summary: In this article we will be implementing authentication using IEX Cloud OAuth. We will be applying a back-end to handle the authentication, along with a front-end to demonstrate how to extract the token from cookie storage. You will need an IEX Cloud business account in order to create an application and allow authentication.


Tech Requirements:

Node.js is a runtime used for building fast and scalable applications.

React is a free and open-source front-end JavaScript library for building user interfaces or UI components.



Prerequisites:

  • An understanding of HTML, CSS, JavaScript, Node/Express, and React.
  • A text editor for modifying files.
  • A web browser (e.g. Chrome, Firefox).
  • Node.js and npm installed.
  • An IEX Cloud business account and a test application.



Setting up our application

To set up our application, we need to create a project folder. Create a folder and name it iex-auth-example.



Setting up the back-end

Inside the iex-auth-example folder, create another folder and name it server. This is where the majority of authentication will take place.

  • Using the command line, navigate to the back-end folder and run `npm init -y`. This will create a package.json file in our back-end folder to be used as part of our server component.

We will need to install the following packages in order to build our server component.

  • express gives us a nice interface to handle routes.
  • express-openid-connect is middleware implementing sign on for Express web apps using OpenID Connect.
  • node-fetch gives us the ability to perform a GET request in order to obtain a token. Make sure to install version ^2.6.1
  • nodemon automatically restarts our server after we make changes.

Ok, let’s get started. We need an index.js file which is where our server code will live. Create a directory in the server folder named src. Now inside of that directory, create a file named index.js.


We don’t have any server code yet, but let’s go ahead and test the back-end and make sure we have everything set up properly. In the package.json file we created previously, add an item to the scripts section.

"watchdev": "./node_modules/.bin/nodemon ./src/index.js"

<p><script src="https://gist.github.com/attila135786/41dbb66f53c200bd1b20c8ef08252bda.js"></script> </p>

This will allow us to run our server using npm. From the command line in the server folder, run the following command.

npm run watchdev

Validate that everything is up and running as expected.


Let’s now open our index.js file and begin the fun part, let’s write some actual code. At the top of the file, let’s import our packages we will be using throughout this implementation.


const express = require("express");
const {auth, requiresAuth} = require("express-openid-connect");
const fetch = require("node-fetch");

<p><script src="https://gist.github.com/attila135786/a6d80ad1779319fbf1faae9f3e56cfe3.js"></script></p>


These packages were explained a little during the installation section but they will be described in more detail as we move forward.


Let’s go ahead and create our root router

const root = express.Router()

<p><script src="https://gist.github.com/attila135786/e041ce239d7b98e074604d17ea14fa44.js"></script></p>

/auth is the route that this router will be built upon but we will set that later when we create a .env.dev file. Now let’s use this router to set up our auth route.

root.use(
  (req, res, next) => {
    next()
  },
  auth({
    authRequired: false,
    idpLogout: true,
    authorizationParams: {
      response_type: "code",
      scope: "openid profile read:pk offline",
    },
    getLoginState: (req, _) => {
      return {
        returnTo: `${process.env.BASE_URL}${req.url}`
      };
    },
    routes: {
      logout: false
    },
  }))

const app = express();

app.use(process.env.BASE_PATH, root)


<p><script src="https://gist.github.com/attila135786/b4cb13a190a565cdc2624518e6ad74bd.js"></script></p>

Ok, let’s create a route named /token. Remember that since we set what we did above with the root route, to hit the /token endpoint, we will need to actually hit /auth/token. Here is how we define the token endpoint. We will console.log as a test to make sure we can hit the endpoint properly.

root.get("/token", requiresAuth(), async (req, res) => {
  console.log("test")
});

<p><script src="https://gist.github.com/attila135786/e041ce239d7b98e074604d17ea14fa44.js"></script></p>


Navigate to localhost:3001/auth/token. In your server console, you should see the string test printed. Now let’s handle actually getting the token and saving the token as a cookie. Replace the console.log in the token endpoint with this code.

let {isExpired, refresh, token_type, access_token} = req.oidc.accessToken;
  if (isExpired()) {
    await refresh();
  }

  const {token} = await (
    await fetch("https://iexcloud.io/oidc/me", {
      headers: {
        Authorization: `${token_type} ${access_token} `,
      },
    })
  ).json();

  return res
    .cookie("iex-pk-token", token, {httpOnly: false, secure: true})
    .redirect(req.query.redirect || '/');

<p><script src="https://gist.github.com/attila135786/b4cb13a190a565cdc2624518e6ad74bd.js"></script></p>


req.oidc.accessToken contains 4 variables we will use:


  • isExpired is a function which returns a boolean value if the token has already expired.
  • refresh performs refresh_token grant type exchange and updates the session's access token.
  • token_type is the type of access token, normally "Bearer".
  • access_token is the access token itself, it can be an opaque string, JWT, or non-JWT token.


Of course, if the token expires, we await a refresh. From here, we make a request to https://iexcloud.io/oidc/me with the Authorization header. A proper solution would be to surround this code with a try/catch in case something goes wrong during the fetch and response. At this point, we have a token and can create a cookie and redirect back to the client, which we will create in the next section. 


const port = 3001;

app.listen(port, () => {

  console.log(`Example app listening at http://localhost:${port}`)

})

<p><script src="https://gist.github.com/attila135786/91ccc16fea950129d3d3b1ba5632262b.js"></script></p>




Setting up IEX Cloud account and create .env.dev file in server

To authenticate properly, we need to create an IEX Cloud account and a project underneath it. Create an account by navigating to https://iexcloud.io . You will need a business tier account in order to use the Oauth features. This may change in the future. Navigate to the Oauth section after logging in and create a new application. Name it whatever you would like and write a description for the application. In the callback url, you will be using http://localhost:3000/auth/callback . Give the application permission to access everything at the moment. You can better define what it should be able to access specific to your use-case. Reveal the App ID and App Secret and save those somewhere on your computer which will be easily accessible. In your server folder, create a .env.dev file. Here is a sample


ISSUER_BASE_URL=https://iexcloud.io/oidc/.well-known/openid-configuration
CLIENT_ID=AppID
BASE_URL=http://localhost:3000/auth
CLIENT_SECRET=AppSecret
SECRET=AppSecret
BASE_PATH=/auth

<p><script src="https://gist.github.com/attila135786/05a01925ecbd4ed14071f09c91fdc584.js"></script> </p>


Once correct values are added to this file, we can re-run the server and we can verify that the dot-env package picks up the environment variables by looking at the console of the server. It is now time to test. Navigate to http://localhost:3001/auth/token and you should be redirected to the IEX Cloud login page. Login from here, follow the instructions on screen (other than clicking the button after using the two-step authentication, make sure you wait for the redirect). We should now be redirected to the client, but we don’t yet have a client running. We will set up the front-end in the next section.


Setting up the front-end

Inside the iex-auth-example folder, create another folder and name it client. The client will be using the back-end authentication mechanism we created in the previous step. For this example, we will be using React and create-react-app. In the client directory, run the following command.

npx create-react-app .

This will create a react application in the client directory since we are currently in the client directory. Once this has been created, run this command to start the client. We need both server and client running in order to have everything work properly.

npm start 

To show we are getting a proper token, let’s update the App.js file of the client to look something like this

import './App.css';
const getToken = () => {
  const cookie = document.cookie
  const cookiePairs = cookie.split('; ')
  const tokenString = cookiePairs.find((row) => row.startsWith('iex-pk-token='))

  const token = tokenString ? tokenString.split('=')[1] : undefined
  return token
};

function App() {
  return (
    <div className="App">
      <header className="App-header">
        {getToken()}
      </header>
    </div>
  );
}

export default App;

<p><script src="https://gist.github.com/attila135786/1555d4842c50584032ec452201c96a1a.js"></script></p>



getToken extracts the token from the cookie. So when we are redirected back to the `front-end/client, we should see the token printed to the screen. Let’s go ahead and try it now. In your browser, navigate to http://localhost:3001/auth/token, go through the login process as you did before, but this time since the front-end is up and running, we should be redirected back to the front-end and the token should be printed to the screen.



Conclusion

In this article, we have seen how to create a server in Node.js which integrates with IEX Cloud Oauth, redirects to the client and stores a cookie of the token to be used on future requests. Unlike other frameworks, building an application with React and Express is quite easy and fast. This allows us to quickly set up IEX Cloud Oauth and obtain some of the most detailed financial data in the industry.


Subscribe to our quarterly newsletter

Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.