-
Notifications
You must be signed in to change notification settings - Fork 43
Expand file tree
/
Copy pathIterableJwtGenerator.swift
More file actions
112 lines (91 loc) · 3.46 KB
/
Copy pathIterableJwtGenerator.swift
File metadata and controls
112 lines (91 loc) · 3.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//
// IterableJwtGenerator.swift
// ReactNativeSdkExample
//
// Utility class to generate JWTs for use with the Iterable API
//
import CryptoKit
import Foundation
@objcMembers public final class IterableJwtGenerator: NSObject {
/// Base64 URL encode without padding (URL-safe base64 encoding for JWT)
private static func urlEncodedBase64(_ data: Data) -> String {
let base64 = data.base64EncodedString()
return
base64
.replacingOccurrences(of: "+", with: "-")
.replacingOccurrences(of: "/", with: "_")
.replacingOccurrences(of: "=", with: "")
}
public static func generateJwtForEmail(secret: String, iat: Int, exp: Int, email: String)
-> String
{
struct Header: Encodable {
let alg = "HS256"
let typ = "JWT"
}
struct Payload: Encodable {
var email = ""
var iat = Int(Date().timeIntervalSince1970)
var exp = Int(Date().timeIntervalSince1970) + 60
}
let headerJsonData = try! JSONEncoder().encode(Header())
let headerBase64 = urlEncodedBase64(headerJsonData)
let payloadJsonData = try! JSONEncoder().encode(Payload(email: email, iat: iat, exp: exp))
let payloadBase64 = urlEncodedBase64(payloadJsonData)
let toSign = Data((headerBase64 + "." + payloadBase64).utf8)
if #available(iOS 13.0, *) {
let privateKey = SymmetricKey(data: Data(secret.utf8))
let signature = HMAC<SHA256>.authenticationCode(for: toSign, using: privateKey)
let signatureBase64 = urlEncodedBase64(Data(signature))
let token = [headerBase64, payloadBase64, signatureBase64].joined(separator: ".")
return token
}
return ""
}
public static func generateJwtForUserId(secret: String, iat: Int, exp: Int, userId: String)
-> String
{
struct Header: Encodable {
let alg = "HS256"
let typ = "JWT"
}
struct Payload: Encodable {
var userId = ""
var iat = Int(Date().timeIntervalSince1970)
var exp = Int(Date().timeIntervalSince1970) + 60
}
let headerJsonData = try! JSONEncoder().encode(Header())
let headerBase64 = urlEncodedBase64(headerJsonData)
let payloadJsonData = try! JSONEncoder().encode(Payload(userId: userId, iat: iat, exp: exp))
let payloadBase64 = urlEncodedBase64(payloadJsonData)
let toSign = Data((headerBase64 + "." + payloadBase64).utf8)
if #available(iOS 13.0, *) {
let privateKey = SymmetricKey(data: Data(secret.utf8))
let signature = HMAC<SHA256>.authenticationCode(for: toSign, using: privateKey)
let signatureBase64 = urlEncodedBase64(Data(signature))
let token = [headerBase64, payloadBase64, signatureBase64].joined(separator: ".")
return token
}
return ""
}
public static func generateToken(
secret: String, durationMs: Int64, email: String?, userId: String?
) throws -> String {
// Convert durationMs from milliseconds to seconds
let durationSeconds = Double(durationMs) / 1000.0
let currentTime = Date().timeIntervalSince1970
if userId != nil {
return generateJwtForUserId(
secret: secret, iat: Int(currentTime),
exp: Int(currentTime + durationSeconds), userId: userId!)
} else if email != nil {
return generateJwtForEmail(
secret: secret, iat: Int(currentTime),
exp: Int(currentTime + durationSeconds), email: email!)
} else {
throw NSError(
domain: "JWTGenerator", code: 6,
userInfo: [NSLocalizedDescriptionKey: "No email or userId provided"])
}
}
}