Authentication Web Services

Server Side Web Frameworks

Functionality provided by server-side web frameworks may include the following:

  • Tying dynamic functionality to specific URLs.

  • Support for the basic HTTP request-response lifecycle.

  • Some kind of application context.

  • Integration with a templating framework.

  • Support for a persistence layer.

Typical Site Architecture

Contexts

Persistence

Persistence layer, used for storing long-term information which may be shared by multiple application servers.

Application

Global to entire application. Good place to remember information like database connections and read-only info like configuration.

Session

Information associated with a user (often tied to user via a cookie). Problematic if only in memory; avoid except for non-critical information.

Request

Context associated with an individual request-response cycle. Can often store this information in some kind of request object.

Client

Information stored on client. Browsers provide cookies, local storage (survives browser restarts) and session storage (does not survive browser restarts).

Express.js Overview

  • Express.js is built on top of nodejs HTTP facilities (which means that you may need to refer to nodejs HTTP docs).

  • Allows dispatching HTTP requests based on a modular routing framework.

  • Allows inserting middleware into the application's request-response cycle.

  • Allows plugging in multiple template engines to generate dynamic content.

Routing

  • A router allows specifying that a handler function (single or multiple) be run when the URL for a web request matches a particular route and method.

  • Matching route can be a fixed string or a pattern or a regular expression.

  • Routes set up using

        //invoked for all requests
        app.use(HANDLER);
    
        //invoked for all requests with URL matching PATTERN
        app.use(PATTERN, HANDLER1,...);
    
        //invoked for request having METHOD (get, post, etc)
        //with URL matching PATTERN
        app.METHOD(PATTERN, HANDLER1, ...)
    
  • Routes are tried in order and first matching route chosen. Hence order of routes matter.

Handler Functions

Express refers to handler functions as middleware as they sit in the "middle" of a request-response cycle.

  • Handler function takes a req and res argument to access the incoming HTTP request and outgoing HTTP response as objects.

  • Optionally, handler functions can also take a next argument; calling next() allows chaining to the next set of handlers for a route which matches the request URL.

  • If method and pattern matches a particular handler which does not call next(), then subsequent matching handler will never be called.

  • Special error hander which must be declared with four arguments err, req, res and next.

Playing with Express

User Web Services Specs

  • Allow user login, logout and registration.

  • Allow CRUD functionality for user information.

  • Distinguish between admin and non-admin users.

  • Authentication via loginId and password, with cookies used to maintain login sessions.

Authorization

  • Associate an optional roles property with each user. If "admin" \(\in\) roles, then the user is an admin user, else the user is a non-admin user.

  • A user is logged in via a session cookie which identifies the user.

  • Creating a non-admin user does not require authorization.

  • If a non-admin user or user which is not logged in creates a user, then the successfully created user is logged in.

  • If an admin user creates a user, then the admin user stays logged in.

  • An admin user can search for users, create admin users as well as update/delete other users.

  • A non-admin user can only update/delete itself. It cannot create an admin user nor can it search for users.

User Web Services

Discover Services

GET /auth : Return services accessible to currently logged in user (or anonymous user, if not logged in).

Register User

POST /auth : Create new user with params given in request body. Returns user object in response body; also sets location header to it.

Login User

POST /auth/login : Login using {loginId, password} in request body. Returns user object in response body.

Get User Details

GET /auth/userId : Returns user object in response body.

Update User

PATCH /auth/userId : Updates user object with update specified by request body. Returns updated user object in response body.

Delete User

DELETE /auth/userId : Removes user specified by userId.

Logout User

POST /auth/userId/logout : Logout currently logged in user userId.

Query Users

GET /auth/query : Search users by optional query parameters; paginate results using index and count query parameters. Returns list of user objects in response body with links possibly containing next and prev links.

Validation using JSON Schema

JSON Schema is used for validation.

  • Any JSON data must be well-formed (meet JSON syntax restrictions), but we need further validity constraints. For example, both [ "hello", "world" ] and [ 1, 2 ] are well-formed JSON, but only the latter can be valid as a 2D-point.

  • A JSON schema is a meta JSON document describing the validity constraints for JSON data.

  • A key property in a JSON schema is type, which can be one of string, number, integer, boolean, null, object or array.

  • Depending on the value of type, there can be other properties in a JSON schema: for example:

    • type string can have additional properties like minLength, maxLength, pattern, contentEncoding, contentMediaType, contentSchema.

    • type number can have additional properties like minimum, exclusiveMinimum, maximum, exclusiveMaximum, multipleOf.

    • type object can have additional properties like properties, required, etc.

    • type array can have additonal properties like contains, prefixItems, minContains.

PHP's Opis JSON Schema is one of the best documents I've seen describing JSON schema.

Example JSON Schema

Using JavaScript, rather than JSON syntax:

// a schema for a search query containing count and index
// paging parameters + possible additional filter parameters
const querySchema = {
  type: 'object',
  properties: {
    count: {
      type: 'integer',
      minimum: 0,
    },
    index: {
      type: 'integer',
      minimum: 0,
    },
    additionalProperties: true,
  },
};

Evaluation of JSON Schema

  • JSON schema can be be used as a contract between an API producer and API consumer.

  • Widely used.

  • JSON schema is independent of implementation language; JSON schema libraries exist for most popular programming languages.

  • Since a JSON document (the schema) is used to constrain another JSON document (the data), sometimes it is difficult to distinguish between properties of the schema and properties of the data.

  • There are several meta-levels: the JSON schema itself is a meta-document about the data, and the schema itself can contain meta-properties about the schema itself like $schema specifying the version of JSON schema and $id specifying its id.

  • Unfortunately, the standard does not specify exactly how validation errors should be handled.

  • JSON schema useful for validating API requests. However, similar validation often needs to be applied to user input. So DRY can be violated if sufficient care is not taken.

JS Validator ajv

Ajv is a popular JavaScript JSON schema validator:

  • Compiles schema to JavaScript code.

  • Supports latest versions of the JSON Schema standard.

  • Unfortunately, it uses a mutable API.

  • Default error messages can be confusing.

User Web Services Implementation

Builds on earlier User Authentication code. All code in auth-ws project:

src/lib/response-envelopes.ts

Define user types.

log1.LOG and query.LOG

Annotated logs of command line interaction using curl as an HTTP client.

src/lib/user.ts

Define user types.

src/lib/auth-ws.ts

Implementation of web services.

src/lib/sessions.ts

In-memory sessions for tracking logins. Could have also used an external library like express-session.

src/lib/user-services.ts

User validation using JSON schema.

index.mjs and src/lib/main.ts

Command-line handling.

src/test/auth-ws.ts

Tests using supertest.