Skip to content

Commit 7bdb3e8

Browse files
committed
Removed the logic for saving auth_time within User Defaults. Added the logic for decoding id token within AuthenticationViewModel
1 parent cfae9ba commit 7bdb3e8

3 files changed

Lines changed: 49 additions & 28 deletions

File tree

‎Samples/Swift/DaysUntilBirthday/Shared/DaysUntilBirthday.swift‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ struct DaysUntilBirthday: App {
2929
GIDSignIn.sharedInstance.restorePreviousSignIn { user, error in
3030
if let user = user {
3131
self.authViewModel.state = .signedIn(user)
32-
self.authViewModel.authTime = UserDefaults.standard.object(forKey: "authTime") as? Date
3332
} else if let error = error {
3433
self.authViewModel.state = .signedOut
3534
print("There was an error restoring the previous sign-in: \(error)")

‎Samples/Swift/DaysUntilBirthday/Shared/Services/GoogleSignInAuthenticator.swift‎

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,6 @@ final class GoogleSignInAuthenticator: ObservableObject {
5959
assertionFailure("ERROR: Returned nonce doesn't match manual nonce!")
6060
return
6161
}
62-
if let authTimeDate = self.decodeAuthTime(fromJWT: idToken) {
63-
self.authViewModel.authTime = authTimeDate
64-
UserDefaults.standard.set(authTimeDate, forKey: "authTime")
65-
}
6662
self.authViewModel.state = .signedIn(signInResult.user)
6763
}
6864

@@ -80,17 +76,6 @@ final class GoogleSignInAuthenticator: ObservableObject {
8076
print("Error! \(String(describing: error))")
8177
return
8278
}
83-
84-
// If the idToken is nil, we cannot get the authTime, so we treat this
85-
// as a failure for the app's sign-in flow and return.
86-
guard let idToken = signInResult.user.idToken?.tokenString else {
87-
print("Error: idToken is missing from signInResult.")
88-
return
89-
}
90-
if let authTimeDate = self.decodeAuthTime(fromJWT: idToken) {
91-
self.authViewModel.authTime = authTimeDate
92-
UserDefaults.standard.set(authTimeDate, forKey: "authTime")
93-
}
9479
self.authViewModel.state = .signedIn(signInResult.user)
9580
}
9681
#endif
@@ -164,7 +149,7 @@ final class GoogleSignInAuthenticator: ObservableObject {
164149

165150
// MARK: Parse nonce from JWT ID Token
166151

167-
private extension GoogleSignInAuthenticator {
152+
extension GoogleSignInAuthenticator {
168153
func decodeNonce(fromJWT jwt: String) -> String? {
169154
let segments = jwt.components(separatedBy: ".")
170155
guard let parts = decodeJWTSegment(segments[1]),
@@ -174,16 +159,6 @@ private extension GoogleSignInAuthenticator {
174159
return nonce
175160
}
176161

177-
func decodeAuthTime(fromJWT jwt: String) -> Date? {
178-
let segments = jwt.components(separatedBy: ".")
179-
guard segments.count > 1,
180-
let parts = decodeJWTSegment(segments[1]),
181-
let authTimeInterval = parts["auth_time"] as? TimeInterval else {
182-
return nil
183-
}
184-
return Date(timeIntervalSince1970: authTimeInterval)
185-
}
186-
187162
func decodeJWTSegment(_ segment: String) -> [String: Any]? {
188163
guard let segmentData = base64UrlDecode(segment),
189164
let segmentJSON = try? JSONSerialization.jsonObject(with: segmentData, options: []),

‎Samples/Swift/DaysUntilBirthday/Shared/ViewModels/AuthenticationViewModel.swift‎

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,21 @@ final class AuthenticationViewModel: ObservableObject {
2222
/// The user's log in status.
2323
/// - note: This will publish updates when its value changes.
2424
@Published var state: State
25-
@Published var authTime: Date?
2625
private var authenticator: GoogleSignInAuthenticator {
2726
return GoogleSignInAuthenticator(authViewModel: self)
2827
}
28+
29+
// 3. Change authTime to a computed property
30+
var authTime: Date? {
31+
switch state {
32+
case .signedIn(let user):
33+
guard let idToken = user.idToken?.tokenString else { return nil }
34+
return decodeAuthTime(fromJWT: idToken)
35+
case .signedOut:
36+
return nil
37+
}
38+
}
39+
2940
/// The user-authorized scopes.
3041
/// - note: If the user is logged out, then this will default to empty.
3142
var authorizedScopes: [String] {
@@ -79,6 +90,42 @@ final class AuthenticationViewModel: ObservableObject {
7990
}
8091
}
8192

93+
private extension AuthenticationViewModel {
94+
func decodeAuthTime(fromJWT jwt: String) -> Date? {
95+
let segments = jwt.components(separatedBy: ".")
96+
guard segments.count > 1,
97+
let parts = decodeJWTSegment(segments[1]),
98+
let authTimeInterval = parts["auth_time"] as? TimeInterval else {
99+
return nil
100+
}
101+
return Date(timeIntervalSince1970: authTimeInterval)
102+
}
103+
104+
func decodeJWTSegment(_ segment: String) -> [String: Any]? {
105+
guard let segmentData = base64UrlDecode(segment),
106+
let segmentJSON = try? JSONSerialization.jsonObject(with: segmentData, options: []),
107+
let payload = segmentJSON as? [String: Any] else {
108+
return nil
109+
}
110+
return payload
111+
}
112+
113+
func base64UrlDecode(_ value: String) -> Data? {
114+
var base64 = value
115+
.replacingOccurrences(of: "-", with: "+")
116+
.replacingOccurrences(of: "_", with: "/")
117+
118+
let length = Double(base64.lengthOfBytes(using: String.Encoding.utf8))
119+
let requiredLength = 4 * ceil(length / 4.0)
120+
let paddingLength = requiredLength - length
121+
if paddingLength > 0 {
122+
let padding = "".padding(toLength: Int(paddingLength), withPad: "=", startingAt: 0)
123+
base64 = base64 + padding
124+
}
125+
return Data(base64Encoded: base64, options: .ignoreUnknownCharacters)
126+
}
127+
}
128+
82129
extension AuthenticationViewModel {
83130
/// An enumeration representing logged in status.
84131
enum State {

0 commit comments

Comments
 (0)