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 withBearer
If you wish to use multiple Credentials plugins, then additionally the header:
X-token-type
: must equalJWT
.
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
: theid
claim (converted to a String),displayName
: thefullName
claim,emails
: an array with a single element, representing theemail
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 theClaims
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 yourClaims
type. The claims are used to generate aUserProfile
. 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 theid
anddisplayName
properties of the profile. This claim can be customized by setting thesubject
option to the name of the appropriate claim in yourClaims
.If you require additional claims to appear as properties of the profile, supply the
userProfileDelegate
option. TheUserProfileDelegate
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 theAuthorization
header.no
X-token-type
header: Attempts to extract a valid JWT string from theAuthorization
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)