Skip to content

Commit d14acf5

Browse files
authored
Merge pull request #209 from P24L/feature/auto-token-refresh
feat: Add automatic token refresh for API methods
2 parents 73507b0 + 84b297c commit d14acf5

File tree

3 files changed

+26
-2
lines changed

3 files changed

+26
-2
lines changed

Sources/ATProtoKit/APIReference/AppBskyAPI/AppBskyFeedGetTimelineMethod.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ extension ATProtoKit {
4747
throw ATRequestPrepareError.missingActiveSession
4848
}
4949

50+
try await sessionConfiguration?.ensureValidToken()
5051
let accessToken = try await keychain.retrieveAccessToken()
5152
let sessionURL = session.serviceEndpoint.absoluteString
5253

Sources/ATProtoKit/APIReference/SessionManager/SessionConfiguration.swift

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,14 @@ public protocol SessionConfiguration: AnyObject, Sendable {
176176
///
177177
/// - Parameter input: The Two-Factor Authentication code.
178178
func receiveCodeFromUser(_ input: String)
179+
180+
/// Ensures the access token is valid and refreshes it if needed.
181+
///
182+
/// This method checks if the current access token will expire within
183+
/// the next 10 seconds and automatically refreshes it if necessary.
184+
///
185+
/// - Throws: An ``ATProtoError``-conforming error type if refresh fails.
186+
func ensureValidToken() async throws
179187
}
180188

181189
extension SessionConfiguration {
@@ -541,4 +549,17 @@ extension SessionConfiguration {
541549

542550
return decodedDidDocument
543551
}
552+
553+
public func ensureValidToken() async throws {
554+
let accessToken = try await keychainProtocol.retrieveAccessToken()
555+
556+
do {
557+
if try SessionToken(sessionToken: accessToken).payload.expiresAt.addingTimeInterval(10) <= Date() {
558+
try await self.refreshSession()
559+
}
560+
} catch {
561+
// If we can't parse the token, continue with the original token
562+
// The API call will fail with proper error if token is invalid
563+
}
564+
}
544565
}

Sources/ATProtoKit/ATProtoKit.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,10 @@ extension ATProtoKitConfiguration {
6161
// Check if the session exists and has a valid access token.
6262
if let sessionConfiguration = sessionConfiguration {
6363
do {
64-
let keychain = try await sessionConfiguration.keychainProtocol.retrieveAccessToken()
65-
return "Bearer \(keychain)"
64+
// Ensure token is valid before retrieving it
65+
try await sessionConfiguration.ensureValidToken()
66+
let accessToken = try await sessionConfiguration.keychainProtocol.retrieveAccessToken()
67+
return "Bearer \(accessToken)"
6668
} catch {
6769
return nil
6870
}

0 commit comments

Comments
 (0)