Calling an ASP.NET WebAPI From Aurelia

In my last article, I promised I would deal with authentication of an ASP.NET WebAPI. Well, to do that, I need a WebAPI and I didn’t want to mix the additions because of the WebAPI with the additions because of the authentication requirements. As a result, I decided to add a page to my Aurelia app that utilized the WebAPI to return some data.

Create a WebAPI

I’m going to create a simple WebAPI for this example. When I do a GET /api/spells, it will return a simple JSON object like this: {id: 1}. It’s really the most simple WebAPI you could possibly produce.

First off, I’ve already added Microsoft.AspNet.Mvc to my project.json file. I only have to create a Controller class. That is located in Controllers/SpellsController.cs. I had to create the Controllers directory since this is my first controller.

using Microsoft.AspNet.Mvc;

namespace aurelia_2.Controllers
{
    [Route("api/[controller]")]
    public class SpellsController : Controller
    {
        [Route("")]
        public string GetAll()
        {
            return "{id:1}";
        }
    }
}

You can test this with Postman or a similar REST client. Just send a GET request for /api/spells and you will see the embedded string returned. Note that I didn’t have to provide a route map to the app.useMvc() call in Startup.cs. It happens thanks to the decorators on the class.

Creating a new View in Aurelia

Back to my Aurelia page, I wanted to create a new view called “spells”. I need two files – pages/spells.html contains my view:

<template>
    <section>
        <h2>${heading} - ${code}</h2>
        <div id="data">
            ${data}
        </div>
    </section>
</template>

The heading, code and data variables are bound to the class – pages/spells.ts contains the definition:

import {inject} from 'aurelia-framework';
import {HttpClient} from 'aurelia-http-client';

export class Spells {
    public heading: string = 'Spells';
    public data: string = '';
    public code: string = '';
    private loading: boolean = false;
    private http: HttpClient = null;

    constructor() {
        var auth_token = localStorage.getItem("auth_token");
        if (auth_token != null) {
            this.http = new HttpClient().configure(x => {
                x.withBaseUrl(window.location.origin);
                x.withHeader("Authorization", "Bearer " + localStorage.getItem("auth_token"));
                x.withHeader("Accept", "application/json");
            });
        } else {
            this.http = new HttpClient().configure(x => {
                x.withBaseUrl(window.location.origin);
            });
        }
    }

    activate() {
        this.loading = true;
        return this.http.get("/api/Spells").then(response => {
            this.data = response.content;
            this.code = response.statusCode.toString();
            this.loading = false;
        });
    }


    canDeactivate() {
        if (this.loading) {
            return confirm("Still loading - are you sure?");
        }
        return true;
    }
}

The constructor should have a little explanation. Firstly, I pull the auth_token. If I’m authenticated, then I will create a new HttpClient object that contains the authorization. If the user is not signed in, then I create a new HttpClient() object without the authorization. That way, the usage of the WebAPI follows the status of the user. Signed in – send the authorization. Not signed in – don’t. I’d probably abstract this (and all the other authentication information) into it’s own class in a real application.

If you remember the flickr page from the Aurelia tutorial, you will note that the activate() methods and canDeactivate() methods (which are part of the page lifecycle that Aurelia provides). When I get a response from the server, I set the data and code and the values will get automatically reflected in the view.

Wire in the new View

Before I can use the view I’ve just created, I need to create a route for it. That is done within the configureRouter() method in app.ts:

        config.map([
            { route: 'welcome', name: 'welcome', moduleId: './pages/welcome', nav: true, title: 'Welcome' },
            { route: 'flickr', name: 'flickr', moduleId: './pages/flickr', nav: AuthorizeStep.isLoggedIn(), auth: true, title: 'Flickr' },
            { route: 'spells', name: 'spells', moduleId: './pages/spells', nav: true, title: 'Spells' },
            { route: '', redirect: 'welcome' },
        ]);

Don’t forget to clear your cache before reloading the page. I found that the browser hung on to this javascript file until I did.

Running the project will provide the appropriate response. You will see a Spells link on the top bar. Clicking on the Spells link will do an XHR request to the backend, which will then fill in the data for you. If you are viewing the page in Chrome, you can open up the Developer Tools and click on Network. Reload the page and check out the XHR request for /api/Spells – you will note the Authorization header if you are signed in.

