From fa56bb956bb4bd430727d9a09f369bef6f8028c5 Mon Sep 17 00:00:00 2001 From: Kevin McKee Date: Mon, 12 Jan 2026 08:01:33 -0800 Subject: [PATCH 01/11] Calculated local authentication policy based on os + version --- Sources/OAuthKit/OAuth.swift | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Sources/OAuthKit/OAuth.swift b/Sources/OAuthKit/OAuth.swift index 6fd3339..a32197b 100644 --- a/Sources/OAuthKit/OAuth.swift +++ b/Sources/OAuthKit/OAuth.swift @@ -51,6 +51,18 @@ public final class OAuth: Sendable { #if os(macOS) || os(iOS) || os(visionOS) @ObservationIgnored var context: LAContext = .init() + + var policy: LAPolicy = { + #if os(macOS) || os(iOS) + if #available(macOS 15, iOS 18, *) { + return .deviceOwnerAuthenticationWithBiometricsOrCompanion + } + return .deviceOwnerAuthenticationWithBiometrics + #else + return .deviceOwnerAuthenticationWithBiometrics + #endif + }() + #endif @ObservationIgnored From fee318ea8435517348158953c756b9f3080a3dee Mon Sep 17 00:00:00 2001 From: Kevin McKee Date: Mon, 12 Jan 2026 08:04:41 -0800 Subject: [PATCH 02/11] WIP --- Package.swift | 10 ++++----- Sources/OAuthKit/OAuth.swift | 39 ++++++++++++++++++++---------------- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/Package.swift b/Package.swift index fc4f96c..7e4c119 100644 --- a/Package.swift +++ b/Package.swift @@ -6,11 +6,11 @@ import PackageDescription let package = Package( name: "OAuthKit", platforms: [ - .iOS(.v26), - .macOS(.v26), - .tvOS(.v26), - .visionOS(.v26), - .watchOS(.v26) + .iOS(.v17), + .macOS(.v14), + .tvOS(.v17), + .visionOS(.v1), + .watchOS(.v10) ], products: [ .library( diff --git a/Sources/OAuthKit/OAuth.swift b/Sources/OAuthKit/OAuth.swift index a32197b..f5af1c8 100644 --- a/Sources/OAuthKit/OAuth.swift +++ b/Sources/OAuthKit/OAuth.swift @@ -51,7 +51,7 @@ public final class OAuth: Sendable { #if os(macOS) || os(iOS) || os(visionOS) @ObservationIgnored var context: LAContext = .init() - + var policy: LAPolicy = { #if os(macOS) || os(iOS) if #available(macOS 15, iOS 18, *) { @@ -62,7 +62,7 @@ public final class OAuth: Sendable { return .deviceOwnerAuthenticationWithBiometrics #endif }() - + #endif @ObservationIgnored @@ -129,15 +129,15 @@ public extension OAuth { state = .authorizing(provider, grantType) case .deviceCode: state = .requestingDeviceCode(provider) - Task.immediate { + task { [self] in await requestDeviceCode(provider: provider) } case .clientCredentials: - Task.immediate { + task { [self] in await requestClientCredentials(provider: provider) } case .refreshToken: - Task.immediate { + task { [self] in await refreshToken(provider: provider) } } @@ -150,7 +150,7 @@ public extension OAuth { /// - code: the code to exchange /// - pkce: the pkce data func token(provider: Provider, code: String, pkce: PKCE? = nil) { - Task.immediate { + task { [self] in await requestToken(provider: provider, code: code, pkce: pkce) } } @@ -245,19 +245,12 @@ private extension OAuth { #if os(macOS) || os(iOS) || os(visionOS) let localizedReason = context.localizedReason.isNotEmpty ? context.localizedReason: defaultAuthenticationWithBiometricsOrCompanionReason - #if os(macOS) || os(iOS) - let policy: LAPolicy = .deviceOwnerAuthenticationWithBiometricsOrCompanion - #else - let policy: LAPolicy = .deviceOwnerAuthenticationWithBiometrics - #endif var error: NSError? if context.canEvaluatePolicy(policy, error: &error) { context.evaluatePolicy(policy, localizedReason: localizedReason) { [weak self] success, error in - guard let self else { return } - Task.immediate { @MainActor in - if success { - self.loadAuthorizations() - } + guard let self, success else { return } + Task { @MainActor in + loadAuthorizations() } } } @@ -321,13 +314,25 @@ private extension OAuth { tasks.append(task) } else { // Execute the task immediately - Task.immediate { + task { [self] in await refreshToken(provider: provider) } } } } } + + /// Create and immediately start running a new detached task in the context of this actor. + /// - Parameters: + /// - priority: the task priority + /// - operation: the operation to be run immediately upon entering the task. + func task(priority: TaskPriority = .high, operation: sending @escaping @isolated(any) () async throws -> Void) { + if #available(macOS 26, iOS 26, watchOS 26, tvOS 26, visionOS 26, *) { + Task.immediate(operation: operation) + } else { + Task(priority: priority, operation: operation) + } + } } // MARK: URLRequests From bf27f9266f4c67d6f3a69606ee3c41d26b27f053 Mon Sep 17 00:00:00 2001 From: Kevin McKee Date: Mon, 12 Jan 2026 08:10:16 -0800 Subject: [PATCH 03/11] WIP --- Sources/OAuthKit/OAuth.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/OAuthKit/OAuth.swift b/Sources/OAuthKit/OAuth.swift index f5af1c8..77bd863 100644 --- a/Sources/OAuthKit/OAuth.swift +++ b/Sources/OAuthKit/OAuth.swift @@ -249,7 +249,7 @@ private extension OAuth { if context.canEvaluatePolicy(policy, error: &error) { context.evaluatePolicy(policy, localizedReason: localizedReason) { [weak self] success, error in guard let self, success else { return } - Task { @MainActor in + task { @MainActor [self] in loadAuthorizations() } } @@ -262,7 +262,7 @@ private extension OAuth { /// Starts the network monitor. func monitor() { - Task { + task { [self] in await networkMonitor.start() } } From 2dc11532c8a73b24da783519df53f13dd59ed160 Mon Sep 17 00:00:00 2001 From: Kevin McKee Date: Mon, 12 Jan 2026 08:19:15 -0800 Subject: [PATCH 04/11] README updates --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3ee7745..7e0ff10 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ ![Build](https://github.com/codefiesta/OAuthKit/actions/workflows/swift.yml/badge.svg) ![Swift 6.2+](https://img.shields.io/badge/Swift-6.2%2B-gold.svg) ![Xcode 26.0+](https://img.shields.io/badge/Xcode-26.0%2B-tomato.svg) -![iOS 26.0+](https://img.shields.io/badge/iOS-26.0%2B-crimson.svg) -![macOS 26.0+](https://img.shields.io/badge/macOS-26.0%2B-skyblue.svg) -![tvOS 26.0+](https://img.shields.io/badge/tvOS-26.0%2B-blue.svg) -![visionOS 26.0+](https://img.shields.io/badge/visionOS-26.0%2B-violet.svg) -![watchOS 26.0+](https://img.shields.io/badge/watchOS-26.0%2B-magenta.svg) +![iOS 17.0+](https://img.shields.io/badge/iOS-17.0%2B-crimson.svg) +![macOS 14.0+](https://img.shields.io/badge/macOS-14.0%2B-skyblue.svg) +![tvOS 17.0+](https://img.shields.io/badge/tvOS-17.0%2B-blue.svg) +![visionOS 1.0+](https://img.shields.io/badge/visionOS-1.0%2B-violet.svg) +![watchOS 10.0+](https://img.shields.io/badge/watchOS-10.0%2B-magenta.svg) [![License: MIT](https://img.shields.io/badge/License-MIT-indigo.svg)](https://opensource.org/licenses/MIT) ![Code Coverage](https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/codefiesta/87655b6e3c89b9198287b2fefbfa641f/raw/oauthkit-coverage.json) From a5aed6802a087b64b90ea24970a16f20c5d585a8 Mon Sep 17 00:00:00 2001 From: Kevin McKee Date: Mon, 12 Jan 2026 08:25:44 -0800 Subject: [PATCH 05/11] Fixing isolation warnings --- Sources/OAuthKit/OAuth.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/OAuthKit/OAuth.swift b/Sources/OAuthKit/OAuth.swift index 77bd863..58f228d 100644 --- a/Sources/OAuthKit/OAuth.swift +++ b/Sources/OAuthKit/OAuth.swift @@ -249,7 +249,7 @@ private extension OAuth { if context.canEvaluatePolicy(policy, error: &error) { context.evaluatePolicy(policy, localizedReason: localizedReason) { [weak self] success, error in guard let self, success else { return } - task { @MainActor [self] in + Task { @MainActor [self] in loadAuthorizations() } } From b2a1c2d9cb55bc9ef8f15cd075a7c2a10e450731 Mon Sep 17 00:00:00 2001 From: Kevin McKee Date: Mon, 12 Jan 2026 08:34:29 -0800 Subject: [PATCH 06/11] Lint fixes --- Sources/OAuthKit/OAuth.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/OAuthKit/OAuth.swift b/Sources/OAuthKit/OAuth.swift index 58f228d..94b88fa 100644 --- a/Sources/OAuthKit/OAuth.swift +++ b/Sources/OAuthKit/OAuth.swift @@ -289,7 +289,7 @@ private extension OAuth { let timeInterval: TimeInterval = .init(deviceCode.interval) let task = Task.delayed(timeInterval: timeInterval) { [weak self] in guard let self else { return } - await self.poll(provider: provider, deviceCode: deviceCode) + await poll(provider: provider, deviceCode: deviceCode) } tasks.append(task) } @@ -309,7 +309,7 @@ private extension OAuth { // Schedule the auto refresh task let task = Task.delayed(timeInterval: timeInterval) { [weak self] in guard let self else { return } - await self.refreshToken(provider: provider) + await refreshToken(provider: provider) } tasks.append(task) } else { From 3dcffd08cc1527b750775c182cd91fb7ac0e41c4 Mon Sep 17 00:00:00 2001 From: Kevin McKee Date: Mon, 12 Jan 2026 09:58:45 -0800 Subject: [PATCH 07/11] Swift 6.1 --- Package.swift | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Package.swift b/Package.swift index 7e4c119..73aa421 100644 --- a/Package.swift +++ b/Package.swift @@ -1,4 +1,4 @@ -// swift-tools-version: 6.2 +// swift-tools-version: 6.1 // The swift-tools-version declares the minimum version of Swift required to build this package. import PackageDescription diff --git a/README.md b/README.md index 7e0ff10..221363b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ![Build](https://github.com/codefiesta/OAuthKit/actions/workflows/swift.yml/badge.svg) -![Swift 6.2+](https://img.shields.io/badge/Swift-6.2%2B-gold.svg) +![Swift 6.1+](https://img.shields.io/badge/Swift-6.1%2B-gold.svg) ![Xcode 26.0+](https://img.shields.io/badge/Xcode-26.0%2B-tomato.svg) ![iOS 17.0+](https://img.shields.io/badge/iOS-17.0%2B-crimson.svg) ![macOS 14.0+](https://img.shields.io/badge/macOS-14.0%2B-skyblue.svg) From 512c8a12625e046b79613c254a4534ce8cf1a68b Mon Sep 17 00:00:00 2001 From: Kevin McKee Date: Mon, 12 Jan 2026 10:01:53 -0800 Subject: [PATCH 08/11] README updates --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 221363b..a34e518 100644 --- a/README.md +++ b/README.md @@ -36,11 +36,11 @@ Key features include: ## OAuthKit Installation -OAuthKit can be installed using [Swift Package Manager](https://www.swift.org/documentation/package-manager/). If you need to build with Swift Tools `6.1` and Apple APIs > `26.0` use version [1.5.1](https://github.com/codefiesta/OAuthKit/releases/tag/1.5.1). +OAuthKit can be installed using [Swift Package Manager](https://www.swift.org/documentation/package-manager/). ```swift dependencies: [ - .package(url: "https://github.com/codefiesta/OAuthKit", from: "2.0.1") + .package(url: "https://github.com/codefiesta/OAuthKit", from: "2.1.0") ] ``` From ad345e3db71770bcbf855547e5dd400b59b48dd2 Mon Sep 17 00:00:00 2001 From: Kevin McKee Date: Tue, 13 Jan 2026 10:12:42 -0800 Subject: [PATCH 09/11] Using the minimum matrix version provided by Apple. --- Package.swift | 4 ++-- README.md | 4 ++-- Sources/OAuthKit/OAuth.swift | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Package.swift b/Package.swift index 73aa421..ab74f96 100644 --- a/Package.swift +++ b/Package.swift @@ -7,8 +7,8 @@ let package = Package( name: "OAuthKit", platforms: [ .iOS(.v17), - .macOS(.v14), - .tvOS(.v17), + .macOS(.v15), + .tvOS(.v18), .visionOS(.v1), .watchOS(.v10) ], diff --git a/README.md b/README.md index a34e518..025b81c 100644 --- a/README.md +++ b/README.md @@ -2,8 +2,8 @@ ![Swift 6.1+](https://img.shields.io/badge/Swift-6.1%2B-gold.svg) ![Xcode 26.0+](https://img.shields.io/badge/Xcode-26.0%2B-tomato.svg) ![iOS 17.0+](https://img.shields.io/badge/iOS-17.0%2B-crimson.svg) -![macOS 14.0+](https://img.shields.io/badge/macOS-14.0%2B-skyblue.svg) -![tvOS 17.0+](https://img.shields.io/badge/tvOS-17.0%2B-blue.svg) +![macOS 15.0+](https://img.shields.io/badge/macOS-54.0%2B-skyblue.svg) +![tvOS 18.0+](https://img.shields.io/badge/tvOS-18.0%2B-blue.svg) ![visionOS 1.0+](https://img.shields.io/badge/visionOS-1.0%2B-violet.svg) ![watchOS 10.0+](https://img.shields.io/badge/watchOS-10.0%2B-magenta.svg) [![License: MIT](https://img.shields.io/badge/License-MIT-indigo.svg)](https://opensource.org/licenses/MIT) diff --git a/Sources/OAuthKit/OAuth.swift b/Sources/OAuthKit/OAuth.swift index 94b88fa..00907f6 100644 --- a/Sources/OAuthKit/OAuth.swift +++ b/Sources/OAuthKit/OAuth.swift @@ -54,7 +54,7 @@ public final class OAuth: Sendable { var policy: LAPolicy = { #if os(macOS) || os(iOS) - if #available(macOS 15, iOS 18, *) { + if #available(macOS 15.0, iOS 18.0, *) { return .deviceOwnerAuthenticationWithBiometricsOrCompanion } return .deviceOwnerAuthenticationWithBiometrics From 39baeddac25023f02970e73f4a3a937ad8652c05 Mon Sep 17 00:00:00 2001 From: Kevin McKee Date: Tue, 13 Jan 2026 10:15:46 -0800 Subject: [PATCH 10/11] README fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 025b81c..943d007 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ![Swift 6.1+](https://img.shields.io/badge/Swift-6.1%2B-gold.svg) ![Xcode 26.0+](https://img.shields.io/badge/Xcode-26.0%2B-tomato.svg) ![iOS 17.0+](https://img.shields.io/badge/iOS-17.0%2B-crimson.svg) -![macOS 15.0+](https://img.shields.io/badge/macOS-54.0%2B-skyblue.svg) +![macOS 15.0+](https://img.shields.io/badge/macOS-15.0%2B-skyblue.svg) ![tvOS 18.0+](https://img.shields.io/badge/tvOS-18.0%2B-blue.svg) ![visionOS 1.0+](https://img.shields.io/badge/visionOS-1.0%2B-violet.svg) ![watchOS 10.0+](https://img.shields.io/badge/watchOS-10.0%2B-magenta.svg) From 7191d8df402c0a7672646dfc62f7fa5e8f15497f Mon Sep 17 00:00:00 2001 From: Kevin McKee Date: Wed, 14 Jan 2026 09:00:18 -0800 Subject: [PATCH 11/11] Removing CodeQL workflow --- .github/workflows/codeql.yml | 81 ------------------------------------ 1 file changed, 81 deletions(-) delete mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index 2b1173c..0000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,81 +0,0 @@ -# This workflow will run CodeQL analysis. -name: CodeQL - -on: - push: - branches: [ "main" ] - pull_request: - branches: [ "main" ] - types: [opened, synchronize, reopened, ready_for_review] - schedule: - - cron: '30 7 * * 3' - -jobs: - - analyze: - - # Only run this action if the PR isn't a draft and it is labled as a `security` PR - if: github.event.pull_request.draft == false && contains(github.event.pull_request.labels.*.name, 'security') - - name: Analyze (${{ matrix.language }}) - # Runner size impacts CodeQL analysis time. To learn more, please see: - # - https://gh.io/recommended-hardware-resources-for-running-codeql - # - https://gh.io/supported-runners-and-hardware-resources - # - https://gh.io/using-larger-runners (GitHub.com only) - # Consider using larger runners or machines with greater resources for possible analysis time improvements. - - runs-on: macos-26 - timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }} - permissions: - # required for all workflows - security-events: write - - # required to fetch internal or private CodeQL packs - packages: read - - # only required for workflows in private repositories - actions: read - contents: read - - strategy: - fail-fast: false - matrix: - include: - - language: swift - build-mode: autobuild - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} - build-mode: ${{ matrix.build-mode }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - - # If the analyze step fails for one of the languages you are analyzing with - # "We were unable to automatically build your code", modify the matrix above - # to set the build mode to "manual" for that language. Then modify this step - # to build your code. - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - if: matrix.build-mode == 'manual' - shell: bash - run: | - echo 'If you are using a "manual" build mode for one or more of the' \ - 'languages you are analyzing, replace this with the commands to build' \ - 'your code, for example:' - echo ' make bootstrap' - echo ' make release' - exit 1 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 - with: - category: "/language:${{matrix.language}}"