CredentialsJWT

public class CredentialsJWT<C> : CredentialsPluginProtocol, CredentialsTokenTTL where C : Claims

A plugin for Kitura-Credentials supporting authentication using JSON Web Tokens.

This plugin requires that the following HTTP headers are present on a request:

  • Authorization: the JWT string, optionally prefixed with Bearer

If you wish to use multiple Credentials plugins, then additionally the header:

  • X-token-type: must equal JWT.

The Swift-JWT library is used to decode JWT strings. To successfully decode it, you must specify the Claims that will be present in the JWT. One claim (by default, sub) will be used to represent the identity of the bearer. You can choose a different claim by supplying the subject option when creating an instance of CredentialsJWT, and you can further customize the resulting UserProfile by defining a UserProfileDelegate.

 Usage Example

To use CredentialsJWT using the default options:

import Credentials
import CredentialsJWT
import SwiftJWT

// Defines the claims that must be present in a JWT.
struct MyClaims: Claims {
    let sub: String
}

// Defines the method used to verify the signature of a JWT.
let jwtVerifier = .hs256(key: "<PrivateKey>".data(using: .utf8)!)

// Create a CredentialsJWT plugin with default options.
let jwtCredentials = CredentialsJWT<MyClaims>(verifier: jwtVerifier)

let authenticationMiddleware = Credentials()
authenticationMiddleware.register(plugin: jwtCredentials)
router.get("/myProtectedRoute", middleware: authenticationMiddleware)

Following successful authentication, the UserProfile will be minimally populated with the two required fields - id and displayName - both with the value of the JWT’s sub claim. The provider will be set to JWT.

Usage Example - custom claims

To customize the name of the identity claim, and further populate the UserProfile fields, specify the subject and userProfileDelegate options as follows:

import Credentials
import CredentialsJWT
import SwiftJWT

// Defines the claims that must be present in a JWT.
struct MyClaims: Claims {
    let id: Int
    let fullName: String
    let email: String
}

struct MyDelegate: UserProfileDelegate {
    func update(userProfile: UserProfile, from dictionary: [String:Any]) {
        // `userProfile.id` already contains `id`
        userProfile.displayName = dictionary["fullName"]! as! String
        let email = UserProfile.UserProfileEmail(value: dictionary["email"]! as! String, type: "home")
        userProfile.emails = [email]
    }
}

// Defines the method used to verify the signature of a JWT.
let jwtVerifier = .hs256(key: "<PrivateKey>".data(using: .utf8)!)

// Create a CredentialsJWT plugin with default options.
let jwtCredentials = CredentialsJWT<MyClaims>(verifier: jwtVerifier, options: [CredentialsJWTOptions.subject: "id", CredentialsJWTOptions.userProfileDelegate: MyDelegate])

let authenticationMiddleware = Credentials()
authenticationMiddleware.register(plugin: jwtCredentials)
router.get("/myProtectedRoute", middleware: authenticationMiddleware)

Following successful authentication, the UserProfile will be populated as follows:

  • id: the id claim (converted to a String),
  • displayName: the fullName claim,
  • emails: an array with a single element, representing the email claim.
  • The name of the plugin: JWT.

    Declaration

    Swift

    public var name: String { get }
  • An indication as to whether the plugin is redirecting or not. This plugin is not redirecting.

    Declaration

    Swift

    public var redirecting: Bool { get }
  • The time in seconds since the user profile was generated that the access token will be considered valid and remain in the usersCache.

    By default, this value is nil, which means that tokens will be cached indefinitely.

    Declaration

    Swift

    public let tokenTimeToLive: TimeInterval?
  • A delegate for UserProfile manipulation. Use this to further populate the profile using any fields from the Claims that you have defined.

    This field can be set by passing the userProfileDelegate option during initialization.

    Declaration

    Swift

    public var userProfileDelegate: UserProfileDelegate? { get }
  • Initialize a CredentialsJWT instance. Upon first receipt, a JWT will be verified to ensure the signature is valid, and that the JWT’s claims can be decoded into an instance of your Claims type. The claims are used to generate a UserProfile. The profile will be cached against the token, so that future receipts of the same token are more efficient. The time a token is cached for can be configured.

    One claim (by default, sub) will be considered the ‘identity’ of the bearer, and will be used to populate the id and displayName properties of the profile. This claim can be customized by setting the subject option to the name of the appropriate claim in your Claims.

    If you require additional claims to appear as properties of the profile, supply the userProfileDelegate option. The UserProfileDelegate will be given a dictionary containing the claims of the JWT from which it can populate the profile.

    Declaration

    Swift

    public init(verifier: JWTVerifier, options: [String : Any]? = nil, tokenTimeToLive: TimeInterval? = nil)

    Parameters

    verifier

    Determines the key and algorithm used to verify the received JWT.

    options

    A dictionary of plugin specific options. The keys are defined in CredentialsJWTOptions.

    tokenTimeToLive

    How long the token should remain cached (in seconds). The default is nil, which means the token will be cached indefinitely.

  • User profile cache.

    Declaration

    Swift

    public var usersCache: NSCache<NSString, BaseCacheElement>?
  • Authenticate incoming request using a JWT.

    Behaviour depends on the presence (and value) of the X-token-type header:

    • X-token-type: JWT: Expects a valid JWT string in the Authorization header.
    • no X-token-type header: Attempts to extract a valid JWT string from the Authorization header, but will defer to other plugins (rather than failing authentication).

    Declaration

    Swift

    public func authenticate(request: RouterRequest, response: RouterResponse,
                            options: [String:Any], onSuccess: @escaping (UserProfile) -> Void,
                            onFailure: @escaping (HTTPStatusCode?, [String:String]?) -> Void,
                            onPass: @escaping (HTTPStatusCode?, [String:String]?) -> Void,
                            inProgress: @escaping () -> Void)

    Parameters

    request

    The RouterRequest object used to get information about the request.

    response

    The RouterResponse object used to respond to the request.

    options

    The dictionary of plugin specific options.

    onSuccess

    The closure to invoke in the case of successful authentication.

    onFailure

    The closure to invoke in the case of an authentication failure.

    onPass

    The closure to invoke when the plugin doesn’t recognize the authentication token in the request.

    inProgress

    The closure to invoke to cause a redirect to the login page in the case of redirecting authentication.

  • Declaration

    Swift

    public func generateNewProfile(token: String, options: [String : Any], completion: @escaping (CredentialsTokenTTLResult) -> Void)