This means I am now all ready for dealing with authentication. I have a page that should send the appropriate authentication when signed in. However, my backend is not configured to handle that authentication yet – in fact, it simply ignores it.

You can get this code from my GitHub Repository.

ASP.NET MVC6 Identity Part 4 – AJAX Authentication

In the last few articles, I’ve covered the following:

  1. Creating an ASP.NET Identity Database
  2. Data Annotations and Custom Validators for Models
  3. A WebAPI Authenticator
  4. An ECMAScript 6 Modal Dialog

Four articles and I still haven’t logged in to my application. Today that is going to change because I’m writing the front-end AJAX code to do the authentication handling.

Doing AJAX Request Promises

Some months ago, I wrote about doing ECMAScript 6 HTTP Requests with Promises. I have a library for that now and I’m going to use it in this project. It’s stored in Static/js/ajax.js. Let’s walk through it:

/**
 * Routines for dealing with AJAX
 */
/*eslint no-console:0 */
"use strict";

function callAjax(method, url, query, body, headers) {
    console.debug("[callAjax] method=%s url=%s query=%o body=%o headers=%o", method, url, query, body, headers);

One method is all it takes to handle all the AJAX functionality. Note that I’m using an eslint directive at the top to say “I’m going to use console statements, so be quiet about it”. When I change over to a non-debug version, I’ll remove that line and all the console statements.

    let uri = url;
    if (query != null) {
        console.debug("[callAjax] query has been specified - processing");
        if (typeof query === "object") {
            console.debug("[callAjax] query is an object");
            let qs = Object.keys(query).map(k =&gt; encodeURIComponent(k) + "=" + encodeURIComponent(query[k]));
            uri = uri + "?" + qs.join("&amp;");
        }
        else if (typeof query === "string") {
            // Assume the query string is already encoded
            console.debug("[callAjax] query is a string (adding unmodified)");
            uri = uri + "?" + query;
        }
        console.debug("[callAjax] New URI is %s", uri);
    }

The next block turns an object, say {"Email":"foo","Password":"bar"} into the appropriate URI encoded query string Email=foo&Password=bar. If the function got passed a string instead of an object, it just uses the string that is provided. It constructs the new URI based on this query string.

    let requestBody = "";
    if (body != null) {
        console.debug("[callAjax] Body has been specified - processing");
        if (typeof body === "object") {
            console.debug("[callAjax] body is an object");
            requestBody = JSON.stringify(body);
            headers["Content-type"] = "application/json";
        } else if (typeof body === "string") {
            console.debug("[callAjax] body is a string (adding unmodified)");
            requestBody = body;
        }
        console.debug("[callAjax] BODY = %s", requestBody);
    }

Next up is the body – used in POST and PUT REST calls. I’m using the JSON methods that are built into pretty much every browser these days. If the method is passed an object, I turn it into JSON and then update the headers to include a Content-type header. As with the query parameters, if I pass a string then I just include it and assume the caller knows what they are doing.

    return new Promise(function (resolve, reject) {
        console.debug("[callAjax] Creating new XMLHttpRequest");
        let request = new XMLHttpRequest();
        console.debug("[callAjax] Open a %s request to %s", method, uri);
        request.open(method, uri);
        for (var p in headers) {
            if (headers.hasOwnProperty(p)) {
                console.debug("[callAjax] Add header %s: %s", p, headers[p]);
                request.setRequestHeader(p, headers[p]);
            }
        }

        console.debug("[callAjax] Set resolve to the onload object");
        request.onload = function() {
            resolve(request);
        };

        console.debug("[callAjax] Set reject to the onerror object");
        request.onerror = function() {
            reject(request);
        };

        console.debug("[callAjax] Send requested body");
        request.send(requestBody);
    });
}

Finally, I construct the XMLHttpRequest wrapped in a promise. Since I expect that different codes are going to get returned, I’m not going to assume that 200 is the only valid code. I did this in the prior version of the library. Instead I say “success is when the server responds and failure is when the server does not response”.

/**
 * Helper Functions for each method
 */
function ajaxDelete(url, query, headers) { //eslint-disable-line no-unused-vars
    return callAjax("DELETE", url, query || {}, null, headers || {});
}

