Kitura

APIDoc Build Status - Master macOS Linux Apache 2 Slack Status

Kitura-Session

A pluggable framework for managing user sessions in a Swift server using Kitura.

Swift version

The latest version of Kitura-Session requires Swift 4.0 or later. You can download this version of the Swift binaries by following this link. Compatibility with other Swift versions is not guaranteed.

Usage

Add dependencies

Add the Kitura-Session package to the dependencies within your application’s Package.swift file. Substitute "x.x.x" with the latest Kitura-Session release.

.package(url: "https://github.com/Kitura/Kitura-Session.git", from: "x.x.x")

Add KituraSession to your target’s dependencies:

.target(name: "example", dependencies: ["KituraSession"]),

Import package

import KituraSession

Raw routing Session

Getting Started

In order to use the Session middleware on a Raw route, an instance of Session has to be created:

public init(secret: String, cookie: [CookieParameter]?=nil, store: Store?=nil)

Where:

  • secret is a String to be used for session encoding. It should be a large unguessable string, a minimum of 14 characters long.
  • cookie is a list of options for session’s cookies. The options are (as specified in the CookieParameter enumeration):
    • name - cookie’s name, defaults to “kitura-session-id”.
    • path - cookie’s path attribute, this defines the path for which this cookie should be supplied. Defaults to “/” which means allow any path.
    • secure - cookie’s secure attribute, this indicates whether the cookie should be provided only over secure (https) connections. Defaults to false.
    • maxAge - cookie’s maxAge attribute, that is, the maximum age (in seconds) from the time of issue that the cookie should be kept for. Defaults to -1.0, i.e., no expiration.
  • store is an instance of a plugin for a session backing store that implements the Store protocol. If not set, InMemoryStore is used.

The cookie and store parameters are optional.

The secret parameter is used to secure the session ID and ensure that the session ID cannot be guessed. Secret is used to derive a pair of encryption and signature keys via PBKDF2 and a fixed IV to make the session ID cookie be authenticated and encrypted. Secret isn’t used directly to encrypt or compute the MAC of the cookie.

Example

In this example, an instance of RedisStore is created that will be used to persist session data (see KituraSessionRedis for more information). An instance of Session is then created, specifying redisStore as the session store. Finally, the session instance is registered as middleware on the desired path.

import Kitura
import KituraSession
import KituraSessionRedis

let redisStore = RedisStore(redisHost: host, redisPort: port)
let session = Session(secret: "Some secret", store: redisStore)
router.all(middleware: session)

Storing Any in a session

Within your Kitura routes, you can store Any type inside the request.session for a given key. This can then be retrieved as an Any and cast to the required type:

router.post("/session") {request, response, next in
    request.session?["key"] = "value"
    next()
}
router.get("/session") {request, response, next in
    let value = request.session?["key"] as? String
    next()
}

This Any type must be JSON serializable. Otherwise, the session will fail when it attempts to save the session.

Storing Codable in a Session

Available from Swift 4.1 or later

Within your Kitura routes, you can also store Codable objects inside the request.session for a given key. This can then be retrieved as the declared type:

public struct User: Codable {
    let name: String
}
router.post("/user") { request, response, next in
    let user = User(name: "Kitura")
    request.session?["User"] = user
    next()
}
router.get("/user") { request, response, next in
    let user: User? = request.session?["Kitura"]
    next()
}

TypeSafeSession Example

To use sessions on a Codable route, declare a type that conforms to the TypeSafeSession protocol:

// Defines the session instance data
final class MySession: TypeSafeSession {
    let sessionId: String                       // Requirement: every session must have an ID
    var books: [Book]                           // User-defined type, where Book conforms to Codable

    init(sessionId: String) {                   // Requirement: must be able to create a new (empty)
        self.sessionId = sessionId              // session containing just an ID. Assign a default or
        books = []                              // empty value for any non-optional properties.
    }
}

// Defines the configuration of the user's type: how the cookie is constructed, and how the session is persisted.
extension MySession {
    static let sessionCookie: SessionCookie = SessionCookie(name: "MySession", secret: "Top Secret")
    static var store: Store?
}

The MySession type can then be included in the application’s Codable route handlers. For example:

struct Book: Codable {
    let title: String
    let author: String
}

router.get("/cart") { (session: MySession, respondWith: ([Book]?, RequestError?) -> Void) in
    respondWith(session.books, nil)
}

router.post("/cart") { (session: MySession, book: Book, respondWith: (Book?, RequestError) -> Void) in
    var session = session       // Required when mutating a Struct
    session.books.append(book)
    session.save()
    respondWith(book, nil)
}

Plugins

API Documentation

For more information visit our API reference.

Community

We love to talk server-side Swift, and Kitura. Join our Slack to meet the team!

License

This library is licensed under Apache 2.0. The full license text is available in LICENSE.