SwiftJWT
Authentication Library
SwiftJWT
Overview
SwiftJWT is a JSON Web Token (JWT) implementation library for Swift developed by IBM. It enables creation, signing, and verification of JWTs on iOS, macOS, and Linux environments, supporting various signing algorithms. It's suitable for building lightweight, high-performance, and secure token authentication systems.
Details
SwiftJWT provides a complete implementation of JWTs compliant with RFC 7519. It encompasses all authentication-related functionalities from JWT generation to token verification, and is particularly optimized for use in server-side Swift applications.
Key Components
- JWT Structure: Representation of JWT containing headers and claims
- Claims: Standard claims defined in RFC 7519 (ClaimsStandardJWT)
- JWTSigner: Structure that manages signing algorithms
- JWTVerifier: Token verification functionality
Supported Signing Algorithms
- RSA: RS256, RS384, RS512
- ECDSA: ES256, ES384, ES512
- HMAC: HS256, HS384, HS512
- None: Unsigned tokens (for development)
Security Features
- Tamper detection through digital signatures
- Time limitation via expiration (exp) claims
- Verification of issuer (iss) and audience (aud)
- Custom claims support
Pros and Cons
Pros
- Pure Swift Implementation: High performance with native Swift code
- Cross-Platform: Works on iOS, macOS, and Linux
- Standards Compliant: Full RFC 7519 compliance
- Multiple Algorithms: Support for various signing algorithms
- Type Safety: Safe implementation leveraging Swift's type system
- IBM Support: Maintained by the Kitura team
Cons
- No JWE Support: Only supports JWS (signing), no encryption (JWE)
- Plain Text Data: Claims are only Base64 encoded, not encrypted
- Swift Only: Cannot be used with languages other than Swift
- Learning Curve: Requires understanding of JWT concepts
Reference Links
- SwiftJWT GitHub - Official repository
- Kitura JWT Documentation - JWT authentication guide
- Swift Package Index - Package information
Code Examples
Package Installation
// Package.swift
dependencies: [
.package(url: "https://github.com/Kitura/Swift-JWT.git", from: "3.6.200")
],
targets: [
.target(
name: "YourTarget",
dependencies: ["SwiftJWT"]
)
]
Basic Claims Definition
import SwiftJWT
// Custom claims structure
struct MyClaims: Claims {
let sub: String // subject (user ID)
let exp: Date // expiration
let iat: Date // issued at
let iss: String // issuer
let name: String // custom claim
let admin: Bool // custom claim
}
JWT Generation and Signing
import SwiftJWT
import Foundation
// Secret for HS algorithms
let secret = "your-secret-key".data(using: .utf8)!
let signer = JWTSigner.hs256(key: secret)
// Create claims
let claims = MyClaims(
sub: "user123",
exp: Date(timeIntervalSinceNow: 3600), // Expires in 1 hour
iat: Date(),
iss: "myapp.com",
name: "John Doe",
admin: false
)
// Create JWT
let jwt = JWT(claims: claims)
// Generate signed token
do {
let signedJWT = try jwt.sign(using: signer)
print("Signed JWT: \(signedJWT)")
} catch {
print("Error signing JWT: \(error)")
}
JWT Verification
// Decode and verify JWT string
let jwtString = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
do {
// Decode JWT
let jwt = try JWT<MyClaims>(jwtString: jwtString)
// Verify signature
let verifier = JWTVerifier.hs256(key: secret)
let isValid = jwt.verify(using: verifier)
if isValid {
print("JWT is valid")
print("User: \(jwt.claims.name)")
print("Admin: \(jwt.claims.admin)")
// Check expiration
if jwt.claims.exp > Date() {
print("Token is not expired")
} else {
print("Token has expired")
}
} else {
print("JWT signature is invalid")
}
} catch {
print("Error verifying JWT: \(error)")
}
RSA Signing Algorithm Example
import SwiftJWT
// RSA private key (PKCS#8 format)
let privateKeyPEM = """
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC7...
-----END PRIVATE KEY-----
"""
// RSA public key
let publicKeyPEM = """
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu5...
-----END PUBLIC KEY-----
"""
// Create RSA256 signer and verifier
let signer = JWTSigner.rs256(privateKey: privateKeyPEM.data(using: .utf8)!)
let verifier = JWTVerifier.rs256(publicKey: publicKeyPEM.data(using: .utf8)!)
// Create and sign JWT
let jwt = JWT(claims: claims)
let signedToken = try jwt.sign(using: signer)
// Verify
let decodedJWT = try JWT<MyClaims>(jwtString: signedToken)
let isValid = decodedJWT.verify(using: verifier)
Standard Claims Example
// Standard JWT claims
struct StandardClaims: Claims {
let iss: String? // issuer
let sub: String? // subject
let aud: [String]? // audience
let exp: Date? // expiration
let nbf: Date? // not before
let iat: Date? // issued at
let jti: String? // JWT ID
}
let standardClaims = StandardClaims(
iss: "myapp.com",
sub: "user123",
aud: ["api.myapp.com"],
exp: Date(timeIntervalSinceNow: 3600),
nbf: Date(),
iat: Date(),
jti: UUID().uuidString
)
Error Handling
// Comprehensive error handling
func processJWT(_ tokenString: String) {
do {
let jwt = try JWT<MyClaims>(jwtString: tokenString)
let verifier = JWTVerifier.hs256(key: secret)
guard jwt.verify(using: verifier) else {
print("Invalid signature")
return
}
guard jwt.claims.exp > Date() else {
print("Token expired")
return
}
print("Valid token for user: \(jwt.claims.name)")
} catch JWTError.invalidJWTString {
print("Invalid JWT format")
} catch JWTError.failedVerification {
print("Signature verification failed")
} catch {
print("Unexpected error: \(error)")
}
}