function ajaxGet(url, query, headers) { //eslint-disable-line no-unused-vars
    return callAjax("GET", url, query || {}, null, headers || {});
}

function ajaxPost(url, args, headers) { //eslint-disable-line no-unused-vars
    return callAjax("POST", url, null, args, headers || {});
}

function ajaxPut(url, args, headers) { //eslint-disable-line no-unused-vars
    return callAjax("PUT", url, null, args, headers || {});
}

export { ajaxDelete, ajaxGet, ajaxPost, ajaxPut };

Finally, I set up a number of functions that send the right arguments to the callAjax() method. GET and DELETE calls use a query method. POST and PUT calls use a body method. This way every method uses the same arguments and the right format gets sent to the backend.

Feel free to co-opt this library file for yourself.

Calling the WebAPI

Now, how do we use this library? In the last article I created a LoginModal class for handling the login modal. Let’s take a look at the new code:

/**
 * Handler for the Login Modal
 */
/*eslint no-console:0 */
"use strict";

import { ajaxPost } from "./ajax";

class LoginModal {
    /**
     * Constructor - store the ID that activates us and then
     * wire up the activator.
     */
    constructor(activatorEl, modalEl) {
        // Store all the elements for later
        this.activator = activatorEl;
        this.modal = modalEl;
        this.modalClose = modalEl.querySelector(".modalClose");
        this.submitButton = modalEl.querySelector("button#loginButton");

        // Make the activator cursor a pointer to show it is clickable
        this.activator.style.cursor = "pointer";

        // Wire up the click event handlers for the activator and modal close
        this.activator.addEventListener("click", (e) =&gt; { return this.activate(e); });
        this.modalClose.addEventListener("click", (e) =&gt; { return this.close(e); });

        // Wire up the submission button for the form
        this.submitButton.addEventListener("click", (e) =&gt; { return this.submit(e); });

        // Ensure the modal is hidden
        this.modal.style.display = "none";
        this.modal.style.opacity = "0";

        return;
    }

As with the AJAX library, I’m using the eslint directive to disable complaints about the console. I then bring in the ajaxPost method (the only one I need in this file) from the AJAX library above.

In the constructor, I’ve added information about the submit button and wired up an event handler for when the user clicks on the submit button.

