Tutorial: OAuth2 Access Tokens and Refresh Tokens with Steemconnect

View this thread on: d.buzz | hive.blog | peakd.com | ecency.com
·@r351574nc3·
0.000 HBD
Tutorial: OAuth2 Access Tokens and Refresh Tokens with Steemconnect
# Motivation

As of late, there have been some phishing scams and the like that have made it such that it's not safe to give out your posting key to anyone. Not even to people you trust. This forced me, for my own applications, to stop requiring posting keys. Instead, we are looking at alternatives like steemconnect that allow users to grant us (developers) a trust.

There are a number of ways to do this, and that's what this tutorial is about. More than anything, it is a technical walkthrough about what many already know and use. I don't want this to be yet another steemconnect tutorial. There are plenty out there for this; however, some have approached me for a more detail-oriented explanation. WITH PICTURES!

----

#### What Will I Learn?

* The oauth2 flow that steemconnect uses
* How access tokens are actually obtained
* What refresh tokens are for
* Where refresh tokens come from
* How to use a refresh token to obtain an access token

#### Requirements

This tutorial assumes the reader is building an application with nodejs using the expressjs web framework.

#### Difficulty

This is an advanced tutorial that will utilize advanced HTTP knowledge and understanding of Oauth2.

----
# The Tutorial

If you are reading this, you should already know what steemconnect is and how you can use it with your application. This tutorial is not about how to use steemconnect.

## Retrieving Access Tokens

By now, you are familiar with setting up your `sc2-sdk`. Your javascript probably has something like this:

```javascript
  let api = sc2.Initialize({
    app: 'we-resist',
    callbackURL: 'https://we-resist-bot.herokuapp.com/',
    accessToken: req.query.access_token,
    scope: ['vote', 'comment', 'offline']
  })
```

This does not do very much. It just initializes stuff. In order to actually get an access token. You need to fetch a URL using your browser. How do you do this? And which URL? 

The URL you need can be found with `api.getLoginURL()`, and you can fetch it in one of two ways. If you are executing this from your browser, you would use:
```javascript
window.location.href = api.getLoginURL();
```

From your ExpressJS application, you would use the following in your routing configuration:
```javascript
res.redirect(api.getLoginURL());
```

![image.png](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520066803/gake1iu1oq0kjzecb4oe.png)

The request actually looks something like:

```
https://v2.steemconnect.com/oauth2/authorize?client_id=we-resist&redirect_uri=https%3A%2F%2Fwe-resist-bot.herokuapp.com%2F&scope=vote,comment,offline
```

This is important because what's happening is the client and return url are being sent to steemconnect. This will be important later. What happens is that this initiates the oauth2 flow. Next, you will be expected to login using your posting key or your memo key. 

![](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520066890/rtq0o70bcxarof1rff3n.png)

![](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520067005/eosr66cgoqcxdlvunlqr.png)

This is just to verify your identity. It isn't actually stored with steemconnect. Steemconnect has no idea about your keys. Once the login is completed and your identity is verified, steemconnect will set you up with a token. 

![](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520067041/iynnj61ngpohge5f5ehu.png)

How do you get the `access_token`? If you observe from the above diagram, steemconnect sends a request back to the application. It knows how to send this request because it is using the `redirect_uri` we mentioned earlier. It's basically a breadcrumb you left earlier. 

The request it follows back to is 
```
https://we-resist-bot.herokuapp.com/?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJyb2xlIjoiY29kZSIsInByb3h5Ijoid2UtcmVzaXN0IiwidXNlciI6InIzNTE1NzRuYzMiLCJzY29wZSI6WyJ2b3RlIiwiY29tbWVudCIsIm9mZmxpbmUiXSwiaWF0IjoxNTIwMDY3MjIyLCJleHAiOjE1MjAwNjc4MjJ9.SXAjVoWuldCzBTU4d2AoavPwkzKgsh1rsRjAxUdKg0Y&username=r351574nc3
```

It basically calls the application and passes the `access_token` in the query string.

## Refresh tokens

Access tokens are great for applications with a user, but what about refresh tokens? How do you get those?

For this we basically have to start over. All the way over.

```javascript
  let api = sc2.Initialize({
    app: 'we-resist',
    callbackURL: 'https://we-resist-bot.herokuapp.com/',
    accessToken: req.query.access_token,
    scope: ['vote', 'comment', 'offline']
  })
```

