Accessing the Coinbase API using OAuth2
Jennifer Bland
Posted on January 24, 2022
Coinbase is a cryptocurrency exchange where you can buy popular coins like Bitcoin and Ethereum. In these series of articles I will show you how to utilize the Coinbase API to see a list of cryptos that you hold as well as all the transactions for a specific crypto coin. We will be creating a Node.js application to access the Coinbase API.
Coinbase API Options
You can access the Coinbase API here. Coinbase has two types of APIs
- API Key
- OAuth2
The API Key is used to access your account on Coinbase. The OAuth2 API is used to authenticate to coinbase for any user and then have access to all the API functionality.
For this demo, I want to make this available to everyone to use not just myself so we are going to use the OAuth2 API.
Create Developer Account
To use the Coinbase API you will need to create a developer account which is free. I will not walk you through the steps to create an account.
Once you have created your account, click on the My Apps
button in the top right corner.
Click on the New OAuth2 Application button
. You will be given this form to complete for your application.
For Application Name
, I put API Demo.
For Description
, I put Demonstration of the Coinbase API.
For Permitted Redirect URIs
, I put http://localhost:3000/callback. NOTE: if you are hosting your website somewhere then you will need to replace the URI above with the URI of your host.
At bottom of form are a series of radio buttons. I selected No for all of them.
Check the box to accept the Coinbase terms for developers.
Once you have the form completed, click the Create Application
button.
After Coinbase creates your application, you will be shown your Client ID
and Client Secret
. Save these because we will be using it in our application.
Creating our Node Application
I am using the express-generator to scaffold out the Node.js application. In your terminal use this command to create your Node application:
npx express-generator -e --view=ejs coinbase-demo
I will be using EJS as my view and template engine so I have included options for it. My application is coinbase-demo.
Change into the directory that contains your application with this command:
cd coinbase-demo
Install all the dependencies next:
npm install
Before we start editing I want to install 3 additional packages that we will be using. You can install them with this command:
npm install axios nodemon qs
Open the application in your editor.
Configuring Start Script
The express generator app goes through a process to verify the port value you give it at startup. This is done in the file bin/www
. I don't like the way this is done so I am going to completely bypass it.
Open the package.json
file. Update the start script so that it looks like this:
"start": "nodemon app.js"
Next open up the app.js
file. After the line for logger add the following 2 lines:
const axios = require('axios');
const port = process.env.PORT || 3000;
NOTE: the port must match the value you used for your redirect URI in your Coinbase application.
Since we will be putting all our routes in a single file you can delete the line for usersRouter
and the line where it is set in app.use section. You can also delete the users.js
file in the routes directory.
We will no longer be exporting the app.js file so delete the last line that was exporting it. Replace it with the following:
app.listen(port, '0.0.0.0', function () {
console.log("Server starting on localhost:" + port);
});
You can now delete the bin
directory and the file www
contained in it.
Start your server by entering the following command in the terminal:
npm start
Open your browser and enter the URI localhost:3000
. You should see the following:
Authenticating with Coinbase OAuth2
We are going to use the Coinbase OAuth2 to validate any user that wants to use our application. You can find the details here.
On the homepage of our application we need to add a button that calls the Coinbase endpoint and passes in any parameters we want to add.
Open up the index.ejs file in the views folder. Add the following button below the paragraph with the Welcome line:
<a href="https://www.coinbase.com/oauth/authorize?response_type=code&client_id=2240e80398486d147c6a3e2e48e63b3d9a562497ad85bcd3300b7dda67eae42d&redirect_uri=http://localhost:3000/callback&state=MY_SECRET_KEY&scope=wallet:user:read,wallet:user:email,wallet:accounts:read,wallet:transactions:read&account=all" class="btn">
Connect with Coinbase
</a>
You might notice that that is one very, very long a
tag.
Right above it is the welcome message that displays a title
that is passed into the file. Let's simplify our button by passing in the appropriate values.
Open up the index.js
file in the routes folder. After the router variable add the following lines. Make sure to put in your client_id and callback URI from your Coinbase OAuth2 application:
const SECRET = "MY_SECRET_KEY";
const REDIRECT_URI = "http://localhost:3000/callback";
const CLIENT_ID = "2240e80398486d147c6a3e2e48e63b3d9a562497ad85bcd3300b7dda67eae42d";
const SCOPE = "wallet:user:read,wallet:user:email,wallet:accounts:read,wallet:transactions:read";
In the router.get
it passes in an object that currently has a value for the title
. Add the following so that they are passed in:
router.get('/', function(req, res, next) {
res.render('index', {
title: 'Express',
CLIENT_ID: CLIENT_ID,
REDIRECT_URI: REDIRECT_URI,
SECRET: SECRET,
SCOPE: SCOPE,
});
});
Now we can update our button to use the values in our button. Go back an open up the index.ejs file in the views folder. Update your button to be this:
<a href="https://www.coinbase.com/oauth/authorize?response_type=code&client_id=<%= CLIENT_ID %>&redirect_uri=<%= REDIRECT_URI %>&state=<%= SECRET %>&scope=<%= SCOPE %>&account=all" >
Connect with Coinbase
</a>
Now when you view your application in your browser you should see this:
I am not so keen on how this button looks. Add a class="btn"
to the button. Open up the file style.css
in the public/stylesheets directory. Add the following css:
.btn {
width: 100%;
background: #2364d2;
border: none;
border-radius: 5px;
font-size: 16px;
font-weight: 500;
padding: 8px 15px;
font-family: "Source Sans Pro", sans-serif;
color: #fff;
cursor: pointer;
text-decoration: none;
}
Now our buttons looks like this:
Now click on the button. You should get a screen to login to your Coinbase account
Enter your Coinbase userid and password to login to your account. Once logged in your will be presented with an option to authorize our application to access your account:
After you authorize the application you will get a 404 error page. This is because Coinbase is redirecting back to the redirect URI which is http://localhost:3000/callback
. There is no route to handle that which is why you are seeing the error message.
Handling Callback Route
Let's go back to the Coinbase API documentation. After authorizing your application it says you must make a call to the token endpoint to get a new token for the user.
We will make the call to the token endpoint when Coinbase calls our redirect URI.
Open up the index.js
file in the routes directory. Add the following code to handle the callback route:
// User gets redirected to this endpoint on successful login
router.get("/callback", async (req, res) => {
const { code, state } = req.query;
if (state === SECRET) {
const data = qs.stringify({
'grant_type': 'authorization_code',
'code': code,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'redirect_uri': REDIRECT_URI
});
const config = {
method: 'post',
url: 'https://api.coinbase.com/oauth/token',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data
};
try {
const response = await axios(config);
res.send({ response: response?.data });
} catch (e) {
console.log("Could not trade code for tokens", e)
}
}
});
Let's walk through this code.
After our application is authorized, Coinbase call our redirect URI and passes it two query params - code and secret. We are destructuring them into variables.
When we called Coinbase initially we passed in a secret phrase which is returned to us. This verifies the call came from Coinbase. We check to make sure the value that is returned is the value we sent Coinbase initially.
Next we are going to stringify the data we will be sending to Coinbase to get the token for the user. We will use the qs
package we installed when we created our application. Add the following line at the top of the file to import it:
const qs = require('qs');
The object that we will stringify has the following values:
grant_type
must have the value 'authorization_code'.
code
has value of code that was destructured from the query params.
client_id
has the value from the CLIENT_ID variable.
client_secret
has the value from the CLIENT_SECRET variable. This variable does not exist so add an entry in the variables for it and set its value to the CLIENT_SECRET in your Coinbase application.
redirect_uri
has the value from the REDIRECT_URI variable.
Next we create a config
object that will passed into axios. We will use axios to make the POST
call to Coinbase to get the token. We don't have axios defined yet so add its import at top of the file:
let axios = require('axios');
For right now we are going to display the contents of what is returned from Coinbase in our browser with this line:
res.send({ response: response?.data });
Let's test everything. Go to your browser and navigate to the URI http://localhost:3000
.
Click the button to connect to Coinbase. Log in if requested. Authorize your application. You should get an object similar to this displayed in your browser:
Now we have an access token that we can use when accessing the Coinbase API to get information on this account.
What's Next
In the next article, we will expand on what we have created so far. We will explore the Coinbase API to display a list of all the crypto tokens that the user has in their Coinbase account. We will then show all the transactions for each crypto token. Check out next article here.
Posted on January 24, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.