Skip to content

Commit 7455c9d

Browse files
committed
[Encoding] Introduce a builder pattern
1 parent 2b5bc6c commit 7455c9d

File tree

3 files changed

+149
-0
lines changed

3 files changed

+149
-0
lines changed

JWT/JWT.swift

+76
Original file line numberDiff line numberDiff line change
@@ -76,3 +76,79 @@ public func encode(payload:Payload, algorithm:Algorithm) -> String {
7676
let signature = algorithm.sign(signingInput)
7777
return "\(signingInput).\(signature)"
7878
}
79+
80+
public class PayloadBuilder {
81+
var payload = Payload()
82+
83+
public var issuer:String? {
84+
get {
85+
return payload["iss"] as? String
86+
}
87+
set {
88+
payload["iss"] = newValue
89+
}
90+
}
91+
92+
public var audience:String? {
93+
get {
94+
return payload["aud"] as? String
95+
}
96+
set {
97+
payload["aud"] = newValue
98+
}
99+
}
100+
101+
public var expiration:NSDate? {
102+
get {
103+
if let expiration = payload["exp"] as? NSTimeInterval {
104+
return NSDate(timeIntervalSince1970: expiration)
105+
}
106+
107+
return nil
108+
}
109+
set {
110+
payload["exp"] = newValue?.timeIntervalSince1970
111+
}
112+
}
113+
114+
public var notBefore:NSDate? {
115+
get {
116+
if let notBefore = payload["nbf"] as? NSTimeInterval {
117+
return NSDate(timeIntervalSince1970: notBefore)
118+
}
119+
120+
return nil
121+
}
122+
set {
123+
payload["nbf"] = newValue?.timeIntervalSince1970
124+
}
125+
}
126+
127+
public var issuedAt:NSDate? {
128+
get {
129+
if let issuedAt = payload["iat"] as? NSTimeInterval {
130+
return NSDate(timeIntervalSince1970: issuedAt)
131+
}
132+
133+
return nil
134+
}
135+
set {
136+
payload["iat"] = newValue?.timeIntervalSince1970
137+
}
138+
}
139+
140+
public subscript(key: String) -> AnyObject? {
141+
get {
142+
return payload[key]
143+
}
144+
set {
145+
payload[key] = newValue
146+
}
147+
}
148+
}
149+
150+
public func encode(algorithm:Algorithm, closure:(PayloadBuilder -> ())) -> String {
151+
let builder = PayloadBuilder()
152+
closure(builder)
153+
return encode(builder.payload, algorithm)
154+
}

JWTTests/JWTTests.swift

+63
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,69 @@ class JWTEncodeTests : XCTestCase {
88
let fixture = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiS3lsZSJ9.zxm7xcp1eZtZhp4t-nlw09ATQnnFKIiSN83uG8u6cAg"
99
XCTAssertEqual(jwt, fixture)
1010
}
11+
12+
func testEncodingWithBuilder() {
13+
let algorithm = Algorithm.HS256("secret")
14+
let jwt = JWT.encode(algorithm) { builder in
15+
builder.issuer = "fuller.li"
16+
}
17+
18+
assertSuccess(JWT.decode(jwt, algorithm)) { payload in
19+
XCTAssertEqual(payload as NSDictionary, ["iss": "fuller.li"])
20+
}
21+
}
22+
}
23+
24+
class JWTPayloadBuilder : XCTestCase {
25+
func testIssuer() {
26+
JWT.encode(.None) { builder in
27+
builder.issuer = "fuller.li"
28+
XCTAssertEqual(builder.issuer!, "fuller.li")
29+
XCTAssertEqual(builder["iss"] as String, "fuller.li")
30+
}
31+
}
32+
33+
func testAudience() {
34+
JWT.encode(.None) { builder in
35+
builder.audience = "cocoapods"
36+
XCTAssertEqual(builder.audience!, "cocoapods")
37+
XCTAssertEqual(builder["aud"] as String, "cocoapods")
38+
}
39+
}
40+
41+
func testExpiration() {
42+
JWT.encode(.None) { builder in
43+
let date = NSDate(timeIntervalSince1970: NSDate().timeIntervalSince1970)
44+
builder.expiration = date
45+
XCTAssertEqual(builder.expiration!, date)
46+
XCTAssertEqual(builder["exp"] as NSTimeInterval, date.timeIntervalSince1970)
47+
}
48+
}
49+
50+
func testNotBefore() {
51+
JWT.encode(.None) { builder in
52+
let date = NSDate(timeIntervalSince1970: NSDate().timeIntervalSince1970)
53+
builder.notBefore = date
54+
XCTAssertEqual(builder.notBefore!, date)
55+
XCTAssertEqual(builder["nbf"] as NSTimeInterval, date.timeIntervalSince1970)
56+
}
57+
}
58+
59+
func testIssuedAt() {
60+
JWT.encode(.None) { builder in
61+
let date = NSDate(timeIntervalSince1970: NSDate().timeIntervalSince1970)
62+
builder.issuedAt = date
63+
XCTAssertEqual(builder.issuedAt!, date)
64+
XCTAssertEqual(builder["iat"] as NSTimeInterval, date.timeIntervalSince1970)
65+
}
66+
}
67+
68+
func testCustomAttributes() {
69+
JWT.encode(.None) { builder in
70+
builder["user"] = "kyle"
71+
XCTAssertEqual(builder["user"] as String, "kyle")
72+
}
73+
}
1174
}
1275

1376
class JWTDecodeTests : XCTestCase {

README.md

+10
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,16 @@ import JWT
2424
JWT.encode(["my": "payload"], .HS256("secret"))
2525
```
2626

27+
#### Building a JWT with the builder pattern
28+
29+
```swift
30+
JWT.encode(.HS256("secret")) { builder in
31+
builder.issuer = "fuller.li"
32+
builder.issuedAt = NSDate()
33+
builder["custom"] = "Hi"
34+
}
35+
```
36+
2737
### Decoding a JWT
2838

2939
When decoding a JWT, you must supply one or more algorithms and keys.

0 commit comments

Comments
 (0)