Intro to Authentic
November 12th, 2015
An introduction to using Authentic to add authentication to your web apps and microservices.
I. What's this Authentic thing?
Authentication is knowing who a user is. Authorization is knowing what a user is allowed to do. Authentic helps with authentication by letting you identify a user by their email address in your apps and services. Once you know a user's email address, you can use this as a unique ID to handle authorization.It's also useful as an ID for storing and retrieving other info and meta data (like name, phone number, address, etc...).
Authentic can be run as a standalone server that will sign users up (get their email and password), send them a confirmation email (so you know that it's them), and of course let them log in. In this case, when they log in, Authentic will respond with an authentication tokenThe token is a JSON Web Token or JWT. Essentially it's an encrypted JSON object. that can be used by other services and apps to know the user's email -- without having to make a request to a central server each time.
Authentic can also help on the service and client sides to make requests to the server and decrypt the token. Here's how the whole system would look for a user logging in and requesting a report from a separate microservice:
Of course, the user doesn't have to log in for each request, and the microservice can cache the server's public key, so 99% of the time it would just be this:
II. Sounds cool, why would we use it?
Here's a common situation: your company has a bunch of microservices, and you need to make sure that they are only accessible to the people you deem worthy.
For example, let's pretend you're in charge of engineering for ScaleHaus, and for simplicity, you want to start your microservice empire with the following two apps/services:
reporting.scalehaus.io is your reporting/analytics microservice and is a JSON REST API and
admin.scalehaus.io is a single-page-app UI for viewing reports that lives on a CDN and has no server component.
To add authentication and authorization (restrict access to ScaleHaus employees) you could do the following:
1) Create an authentication server with
authentic-server and make it available at
authentic-client to add views to
admin.scalehaus.io for signup/confirm/login/reset-password and for requests to
authentic-service to decrypt the authentication token provided in the request and verify the user's identity and that their email ends in "@scalehaus.io".
III. OK, let's do it!
Great, glad you're on board. Let's walk through building out the hypothetical situation above.
Step 1: The Server
First, grab your favorite terminal and create a new directory for your authentication server (
auth.scalehaus.io in the above scenario):
Next, we'll create our public and private keys:
Now that we have those, we can create our server. Create a new file
server.js Fun fact:
npm start will run
node server.js by default and use
authentic-server like so:
npm start and you should have your auth server running. To test it out, let's open a new terminal and use
curl to sign up a new user:
The response to the curl should look like this:
And your auth server should have logged something like this:
There are two things to note. First, because the
sendEmail function we gave
authentic-server doesn't actually send email, it just logs the email data to the terminal, that's what it did.If you'd like to see an example of a
sendEmail function that actually sends email, here's one using Mandrill and powerdrill Second, when you sign up a user,
authentic-server requires three things: 1)
confirmUrl. To confirm a user, we want to verify that the user owns that email address. To do this, we send an email to that address and they return with the correct confirmation token.
confirmUrl is where we'd like them to return to.
Astute readers will note, however, that the url we provided doesn't exit yet, and we can't confirm our user -- let's change that real quick.
Step 2: The Client
Create a new, separate project and directory for our "admin" app:
This app will be client-side only, so we'll make life easy by using
wzrd to give us a static server that will automatically run browser JS for us:
npm i --save wzrd
Once that's done, edit your
package.json to add a start script that will run
wzrd index.js. The relevant part of
package.json should look like this:
To verify that it's working, let's add an obnoxoius
echo "alert('hi from wzrd')" > index.js
npm start and open the app by going to http://localhost:9966 in your browser of choice. You should see the alert.
Rockin, we have our browser code up and running. Let's use
authentic-client to provide an interface to our auth server. Install
npm install --save authentic-client
Now we'll create a user interface using
authentic-client to talk to
authentic-server. We could do this part with React, Mercury, Backbone, Angular, Elm, Mithril, etc... but for simplicity copy this vanilla approach into
index.js and reload. You should see something like the following:
Feel free to go through the sign up/confirm/login flow. 95% of
index.js is now UI wrangling, but you can see examples of
authentic-client's use in
Once you log in, the UI will attempt to hit your not-yet-created microservice. Your nonexistant microservice will not respond, and you'll see a network error.
But here's the good news: all that's left now is to create a microservice with a protected endpoint!
Step 3: The Service
Open up a new terminal and create a new project/directory:
Create an http server in
server.js that uses
authentic-service like so:
Once that's running you can either use authentic-client (either in node or in browser) or
curl to make authenticated requests.If you use
curl or are crafting the HTTP request yourself, place the auth token in the
Authorization header using Bearer schema. It should look like this:
Authorization: Bearer eyJ0eX.... For more info see How do JSON Web Tokens Work?
Feel free to change the authorized email(s) in
authorized to either block or allow requests based on the identity of the user.
You now have the basic scaffold for handling authentication with microservices: a standalone authentication server, a client/UI for handling user logins, and a protected microservice.
If you have any questions or ideas, feel free to reach out on Twitter or Github.