mirror of https://github.com/cirruslabs/tart.git
Registry: use issued_at field in the token response message (#65)
* Registry: use issued_at field in the token response message * Configure JSONDecoder instead of the Decodable itself
This commit is contained in:
parent
3fdcc5c33c
commit
8554e56e4b
|
|
@ -8,11 +8,31 @@ enum RegistryError: Error {
|
|||
}
|
||||
|
||||
struct TokenResponse: Decodable {
|
||||
let creationTime = Date()
|
||||
|
||||
let defaultIssuedAt = Date()
|
||||
let defaultExpiresIn = 60
|
||||
|
||||
var token: String
|
||||
var expires_in: Int?
|
||||
|
||||
var expiresIn: Int?
|
||||
var issuedAt: Date?
|
||||
|
||||
static func parse(fromData: Data) throws -> Self {
|
||||
let decoder = JSONDecoder()
|
||||
|
||||
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||
|
||||
// RFC3339 date formatter from Apple's documentation[1]
|
||||
//
|
||||
// [1]: https://developer.apple.com/documentation/foundation/dateformatter
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
|
||||
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
|
||||
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
|
||||
|
||||
decoder.dateDecodingStrategy = .formatted(dateFormatter)
|
||||
|
||||
return try decoder.decode(TokenResponse.self, from: fromData)
|
||||
}
|
||||
|
||||
var tokenExpiresAt: Date {
|
||||
get {
|
||||
// Tokens can expire and expire_in field is used to determine when:
|
||||
|
|
@ -22,8 +42,8 @@ struct TokenResponse: Decodable {
|
|||
// >a token should never be returned with less than 60 seconds to live.
|
||||
//
|
||||
// [1]: https://docs.docker.com/registry/spec/auth/token/#requesting-a-token
|
||||
|
||||
creationTime + TimeInterval(expires_in ?? 60)
|
||||
|
||||
(issuedAt ?? defaultIssuedAt) + TimeInterval(expiresIn ?? defaultExpiresIn)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -233,7 +253,7 @@ class Registry {
|
|||
+ "while retrieving an authentication token", details: String(decoding: tokenResponseRaw, as: UTF8.self))
|
||||
}
|
||||
|
||||
currentAuthToken = try JSONDecoder().decode(TokenResponse.self, from: tokenResponseRaw)
|
||||
currentAuthToken = try TokenResponse.parse(fromData: tokenResponseRaw)
|
||||
}
|
||||
|
||||
private func authAwareRequest(request: URLRequest) async throws -> (Data, HTTPURLResponse) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
import XCTest
|
||||
@testable import tart
|
||||
|
||||
final class TokenResponseTests: XCTestCase {
|
||||
func testBasic() throws {
|
||||
let tokenResponseRaw = Data("{\"token\":\"some token\"}".utf8)
|
||||
let tokenResponse = try TokenResponse.parse(fromData: tokenResponseRaw)
|
||||
|
||||
XCTAssertEqual(tokenResponse.token, "some token")
|
||||
|
||||
let expectedTokenExpiresAtRange = Date()...Date().addingTimeInterval(60)
|
||||
XCTAssertTrue(expectedTokenExpiresAtRange.contains(tokenResponse.tokenExpiresAt))
|
||||
|
||||
XCTAssertTrue(tokenResponse.isValid)
|
||||
}
|
||||
|
||||
func testExpirationBasic() throws {
|
||||
let tokenResponseRaw = Data("{\"token\":\"some token\",\"expires_in\":2}".utf8)
|
||||
let tokenResponse = try TokenResponse.parse(fromData: tokenResponseRaw)
|
||||
|
||||
XCTAssertEqual(tokenResponse.expiresIn, 2)
|
||||
|
||||
let expectedTokenExpiresAtRange = Date()...Date().addingTimeInterval(2)
|
||||
XCTAssertTrue(expectedTokenExpiresAtRange.contains(tokenResponse.tokenExpiresAt))
|
||||
|
||||
XCTAssertTrue(tokenResponse.isValid)
|
||||
_ = XCTWaiter.wait(for: [expectation(description: "Wait 3 seconds for the token to become invalid")], timeout: 2)
|
||||
XCTAssertFalse(tokenResponse.isValid)
|
||||
}
|
||||
|
||||
func testExpirationWithIssuedAt() throws {
|
||||
let tokenResponseRaw = Data("{\"token\":\"some token\",\"expires_in\":3600,\"issued_at\":\"1970-01-01T00:00:00Z\"}".utf8)
|
||||
let tokenResponse = try TokenResponse.parse(fromData: tokenResponseRaw)
|
||||
|
||||
XCTAssertEqual(Date(timeIntervalSince1970: 3600), tokenResponse.tokenExpiresAt)
|
||||
XCTAssertFalse(tokenResponse.isValid)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue