-
Notifications
You must be signed in to change notification settings - Fork 490
Expand file tree
/
Copy pathMultiFactor.swift
More file actions
114 lines (101 loc) · 3.2 KB
/
MultiFactor.swift
File metadata and controls
114 lines (101 loc) · 3.2 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
113
114
// Copyright 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
@preconcurrency import FirebaseAuth
import SwiftUI
public enum SecondFactorType {
case sms
case totp
}
public struct TOTPEnrollmentInfo {
public let sharedSecretKey: String
public let qrCodeURL: URL?
public let accountName: String?
public let issuer: String?
public let verificationStatus: VerificationStatus
public enum VerificationStatus {
case pending
case verified
case failed
}
public init(sharedSecretKey: String,
qrCodeURL: URL? = nil,
accountName: String? = nil,
issuer: String? = nil,
verificationStatus: VerificationStatus = .pending) {
self.sharedSecretKey = sharedSecretKey
self.qrCodeURL = qrCodeURL
self.accountName = accountName
self.issuer = issuer
self.verificationStatus = verificationStatus
}
}
public struct EnrollmentSession {
public let id: String
public let type: SecondFactorType
public let session: MultiFactorSession
public let totpInfo: TOTPEnrollmentInfo?
public let phoneNumber: String?
public let verificationId: String?
public let status: EnrollmentStatus
public let createdAt: Date
public let expiresAt: Date
// Internal handle to finish TOTP
internal let _totpSecret: AnyObject?
public enum EnrollmentStatus {
case initiated
case verificationSent
case verificationPending
case completed
case failed
case expired
}
public init(id: String = UUID().uuidString,
type: SecondFactorType,
session: MultiFactorSession,
totpInfo: TOTPEnrollmentInfo? = nil,
phoneNumber: String? = nil,
verificationId: String? = nil,
status: EnrollmentStatus = .initiated,
createdAt: Date = Date(),
expiresAt: Date = Date().addingTimeInterval(600), // 10 minutes default
_totpSecret: AnyObject? = nil) {
self.id = id
self.type = type
self.session = session
self.totpInfo = totpInfo
self.phoneNumber = phoneNumber
self.verificationId = verificationId
self.status = status
self.createdAt = createdAt
self.expiresAt = expiresAt
self._totpSecret = _totpSecret
}
public var isExpired: Bool {
return Date() > expiresAt
}
public var canProceed: Bool {
return !isExpired &&
(status == .initiated || status == .verificationSent || status == .verificationPending)
}
}
public enum MFAHint {
case phone(displayName: String?, uid: String, phoneNumber: String?)
case totp(displayName: String?, uid: String)
}
public struct MFARequired {
public let hints: [MFAHint]
public init(hints: [MFAHint]) {
self.hints = hints
}
}