From here, the URL we are going to use is: `https://v2.steemconnect.com/oauth2/authorize?client_id=we-resist&response_type=code&redirect_uri=https%3A%2F%2Fwe-resist-bot.herokuapp.com%2F&scope=vote,comment,offline`


I have added my own `client_id` and `redirect_uri`. You will want to replace these with your own. Notice the `response_type` is `code`. We use this `response_type` to receive a `code` from steemconnect instead of an `access_token`.

![](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520067815/ztkcnpyvjylk6gtzcisl.png)

Once we have the code, we can use the code to retrieve the `refresh_token`. This is best done using `request`.

```
const rp = require('request-promise');

  return rp({
    method: "POST",
    uri: "https://steemconnect.com/api/oauth2/token",
    body: {
      response_type: "refresh",
      code: req.query.code,
      client_id: "we-resist",
      client_secret: sc2_secret,
      scope: "vote,comment,offline"
    },
    json: true
  })
  .then((results) => {
    let qs = "?access_token=" + results.access_token + "&refresh_token=" + results.refresh_token + "&username=" + results.username
    return res.redirect('/@' + results.username + '/preferences' + qs)
  })
```
What I have done here is fetched the `code` from the query string and used it to make a call (not from the browser) directly to steemconnect for an answer.  Steemconnect returns a response that looks like this:

```
{
    access_token: blah blah blah,
    username: blahblahblah,
    refresh_token: blah blah blah
}
```

Immediately, I have an `access_token` I can use, and a `refresh_token` for later. At this stage, I will probably persist the token (database, filesystem, etc...) to use at a later date.

## Using the Refresh Token

At some point that I do decide I need to use my `refresh_token`, how do I do that?

To do this, I created a function called `fetch_access_token`. 

```javascript
function fetch_access_token(user) {
    return rp({
        method: "POST",
        uri: "https://v2.steemconnect.com/api/oauth2/token",
        body: {
          refresh_token: user.refresh_token,
          client_id: "we-resist",
          client_secret: sc2_secret,
          scope: "vote,comment,offline"
        },
        json: true
      })
}
```

A couple things to note:
1. `https://v2.steemconnect.com/api/oauth2/token` is the url used. Previously, we had been using `authorize` instead of `token`. `token` is specifically for this purpose
1. `refresh_token` is sent in the `body`
1. `client_secret` is also required

`client_secret` is important. Unlike tokens, another cannot be reissued. You definitely do not want to let this into the wrong hands. `client_secret` is unique to your application. This is the secret given to you when you create your app with steemconnect. It's only real purpose is to process `refresh_tokens`.

The `client_secret` can be statically set as part of your application configuration. However, the `refresh_token` is bound to a user. In the previous steps, we persisted our `refresh_token` either to a file or a database. That means that in this step, part of the task will be to pull it back out.

This is the flow you are following:
![](https://res.cloudinary.com/hpiynhbhq/image/upload/v1520068546/o8fahrvt4gxgqropylpo.png)

1. Start processing steemit stream
1. Fetch users
1. Get `refresh_token` from user
1. Use `refresh_token` to get access token
1. Use `access_token`

Basically, we will follow something like this:
```javascript
  let api = sc2.Initialize({
    app: 'we-resist',
    scope: ['vote', 'comment', 'offline']
  })

const users = get_users_from_storage();
users.each((user) => {
    fetch_access_token(user)
        .then((token) => {
            api.setAccessToken(token);
            // Do stuff with api
        });
})
```

That is all you need to do to use the `refresh_token`.

----
#### Curriculum
Other steem tutorials in this series:

* [Tutorial: Getting Started with git-steem-bot](https://utopian.io/utopian-io/@r351574nc3/tutorial-git-steem-bot)
* [Tutorial: Weekly Digest Steembot in a Docker Container](https://utopian.io/utopian-io/@r351574nc3/tutorial-weekly-digest-steembot-in-a-docker-container)
* [Tutorial: Viewing Steemit Account History](https://utopian.io/utopian-io/@r351574nc3/tutorial-viewing-steemit-account-history)
    

<br /><hr/><em>Posted on <a href="https://utopian.io/utopian-io/@r351574nc3/tutorial-oauth2-access-tokens-and-refresh-tokens-with-steemconnect">Utopian.io -  Rewarding Open Source Contributors</a></em><hr/>
👍 , , , , , , , , , , , , , , , , , , ,