   /**
     * Someone hit the submit button.
     */
    submit(e) {
        let modal = this.modal,
            submitButton = this.submitButton,
            spinner = "<i class='fa fa-spinner fa-pulse'></i> ",
            submitContent = this.submitButton.innerHTML;

        // Deactivate the form
        submitButton.disabled = true;
        submitButton.innerHTML = spinner + submitContent;

The first thing we do when going into the submit button event handler is to deactivate the form. Sometimes you will have a slow link – you don’t want someone clicking repeatedly on the submit button and having that kick off tons of requests to the backend – the idea is to reduce the load on the backend, not increase it. To indicate that the form is busy, I’ve added a spinner to the button content.

        // Validation goes here (eventually)

        // Submit AJAX Request
        let requestArgs = {
            "Email": this.modal.querySelector("input[name=Email]").value,
            "Password": this.modal.querySelector("input[name=Password]").value
        };
        console.debug("[LoginModal#submit] requestArgs = %o", requestArgs);

I’m not doing client side validation (yet). I’ll get to it. From the WebAPI work, I know that my request has to be a JSON request with the Email and Password fields, so I need to construct an object that I can pass along. Next step is the actual AJAX call:

        ajaxPost("/api/login", requestArgs)
            .catch(function(error) {
                console.error("[LoginModal#submit] Error in AJAX Call to /api/login: %o", error);
            })
            .then(function (response) {
                console.debug("[LoginModal#submit] AJAX Call to /api/login: Response = %o", response);
                if (response.status === 200) {
                    // We got a 200 Success back, so refresh the page
                    location.reload();
                } else if (response.status === 400) {
                    let r = JSON.parse(response.response);

                    // If there were errors, then add them to the appropriate areas on
                    // the form.  If there weren't errors, make sure those same areas
                    // don't have errors (handles multiple submissions)
                    if (r[""]) {
                        modal.querySelector("#errorForSignInModal").innerHTML = r[""][0];
                    } else {
                        modal.querySelector("#errorForSignInModal").innerHTML = "";
                    }
                    if (r.Email) {
                        modal.querySelector("#errorForEmail").innerHTML = r.Email[0];
                    } else {
                        modal.querySelector("#errorForEmail").innerHTML = "";
                    }
                    if (r.Password) {
                        modal.querySelector("#errorForPassword").innerHTML = r.Password[0];
                    } else {
                        modal.querySelector("#errorForPassword").innerHTML = "";
                    }

                    // Re-activate the form
                    submitButton.innerHTML = submitContent;
                    submitButton.disabled = false;
                }
            });

        e.stopPropagation();
        return false;
    }

If you remember from my discussion on ES6 Promises, I can catch errors and handle responses asynchronously. The catch statement says “there is an error” – right now, I’m just logging the error in the console and not re-activating the form. This isn’t very friendly and I should probably do something about that.

In the then clause, I handle the response. There are two possible responses from the WebAPI – a 200 Success with a few cookies or a 400 Bad Request with some JSON. If the response is Success then the browser already knows about the cookies and all I have to do is reload the page.

If the response is a 400 Bad Request, then I turn the JSON response into an object and look for things I’m interested in, placing the response in prepared locations in the modal dialog. Once that is done, I restore the button content (which removes the spinner) and re-enable the submit button.

Running the Code

If you run this code and click on the Sign In button, the modal will pop up. At this point you can bring up the F12 Developer Tools and hop over to the Console window. Enter some information and see what comes up:

blog-code-0606-1

I’ve added a number of console.debug statements so you can see what is happening. You can also click on any of the objects with a triangle beside them to see the actual contents. Here I’ve entered “admin@” as the username, so I’m expecting a 400 Bad Request, which is exactly what I get.

Problems Still to be Solved

There are two problems to be solved. Firstly, users like to be able to press Enter in the text boxes to submit the form. I’m not capturing key presses within the form so I can’t emulate that functionality. Right now, the only submission possibility is clicking on the button.

Secondly, if there is an error in transmission then there is no indication. The form will continue to spin. This is an easy fix and I’ll do it before I check in the code.

Finally, I don’t do any client-side validation. I leave the validation to the server-side. This means that there are extra round-trips happening when it’s not really necessary. I’ll fix that in the next article.

ASP.NET MVC6 Identity Part 2 – WebAPI

I’ve got this vague thought at the moment. To make my web site truly responsive I need to lose the round trip to the server to load the login page. With that in mind, I’m investigating adding a WebAPI to my application to handle logging in.

The idea is relatively simple. The layout (and hence the home page) will contain the login form. When the user clicks on the login button to submit the form, an AJAX request is sent to the server to validate the response. The server will log the person in and send back whatever is required to actually authenticate the user. The application then stores this (in a cookie or something similar) and refreshes the page. If the user is not authenticated, then immediate feedback can be provided in terms of the validation errors.

Of course, this requires that I provide a WebAPI. I’m going to create a new AccountController class in Areas/Public/Controllers for this purpose. Fortunately, I don’t need any additional packages – the WebAPI stuff is included in MVC6.

My First WebAPI

Let’s start with a pretty basic example – in fact, let’s make it as basic as I can:

using Microsoft.AspNet.Mvc;

namespace Grumpy.Wizards.Areas.Public.Controllers
{
    public class AccountController : Controller
    {
        [Route("api/login")]
        [HttpPost]
        public IActionResult Login([FromBody] LoginViewModel model)
        {
            return new HttpStatusCodeResult(200);
        }
    }
}

This listens on the route /api/login and returns a 200 response to any POST request. I’m not validating the request at this point. I want to get to the point where I can send requests and receive a response back.

if you are confused by the terminology, requests and response codes, you should read a primer – I like the Tuts+ primer.

To test this, I will run the application and then bring up Postman for the testing of the service. Here is a look at the interface configured to send the request:

blog-code-0602-1

I’ve included the actually body as well. Although I don’t check it with the code right now, I’m going to be using that soon so I may as well get the request correct now.

Validating the Model

Of course, this API doesn’t do anything other than respond. To do more, we need to validate the request. The logic is simple enough. If the model is good, then return a 200 response. If the model is bad, return a 400 Bad Request response and a JSON response that provides details on why the model failed validation.

In the ASP.NET code, I use ModelState.IsValid to determine if the model follows the rules I’ve set. I introduced the LoginViewModel and its annotations that implement the validation in my last article. I need a little more code to return those validation errors to the front-end application:

using Grumpy.Wizards.Areas.Public.ViewModels;
using Microsoft.AspNet.Mvc;

namespace Grumpy.Wizards.Areas.Public.Controllers
{
    public class AccountController : Controller
    {
        [Route("api/login")]
        [HttpPost]
        public IActionResult Login([FromBody] LoginViewModel model)
        {
            if (!ModelState.IsValid)
            {
                return new BadRequestObjectResult(ModelState);
            }

            return new HttpStatusCodeResult(200);
        }
    }
}

Let’s try getting through this with a non-valid model. The model uses the ApplicationUser validator that returns success if the provided value is RFC-5321 or our admin user, so I’m going to use a non-compliant username to test the validation:

blog-code-0602-2

If I change back to “admin” as the username or I put in a valid email address, I get the 200 Success response back. This means my data validation is working.

The second part of the process is verification and that’s where ASP

using System.Threading.Tasks;
using Grump.yWizards.Areas.Public.ViewModels;
using Grumpy.Wizards.Database;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Mvc;

namespace Grumpy.Wizards.Areas.Public.Controllers
{
    public class AccountController : Controller
    {
        private UserManager userManager = null;
        private SignInManager signInManager = null;

