Skip to content

Commit 780e6ac

Browse files
committed
Refactor DPoP Signing to correctly track nonces per origin
This also ensures we clearly signal to the DPoP request method whether we are talking to an authorization server or a resource server (since these give different OAuth Error responses). The test coverage has increased dramatically here.
1 parent f4d416f commit 780e6ac

9 files changed

Lines changed: 961 additions & 73 deletions

File tree

Sources/OAuthenticator/Authenticator.swift

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -308,20 +308,20 @@ extension Authenticator {
308308
pcke: config.tokenHandling.pkce,
309309
parRequestURI: parRequestURI,
310310
stateToken: stateToken,
311-
responseProvider: { try await self.dpopResponse(for: $0, login: nil) }
311+
responseProvider: { try await self.dpopResponse(for: $0, login: nil, isAuthServer: true) }
312312
)
313313

314314
let tokenURL = try await config.tokenHandling.authorizationURLProvider(authConfig)
315315

316316
let scheme = try config.appCredentials.callbackURLScheme
317317

318-
let callbackURL = try await userAuthenticator(tokenURL, scheme)
318+
let callbackURL = try await userAuthenticator(tokenURL, scheme)
319319

320320
let params = TokenHandling.LoginProviderParameters(
321321
authorizationURL: tokenURL,
322322
credentials: config.appCredentials,
323323
redirectURL: callbackURL,
324-
responseProvider: { try await self.dpopResponse(for: $0, login: nil) },
324+
responseProvider: { try await self.dpopResponse(for: $0, login: nil, isAuthServer: true) },
325325
stateToken: stateToken,
326326
pcke: config.tokenHandling.pkce
327327
)
@@ -347,7 +347,11 @@ extension Authenticator {
347347
}
348348

349349
do {
350-
let login = try await refreshProvider(login, config.appCredentials, { try await self.dpopResponse(for: $0, login: nil) })
350+
let login = try await refreshProvider(
351+
login, config.appCredentials,
352+
{
353+
try await self.dpopResponse(for: $0, login: nil, isAuthServer: true)
354+
})
351355

352356
try await storeLogin(login)
353357

@@ -365,7 +369,7 @@ extension Authenticator {
365369
}
366370

367371
let challenge = pkce.challenge
368-
let scopes = config.appCredentials.scopes.joined(separator: " ")
372+
let scopes = config.appCredentials.scopeString
369373
let callbackURI = config.appCredentials.callbackURL
370374
let clientId = config.appCredentials.clientId
371375

@@ -391,7 +395,7 @@ extension Authenticator {
391395

392396
request.httpBody = Data(body.utf8)
393397

394-
let (parData, _) = try await dpopResponse(for: request, login: nil)
398+
let (parData, _) = try await self.dpopResponse(for: request, login: nil, isAuthServer: true)
395399

396400
return try JSONDecoder().decode(PARResponse.self, from: parData)
397401
}
@@ -412,7 +416,31 @@ extension Authenticator {
412416
{ try await self.response(for: $0) }
413417
}
414418

415-
private func dpopResponse(for request: URLRequest, login: Login?) async throws -> (Data, URLResponse) {
419+
private func dpopResponse(for request: URLRequest, login: Login?) async throws -> (
420+
Data, URLResponse
421+
) {
422+
var issuer: String? = nil
423+
if let iss = login?.issuingServer {
424+
issuer = URL(string: iss)?.origin
425+
}
426+
427+
guard let requestOrigin = request.url?.origin else {
428+
throw DPoPError.requestInvalid(request)
429+
}
430+
431+
let isAuthServer = issuer == nil || issuer == requestOrigin
432+
433+
return try await dpopResponse(
434+
for: request,
435+
login: login,
436+
isAuthServer: isAuthServer
437+
)
438+
}
439+
440+
private func dpopResponse(for request: URLRequest, login: Login?, isAuthServer: Bool?)
441+
async throws -> (Data, URLResponse)
442+
{
443+
print("Request: \(request.httpMethod!) - \(request.url?.absoluteString ?? "missing url")")
416444
guard let generator = config.tokenHandling.dpopJWTGenerator else {
417445
return try await urlLoader(request)
418446
}
@@ -430,8 +458,8 @@ extension Authenticator {
430458
using: generator,
431459
token: token,
432460
tokenHash: tokenHash,
433-
issuingServer: login?.issuingServer,
434-
provider: urlLoader
461+
isAuthServer: isAuthServer,
462+
responseProvider: urlLoader
435463
)
436464
}
437465
}

0 commit comments

Comments
 (0)