-
Notifications
You must be signed in to change notification settings - Fork 221
/
IDTokenValidator.swift
81 lines (73 loc) · 3.11 KB
/
IDTokenValidator.swift
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
#if WEB_AUTH_PLATFORM
import Foundation
import JWTDecode
protocol JWTValidator {
func validate(_ jwt: JWT) -> Auth0Error?
}
protocol JWTAsyncValidator {
func validate(_ jwt: JWT, callback: @escaping (Auth0Error?) -> Void)
}
struct IDTokenValidator: JWTAsyncValidator {
private let signatureValidator: JWTAsyncValidator
private let claimsValidator: JWTValidator
private let context: IDTokenValidatorContext
init(signatureValidator: JWTAsyncValidator,
claimsValidator: JWTValidator,
context: IDTokenValidatorContext) {
self.signatureValidator = signatureValidator
self.claimsValidator = claimsValidator
self.context = context
}
func validate(_ jwt: JWT, callback: @escaping (Auth0Error?) -> Void) {
DispatchQueue.global(qos: .userInitiated).async {
self.signatureValidator.validate(jwt) { error in
if let error = error { return callback(error) }
let result = self.claimsValidator.validate(jwt)
DispatchQueue.main.async {
callback(result)
}
}
}
}
}
enum IDTokenDecodingError: Auth0Error {
case cannotDecode
var debugDescription: String {
switch self {
case .cannotDecode: return "ID token could not be decoded"
}
}
}
func validate(idToken: String,
with context: IDTokenValidatorContext,
signatureValidator: JWTAsyncValidator? = nil, // for testing
claimsValidator: JWTValidator? = nil,
callback: @escaping (Auth0Error?) -> Void) {
guard let jwt = try? decode(jwt: idToken) else { return callback(IDTokenDecodingError.cannotDecode) }
var claimValidators: [JWTValidator] = [IDTokenIssValidator(issuer: context.issuer),
IDTokenSubValidator(),
IDTokenAudValidator(audience: context.audience),
IDTokenExpValidator(leeway: context.leeway),
IDTokenIatValidator()]
if let nonce = context.nonce {
claimValidators.append(IDTokenNonceValidator(nonce: nonce))
}
if let audience = jwt.audience, audience.count > 1 {
claimValidators.append(IDTokenAzpValidator(authorizedParty: context.audience))
}
if let maxAge = context.maxAge {
claimValidators.append(IDTokenAuthTimeValidator(leeway: context.leeway, maxAge: maxAge))
}
if let organization = context.organization {
if organization.starts(with: "org_") {
claimValidators.append(IDTokenOrgIDValidator(orgID: organization))
} else {
claimValidators.append(IDTokenOrgNameValidator(orgName: organization))
}
}
let validator = IDTokenValidator(signatureValidator: signatureValidator ?? IDTokenSignatureValidator(context: context),
claimsValidator: claimsValidator ?? IDTokenClaimsValidator(validators: claimValidators),
context: context)
validator.validate(jwt, callback: callback)
}
#endif