        public AccountController(UserManager userManager, SignInManager signInManager)
        {
            this.userManager = userManager;
            this.signInManager = signInManager;
        }

Next we want to authenticate the user. This is the same logic that we used the last time we covered Identity:

        /// <summary>
        /// Authenticate the supplied user
        /// </summary>
        /// The Login ViewModel
        /// Result of the login action
        [Route("api/login")]
        [HttpPost]
        [AllowAnonymous]
        public async Task Login([FromBody] LoginViewModel model)
        {
            // Verify that the model is valid according to the validation rules
            // in the model itself.  If it isn't valid, return a 400 Bad Request
            // with some JSON reviewing the errors
            if (!ModelState.IsValid)
            {
                return new BadRequestObjectResult(ModelState);
            }

            // Find the user in our database.  If the user does not exist, then
            // return a 400 Bad Request with a general error.
            var user = await userManager.FindByNameAsync(model.Email);
            if (user == null)
            {
                ModelState.AddModelError("", "Invalid Username or Password");
                return new BadRequestObjectResult(ModelState);
            }
            // If the user has not confirmed his/her email address, then return a
            // 400 Bad Request with a request to activate the account.
            if (!user.EmailConfirmed)
            {
                ModelState.AddModelError("Email", "Please activate your account");
                return new BadRequestObjectResult(ModelState);
            }
            // Authenticate the user with the Sign-In Manager
            var result = await signInManager.PasswordSignInAsync(model.Email, model.Password, false, shouldLockout: false);
            // If the authentication failed, add the same error that we add when
            // we can't find the user (so you can't tell the difference between
            // a bad username and a bad password) and return a 400 Bad Request
            if (!result.Succeeded)
            {
                ModelState.AddModelError("", "Invalid Username or Password");
                return new BadRequestObjectResult(ModelState);
            }

            return new HttpStatusCodeResult(200);
        }

After doing a few tests, I got this:

blog-code-0602-3

Oops – this actually is a security concern. I give away the fact that the user has an account even though the password is wrong. To fix this, I moved the EmailConfirmed below the sign in test. This does bring up an interesting problem – I need to activate the admin account when I’m creating the database. To do this, I adjust the ApplicationDbContext.cs file:

                user = new ApplicationUser {
                    UserName = options.DefaultUsername,
                    EmailConfirmed = true
                };

After I deleted the database and restart the server, I could get all the way through the WebAPI. You need the Postman Interceptor installed to see cookies, but once you do that, you’ll get the following:

blog-code-0602-4

There are actually three cookies generated:

