feat: add .bearer credential for OAuth access tokens (#4)

This commit is contained in:
systemblue 2026-06-04 11:15:25 +02:00 committed by secana
parent 7352bc4b1f
commit 551e1d01ea
2 changed files with 53 additions and 2 deletions

View file

@ -7,6 +7,7 @@ public final class ForgejoClient: Sendable {
private enum AuthCredential: Sendable {
case basic(base64: String)
case token(String)
case bearer(String)
}
private let credential: AuthCredential
@ -48,6 +49,21 @@ public final class ForgejoClient: Sendable {
)
}
/// Creates a client authenticated with an OAuth2 access token.
///
/// OAuth2 access tokens are sent with the `Authorization: Bearer` scheme,
/// unlike personal access tokens which use `Authorization: token`.
public convenience init(
serverURL: String, username: String, bearerToken: String,
allowSelfSignedCertificates: Bool = false,
) {
self.init(
serverURL: serverURL, username: username,
credential: .bearer(bearerToken),
allowSelfSignedCertificates: allowSelfSignedCertificates,
)
}
public static func login(
serverURL: String, username: String, password: String,
allowSelfSignedCertificates: Bool = false,
@ -125,11 +141,19 @@ public final class ForgejoClient: Sendable {
}
private func applyAuthHeader(to request: inout URLRequest) {
request.setValue(authorizationHeaderValue, forHTTPHeaderField: "Authorization")
}
/// The `Authorization` header value for this client's credential.
/// Exposed internally so tests can assert the scheme without issuing a request.
var authorizationHeaderValue: String {
switch credential {
case let .basic(base64):
request.setValue("Basic \(base64)", forHTTPHeaderField: "Authorization")
"Basic \(base64)"
case let .token(token):
request.setValue("token \(token)", forHTTPHeaderField: "Authorization")
"token \(token)"
case let .bearer(token):
"Bearer \(token)"
}
}

View file

@ -0,0 +1,27 @@
import Foundation
import Testing
@testable import ForgejoKit
struct BearerCredentialTests {
@Test func bearerCredentialUsesBearerScheme() {
let client = ForgejoClient(
serverURL: "https://codeberg.org", username: "octocat", bearerToken: "abc123",
)
#expect(client.authorizationHeaderValue == "Bearer abc123")
}
@Test func tokenCredentialStillUsesTokenScheme() {
let client = ForgejoClient(
serverURL: "https://codeberg.org", username: "octocat", token: "abc123",
)
#expect(client.authorizationHeaderValue == "token abc123")
}
@Test func basicCredentialUsesBasicScheme() {
let client = ForgejoClient(
serverURL: "https://codeberg.org", username: "octocat", password: "pw",
)
let expected = "Basic " + Data("octocat:pw".utf8).base64EncodedString()
#expect(client.authorizationHeaderValue == expected)
}
}