Getting Started With HTTP Middleware in Kitura

Middleware is a popular way to to handle incoming server-side requests and outgoing responses. In this tutorial, you’ll learn how to add middleware to a REST API that’s built in Swift and uses the Kitura framework. You’ll learn how to add CORS (Cross-Origin Resource Sharing) policies, custom logic and authentication to the routes of an app that knows the meaning of life. By David Okun.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

Authentication Middleware

Whenever you’re browsing your favorite social media website, it would make sense that you could only see your personal content if you’re logged in, right? Why would you even want to waste time performing an operation in a route handler if the request is unauthenticated? You’re going to implement a route handler that uses Codable Routing in Kitura with type-safe middleware to ensure that the request is authenticated.

Note: Both Server-Side Swift books, Kitura and Vapor, go into the details of HTTP authentication. HTTP basic is often used as a means of demonstration authentication on a server, and it is generally not recommended for production.

First, open RazeRoutes.swift and register your route in your initalizeRazeRoutes() function:

app.router.get("/auth", handler: authHandler)

Next, scroll to the bottom of this file and add the following handler:

func authHandler(profile: RazeAuth, completion: (RazeAuth?, RequestError?) -> Void) {
  completion(profile, nil)
}

Your server should not compile properly at this point, because you have not yet defined RazeAuth. Open Middleware.swift and import the following module at the top of your file underneath your import of KituraCORS:

import CredentialsHTTP

Next, scroll to the bottom of this file and add the following code to define your middleware instance:

// 1
public struct RazeAuth: TypeSafeHTTPBasic {
  // 2
  public var id: String
  // 3
  static let database = ["David": "12345", "Tim": "54321"]
  
  // 4
  public static func verifyPassword(username: String, 
    				    password: String,
    				    callback: @escaping (RazeAuth?) -> Void) {

  }
}

Take a moment to examine what you’ve added:

  1. The main requirement of your middleware is that it must conform to the TypeSafeHTTPBasic protocol.
  2. The first required implementation in the TypeSafeBasicHTTP protocol is the id property, to be able to identify an authenticated user.
  3. In this example, you are setting up a very small and simple database of usernames and passwords — this is here to demonstrate that you could use any existing database module to query by username!
  4. The other required implementation for the TypeSafeBasicHTTP protocol is the verifyPassword method. After you have confirmed that the username and password match expected values, you can create a RazeAuth object with the proper username, and pass it on in the callback. Since you registered the route with a non-optional RazeAuth object, this means that calling callback() with nil will instead send a 401 Unauthorized response to the client.

Next, add this code inside verifyPassword() to verify if the given username and password are valid according to your super secure database of usernames and passwords:

guard let storedPassword = database[username],
      password == storedPassword else {
  return callback(nil)
}

return callback(RazeAuth(id: username))

Lastly, go to RazeRoutes.swift and put a breakpoint inside your /auth route handler. Build and run your server, and ensure your server is listening on port 8080. Open Terminal, and run the three following commands:

curl -u "Ray":"12345" localhost:8080/auth
curl -u "David":"12345" localhost:8080/auth
curl -u "Tim":"54321" localhost:8080/auth

For the commands that are properly authenticated (David and Tim’s), you should trigger your breakpoint, and your server should respond with the username that you sent over! Now, your server only has to do the work its authenticated to do!

Where to Go From Here?

Middleware opens up a large realm of possibilities for developers to enhance routes that might already exist on a server. This tutorial showed you how easy it is to both implement existing middleware libraries, and how you can roll your own library to add custom behavior to your server, like the koba library written by Caleb Kinney.

Both our Server Side Swift with Kitura and Server Side Swift with Vapor books have plenty of information about implementing middleware and authentication, and you can work on them in a real-life scenario!

If you want to learn more about how Kitura handles HTTP routing and works in general, read this beginner’s tutorial about it.

Please leave a comment below if you know about any other middleware libraries or if you have any questions!

Contributors

Cesare Rocchi

Tech Editor

Adriana Kutenko

Illustrator

Shai Mishali

Final Pass Editor

Tim Condon

Team Lead

Over 300 content creators. Join our team.