  1. .AspNet.Microsoft.AspNet.Identity.Application
  2. 8lk97XBCwt0 (or more correctly, something completely random)
  3. connect.sid

All I need to do in my web application is to transcribe those cookies that I received to my web session and refresh the page. The ASP.NET application should then recognize me as authenticated as a particular user and display the Signoff link instead of the Signon link.

In my next article, I’m going to use this WebAPI to do exactly that inside of the ASP.NET Layout.

Note that there is nothing different about these techniques from the last time I did Identity. If you want to do Identity the same way I did last time, please feel free – there is no difference.

Web API – Node Style

In the last four articles I’ve been doing a study of what it takes to do a node app. For those who are starting here, I had a list of requirements:

  1. I need to be able to run a small web server
  2. I need to be able to handle templated views with server-side code
  3. I need to be able to do social authentication
  4. I need to be able to use an MVC architecture
  5. I need to be able to provide a Web API
  6. I need to be able to publish a node app to Azure
  7. I need to be able to edit node applications in Visual Studio 2015

Todays article is all about the Web API. If you remember, I am developing a Dungeons and Dragons Character Sheet app as a side project. One of the things you need to do is to list and look up spells for your character. So I need a spell reference. To do this, I’m going to add two routes to my project: /api/spells to list all spells and /api/spells/number to get information on a specific spell. This is, after all, just to demonstrate what is required to do an unauthenticated Web API in Node.

I’ve got some spell data in data/spells.json – it’s just a JSON file with a bunch of fields. I could just as easily push this into a database (like SQL Server or MongoDB), but it’s small enough that I can load it at runtime. The json file itself is an array with objects – one for each spell. Each spell has an _id field that uniquely identifies the object.

Don’t like spells? Well, you can replace “spells” with products, books, companies, or whatever you desire.

To start the API, I’ve introduced an API controller in controllers/api.js:

/*eslint-env node */

"use strict";

var express = require("express"),
    passport = require("passport"),
    path = require("path"),
    config = require("../config.json"),
    spells = require("../data/spells.json");

var router = express.Router(), // eslint-disable-line new-cap
    controller = path.basename(__filename, ".js");

// Set up the Web API Here

module.exports = router;

This is mostly boilerplate code – the same code runs inside the home controller and the account controller. It uses the same routing mechanism, so I can set up my routes just the same way. In fact, the only real difference is that I need to return JSON data rather than HTML.

The /api/spells route is easy, but the /api/spells/number route requires a little explaining. Let’s get the list function out the way first:

function get_all_spells(req, res) {
  res.status(200).json(spells);
}

router.get("/spells", get_all_spells);

There is no view in the Web API world. Instead, Express knows how to send JSON directly. In this case, I set the HTTP Response code to 200 (which means success) and then dump out the spells list that I loaded earlier.

Now, back to that special case. Here is the route:

router.get("/spells/:id", get_one_spell);

Here I’m using a standard notation for a route – whatever route segment comes after the colon will be placed into the req.params object and named the same thing. In this case, I am going to get a req.params.id as a string in my function call:

function get_one_spell(req, res) {
  // Figure out what ID we are actually looking for.  If it is non-numeric,
  // then throw a "Not Found" error back to the user.
  try {
    if (req.params && req.params.id) {
      var id = parseInt(req.params.id);
    } else {
      res.status(404).json({ error: "Spell ID must be numeric" });
      return;
    }
  } catch (e) {
    res.status(404).json({ error: "Spell ID is always a number" });
    return;
  }

  // Find the spell by ID - returns empty array if not found
  var spell = spells.filter(function(o) {
    return o._id === id;
  });
  if (spell === undefined || spell.length === 0) {
    res.status(404).json({ error: "Spell ID Not Found" });
  } else {
    res.status(200).json(spell[0]);
  }
}

Step 1 in this method is to convert the thing we get into a number. However, you should never trust the user. The ID may be non-numeric, missing, a space, special characters – pretty much anything. So the code needs to handle those cases. The try-catch block converts what the user gives me to an integer and returns an error to the user in all other cases.

Now that I have an integer, I can try to find the spell. I’m using Array.filter() here. If node was running ECMAScript 6 then I could use Array.find(), but Node is ECMAScript 5 right now. Array.filter() returns an empty array if it doesn’t find any matches. It could be more than one match, but that is improbable if we properly format the data.

If the returned array is undefined or the length is zero, then I tell the user that the spell is not found, otherwise return success (HTTP Response Code 200) and dump the JSON object.

Right now, this is unauthenticated, so I can just test the API using Postman (available on Chrome) or another Web REST API tool:

blog-code-0523-1

Authentication

The Web API I’ve developed is unauthenticated right now – anyone can consume it. I probably want it authenticated. I can do this two ways – firstly, I can use the req.isAuthenticated() to adjust the output. For instance, I may want to provide everyone with a set of data, but provide a minimal set of data to everyone and extra data to authenticated users. I can do this in the get_all_spells() method like this:

function get_all_spells(req, res) {
  // If the user is not authenticated, only show spells on level
  // 1 or the cantrips.
  if (!req.isAuthenticated()) {
    var spell_list = spells.filter(function(o) {
      return (o.Level === "Cantrip" || o.Level === 1);
    });
    res.status(200).json(spell_list);
    return;
  } else {
    // User is authenticated - show all the spells
    res.status(200).json(spells);
  }
}

Simulating Authentication in Postman

One of the biggest hurdles for me was this. How do I test my authenticated API code? For that matter, what does an Unauthenticated vs. Authenticated Web API look like? To check this out, I took a look at an authentication request via node in Fiddler.

When I browse to my home page the first time, this is what I get:

blog-code-0523-2

The request for / results in a 302 Redirect to /home, which results in a 302 Redirect to /account/login which then returns the view and the view requires a couple of CSS pages. Clicking on Twitter gets me the following:

blog-code-0523-3

I’m using Auth0, so clicking on the Twitter Icon really loads my Auth0 page, which then eventually loads Twitter. Once I’ve done the twitter authentication, I’m back at the /account/external-callback URI before redirecting back to the home. Let’s take a look at that final request for the home page:

blog-code-0523-4

Note the connect.sid cookie – this is what authenticates the session. I need to include that in any authenticated session.

Let’s say I don’t want the use to be able to use the /api/spells/:id unless authenticated. There is no consensus on how to implement authentication in Web APIs:

