As a little hobby project I'm working on a web app that taps into steemit. I think sometimes the steemit website is not so easy to use, so I'm trying to see if I can make a better version.
My first objective was to make sure a visitor could log in to his Steemit account, which will be required if I want to enable them to vote, follow, comment, etc. through my app.
After looking around I quickly found out that the steem-js API I'm planning to use is not very well documented, especially on the subject of authenticating a user. Thankfully I stumbled upon steemconnect, which already solved that problem for me.
Preparations
I'll be using NPM to install the dependencies I need, namely Angular and steemconnect. If you don't have that, make sure to install node and NPM before you proceed.
You'll also need some kind of terminal application to use NPM and the Angular CLI. I just use Terminal on my macbook.
Regular old Terminal on OSX showing the contents of my app folder
Setting up your app
I decided to build my app using Angular 4. The steemconnect API is framework agnostic, so if you choose to use another framework that will work equally fine. Just take the relevant bits from my code and use them in whatever way they fit in your app.
Because the login functionality was the first thing on my list to implement, I started with a fresh install . I won't go into detail explaining the installation of an Angular app, there's plenty of tutorials out there.
After running ng new kanzeon
(where "kanzeon" is the name of my app) to generate my app, I enter the newly created directory. Here I will install the steemconnect
package:
> npm install steemconnect --save
Now we have the steemconnect API available in our node_modules, so let's figure out how to use it.
Registering an app at steemconnect
Before we can even use the steemconnect API we need to register an account there. Go to steemconnect.com and log in using your Steemit account. Once logged in, choose the "Developers" link in the menu and click "Setup your app"
Here we can enter some important information about the app we want to log in with. First of all your name. I just entered "pilcrow", but it doesn't seem to matter that much.
The requested permissions section is where you decide what permissions your users should delegate to your app. If the purpose of your app only is to upvote people, then all you need is the upvote permission. I would like my users to be able to do everything they can in steemit, so I'm asking them all permissions.
Allowed origins is required as a security measure. It tells steemconnect from which websites I'll let my users log in, so they'll only allow requests from those addresses. Try to connect from any other address and it'll give an error. I entered both http://localhost:4200
(my local address where I run my Angular app during development) and http://kanzeon.litso.com
, the address where I'll host my app online. If I decide to buy a domain name like kanzeon.com, I'll have to add that to my "allowed origins" list as well.
Allowed redirect urls is very similar. When users try to log in to my app, they'll get redirected to steemconnect to do the actual logging in. After they succeeded, steemconnect will redirect them back to my app. Again as a security measure, you'll have to enter the urls to which the app is allowed to redirect.
In the bottom there are also two options, Development and Production. I have yet to figure out which does what exactly, but because I'm stil developing I set it to "Development".
Creating a login page
Now that we've registered with steemconnect we can make a page where users can log in. For now I'll just do that on the home screen of my application. Here's what the HTML for app.component.html
looks like.
<h1>My Angular App</h1>
<a [href]="url">Log in to steemconnect</a>
<pre [innerHTML]="message"></pre>
The url
link is dynamic, because we need to generate it using the steemconnect API based on our app settings (see below). The message
will be filled after we try to connect with steemconnect. The first time you load the page this will show an error message, because you haven't logged in yet.
Error 401 means "not authenticated", because we haven't logged in yet
Here's the code in app.component.ts
that attempts to log in.
import {Component, OnInit} from '@angular/core';
import * as steemconnect from 'steemconnect';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
message: string;
url: string;
ngOnInit() {
steemconnect.init({
baseURL: 'https://steemconnect.com',
app: 'pilcrow',
callbackURL: 'http://localhost:4200'
});
this.url = steemconnect.getLoginURL();
steemconnect.isAuthenticated((err, result) => {
if (err) {
this.message = err;
} else {
this.message = `Logged in as ${result.username}`;
}
});
}
}
On line 2 you can see that I import steemconnect
from the node modules. This is necessary to interact with the API. When the app initializes the ngOnInit()
function is run, doing the following:
Initializing steemconnect. By running steemconnect.init()
I tell steemconnect I plan to connect to their API. I pass along three arguments:
baseURL
is optional and defaults tohttps://steemconnect.com
. I entered that same address just as an example.app
is the name of my Steemit account. I wanted to change this to "Kanzeon" as that is what I'll name my Angular app for now, but that doesn't seem possible. I created my app by logging in as @pilcrow, so that's the name we'll have to use.callbackURL
is the address that steemconnect redirects the user to after they successfully logged in. When I upload my app to my web server I'll have to change that tohttp://kanzeon.litso.com
but for nowlocalhost
will do.
Getting the login URL. After initializing the API I can request a login URL by calling steemconnect.getLoginURL()
. I store that in the url
property of my controller so that it will be used in the template (remember the link with [href]="url"
?).
Trying to authenticate. The next step is connecting to steemconnect to see if we're already logged in, by using steemconnect.isAuthenticated()
. On a first visit we won't be logged in, so the request will return an error. We know that in the code because the err
argument will be filled. If so, we fill the message
field in the HTML with the error message, so the user know's what's up.
This is where the user should click the link to log in. They get redirected to steemconnect.com, and after logging in it will redirect them back to our app.
Logged in
If the err
variable is not filled the request was successful, which means the result
argument should contain some information. We receive the following information:
{
userId: 204451,
isAuthenticated: true,
username: "pilcrow",
permissions: [
"vote",
"follow",
"reblog",
"comment",
"post"
],
token: "[redacted]"
}
The token is stored in your cookies, so that on next requests steemconnect will know that you're already logged in.
For now we only take the username and display it in our HTML, to tell the user they successfully logged in.
Note: If you followed my instructions and keep getting a 401 error even after logging in, check if you have "third party cookies" allowed in your browser. If you have disabled those, authentication will keep failing.
Try it yourself right here: http://kanzeon.litso.com
Oobviously the page will change while I work on improving the app, but there will always be a login option available somewhere on it.
If you want to see all the code for this post visit https://github.com/stephanmullerNL/kanzeon/tree/login-with-steemconnect.
Success!
And there you have it! Now that the user is logged in to our app, we can start letting them interact with Steemit. Next up we'll load a couple of posts and let the user upvote one. I'm blogging this "live" while developing the app, so as soon as I've built the next step I'll write another post about it.
Let me know if this was useful, or if you have any questions!