diff --git a/Sources/ContainerizationOCI/Client/RegistryClient.swift b/Sources/ContainerizationOCI/Client/RegistryClient.swift index 6c897e23..679155cb 100644 --- a/Sources/ContainerizationOCI/Client/RegistryClient.swift +++ b/Sources/ContainerizationOCI/Client/RegistryClient.swift @@ -184,13 +184,26 @@ public final class RegistryClient: ContentClient { if let ct = currentToken, ct.isValid(scope: tokenRequest.scope) { break } - let _currentToken = try await fetchToken(request: tokenRequest) - guard let token = _currentToken.getToken() else { - throw ContainerizationError(.internalError, message: "Failed to fetch Bearer token") + + do { + let _currentToken = try await fetchToken(request: tokenRequest) + guard let token = _currentToken.getToken() else { + throw ContainerizationError(.internalError, message: "Failed to fetch Bearer token") + } + currentToken = _currentToken + request.headers.replaceOrAdd(name: "Authorization", value: token) + retryCount += 1 + } catch let err as RegistryClient.Error { + guard case .invalidStatus(_, let status, _) = err else { + throw err + } + if status == .unauthorized || status == .forbidden { + throw RegistryClient.Error.invalidStatus(url: path, _response.status, reason: "Access denied or wrong credentials") + } + + throw err } - currentToken = _currentToken - request.headers.replaceOrAdd(name: "Authorization", value: token) - retryCount += 1 + continue } guard let retryOptions = self.retryOptions else { diff --git a/Tests/ContainerizationOCITests/RegistryClientTests.swift b/Tests/ContainerizationOCITests/RegistryClientTests.swift index a9ebf19d..401ce701 100644 --- a/Tests/ContainerizationOCITests/RegistryClientTests.swift +++ b/Tests/ContainerizationOCITests/RegistryClientTests.swift @@ -81,10 +81,11 @@ struct OCIClientTests: ~Copyable { let authentication = BasicAuthentication(username: "foo", password: "bar") let client = RegistryClient(host: "ghcr.io", authentication: authentication) let error = await #expect(throws: RegistryClient.Error.self) { try await client.ping() } - if case .invalidStatus = error { - } else { - Issue.record("encountered unexpected error \(error)") + guard case .invalidStatus(_, let status, let reason) = error else { + throw error! } + #expect(status == .unauthorized) + #expect(reason == "Access denied or wrong credentials") } @Test(.enabled(if: hasRegistryCredentials))