  1. Return a 302 “Redirect” to the login page
  2. Return a 511 “Network Authentication Required” with a list of authentication providers
  3. Accept an Authorization header with the information and return 301 “Unauthenticated” if it isn’t provided

If a user tries to use the /api/spells/:id route unauthenticated, I’m going to return a 302 Redirect to /account/login. My code now looks like this:

function get_one_spell(req, res) {
  // If the user is not authenticated, tell them to authenticate
  if (!req.isAuthenticated()) {
    res.redirect("/account/login");
    return;
  }

  // Rest of the get_one_spell method
}

When I run this through the process in Postman, I can see the following:

blog-code-0523-5

This isn’t very friendly. When I’m using an API, I don’t want to see HTML that is meant for a human. Let’s instead look at option #2 (the 511 Network Authentication Required version):

function get_login_api() {
  var connections = config.passport.auth0.connections || [],
      r = {}, 
      buildurl = function(provider) {
        var server = config.server.uri || "http://localhost:3000";
        var url = "https://" + config.passport.auth0.domain + "/authorize" +
          "?response_type=code&scope=openid%20profile" +
          "&client_id=" + config.passport.auth0.clientid +
          "&redirect_uri=" + server + "/" + controller + "/external-callback" +
          "&connection=" + provider;
        return url;
      };
      
  for (var i = 0; i < connections.length; i++) {
    r[connections[i].replace("-","_")] = buildurl(connections[i]);
  }
  
  return r;
}

function get_one_spell(req, res) {
  // If the user is not authenticated, tell them to authenticate
  if (!req.isAuthenticated()) {
    res.status(511).json(get_login_api());
    return;
  }
  
  // Rest of the get_one_spell method
}

The get_login_api() converts the configuration we have set up to be an object that we can serialize to JSON. When I run the request in Postman, I get the following:

blog-code-0523-6

I’ve obfuscated the client ID. However, you can see that this returns JSON I can work with. A list of the providers and their respective links is provided. As part of a richer login scheme – for instance, with a Single Page Application (SPA) – I can see this working.

Which one you provide is up to you. I like the 511 response code when you are using social logins with a SPA. I’ve seen the 301 Unauthenticated version implemented a few times as well. You have a lot more flexibility, of course, if your interface is only being used by your application.

As always, my code is up on my GitHub Repository.