Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 7 additions & 15 deletions Sources/UID2/Data/IdentityPackage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,12 @@ import Foundation
// https://github.com/IABTechLab/uid2-web-integrations/blob/5a8295c47697cdb1fe36997bc2eb2e39ae143f8b/src/uid2Sdk.ts#L174-L186
// NOTE: JS SDK makes 2 references to `IdentityStatus`, the second being an enum with actual states defined
// https://github.com/IABTechLab/uid2-web-integrations/blob/5a8295c47697cdb1fe36997bc2eb2e39ae143f8b/src/Uid2InitCallbacks.ts#L12-L20
public struct IdentityPackage: Hashable, Sendable {

public let valid: Bool
public let errorMessage: String?
public let identity: UID2Identity?
public let status: IdentityStatus

public init(valid: Bool, errorMessage: String?, identity: UID2Identity?, status: IdentityStatus) {
self.valid = valid
self.errorMessage = errorMessage
self.identity = identity
self.status = status
}
struct IdentityPackage: Hashable, Sendable {

let valid: Bool
let errorMessage: String?
let identity: UID2Identity?
let status: IdentityStatus
}

extension IdentityPackage: Codable {
Expand All @@ -32,7 +24,7 @@ extension IdentityPackage: Codable {
case valid, errorMessage, identity, status
}

public init(from decoder: Decoder) throws {
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

// Automatic
Expand All @@ -52,7 +44,7 @@ extension IdentityPackage: Codable {
}
}

public func encode(to encoder: Encoder) throws {
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)

// Automatic
Expand Down
8 changes: 4 additions & 4 deletions Sources/UID2/KeychainManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ import Foundation
import Security

/// Securely manages data in the Keychain
internal actor KeychainManager {
actor KeychainManager {

private let attrAccount = "uid2"

private let attrService = "auth-state"

public func getIdentityFromKeychain() -> IdentityPackage? {
func getIdentityFromKeychain() -> IdentityPackage? {
let query = [
String(kSecClass): kSecClassGenericPassword,
String(kSecAttrAccount): attrAccount,
Expand All @@ -31,7 +31,7 @@ internal actor KeychainManager {
}

@discardableResult
public func saveIdentityToKeychain(_ identityPackage: IdentityPackage) -> Bool {
func saveIdentityToKeychain(_ identityPackage: IdentityPackage) -> Bool {

guard let data = try? identityPackage.toData() else {
return false
Expand Down Expand Up @@ -63,7 +63,7 @@ internal actor KeychainManager {
}

@discardableResult
public func deleteIdentityFromKeychain() -> Bool {
func deleteIdentityFromKeychain() -> Bool {

let query: [String: Any] = [String(kSecClass): kSecClassGenericPassword,
String(kSecAttrAccount): attrAccount,
Expand Down
4 changes: 2 additions & 2 deletions Sources/UID2/Networking/RefreshTokenResponse.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ extension RefreshTokenResponse {

extension RefreshTokenResponse {

public func toUID2Identity() -> UID2Identity? {
func toUID2Identity() -> UID2Identity? {
guard let body = body else {
return nil
}
Expand All @@ -55,7 +55,7 @@ extension RefreshTokenResponse {
)
}

public func toRefreshAPIPackage() -> RefreshAPIPackage? {
func toRefreshAPIPackage() -> RefreshAPIPackage? {

switch status {
case .success:
Expand Down
28 changes: 14 additions & 14 deletions Sources/UID2/UID2Manager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -217,12 +217,12 @@ public final actor UID2Manager {
}
}

private func hasExpired(expiry: Int64) async -> Bool {
private func hasExpired(expiry: Int64) -> Bool {
return expiry <= dateGenerator.now.millisecondsSince1970
}

private func getIdentityPackage(identity: UID2Identity?) async -> IdentityPackage {
private func getIdentityPackage(identity: UID2Identity?, newIdentity: Bool) -> IdentityPackage {

guard let identity = identity else {
return IdentityPackage(valid: false, errorMessage: "Identity not available", identity: nil, status: .noIdentity)
}
Expand All @@ -235,15 +235,15 @@ public final actor UID2Manager {
return IdentityPackage(valid: false, errorMessage: "refresh_token is not available or is not valid", identity: nil, status: .invalid)
}

if await hasExpired(expiry: identity.refreshExpires) {
if hasExpired(expiry: identity.refreshExpires) {
return IdentityPackage(valid: false, errorMessage: "Identity expired, refresh expired", identity: nil, status: .refreshExpired)
}

if await hasExpired(expiry: identity.identityExpires) {
if hasExpired(expiry: identity.identityExpires) {
return IdentityPackage(valid: true, errorMessage: "Identity expired, refresh still valid", identity: identity, status: .expired)
}

if self.identity == nil || self.identity?.advertisingToken == identity.advertisingToken && self.identityStatus != .refreshed {
if newIdentity {
return IdentityPackage(valid: true, errorMessage: "Identity established", identity: identity, status: .established)
}

Expand Down Expand Up @@ -275,7 +275,7 @@ public final actor UID2Manager {
}

// Process Remaining IdentityStatus Options
let validatedIdentityPackage = await getIdentityPackage(identity: identity)
let validatedIdentityPackage = getIdentityPackage(identity: identity, newIdentity: self.identity == nil)

os_log("Updating identity (Identity: %@, Status: %@)", log: log,
validatedIdentityPackage.identity != nil ? "true" : "false",
Expand Down Expand Up @@ -316,13 +316,13 @@ public final actor UID2Manager {
if let identity = identity {
// If the identity is already suitable for a refresh, we can do so immediately. Otherwise, we will work out
// how long it is until a refresh is required and schedule it accordingly.
if await hasExpired(expiry: identity.refreshFrom) {
if hasExpired(expiry: identity.refreshFrom) {
refreshJob = Task {
await refreshToken(identity: identity)
}
} else {
refreshJob = Task {
let delayInNanoseconds = await calculateDelay(futureCompletionTime: identity.refreshFrom)
let delayInNanoseconds = calculateDelay(futureCompletionTime: identity.refreshFrom)
try await Task.sleep(nanoseconds: delayInNanoseconds)
await refreshToken(identity: identity)
}
Expand All @@ -343,18 +343,18 @@ public final actor UID2Manager {

// If the expiration time of being able to refresh is in the future, we will schedule a job to detect if we
// pass it. This will allow us to reevaluate our state and update accordingly.
if await !hasExpired(expiry: identity.refreshExpires) {
if !hasExpired(expiry: identity.refreshExpires) {
checkRefreshExpiresJob = Task {
let delayInNanoseconds = await calculateDelay(futureCompletionTime: identity.refreshExpires)
let delayInNanoseconds = calculateDelay(futureCompletionTime: identity.refreshExpires)
try await Task.sleep(nanoseconds: delayInNanoseconds)
os_log("Detected refresh has expired", log: log, type: .debug)
await validateAndSetIdentity(identity: identity, status: nil, statusText: nil)
}
}

if await !hasExpired(expiry: identity.identityExpires) {
if !hasExpired(expiry: identity.identityExpires) {
checkIdentityExpiresJob = Task {
let delayInNanoseconds = await calculateDelay(futureCompletionTime: identity.identityExpires)
let delayInNanoseconds = calculateDelay(futureCompletionTime: identity.identityExpires)
try await Task.sleep(nanoseconds: delayInNanoseconds)
os_log("Detected identity has expired", log: log, type: .debug)
await validateAndSetIdentity(identity: identity, status: nil, statusText: nil)
Expand All @@ -367,7 +367,7 @@ public final actor UID2Manager {
/// Calculate the delay that Identity Checks use
/// - Parameter futureCompletionTime: The time in milliseconds to end the
/// - Returns: Delay in nanonseconds (UInt64) or 0 if futureCompletionTime is less than now
private func calculateDelay(futureCompletionTime: Int64) async -> UInt64 {
private func calculateDelay(futureCompletionTime: Int64) -> UInt64 {
let now = dateGenerator.now.millisecondsSince1970
if futureCompletionTime < now {
return UInt64(0)
Expand Down