Skip to content

Commit

Permalink
feat: add a helper function for DPoP retry management
Browse files Browse the repository at this point in the history
  • Loading branch information
panva committed Oct 7, 2024
1 parent dcaf056 commit 06493e3
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 152 deletions.
42 changes: 8 additions & 34 deletions conformance/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -337,11 +337,7 @@ export const flow = (options?: MacroOptions) => {
try {
result = await oauth.processPushedAuthorizationResponse(as, client, par)
} catch (err) {
if (
DPoPKeyPair &&
err instanceof oauth.ResponseBodyError &&
err.error === 'use_dpop_nonce'
) {
if (DPoPKeyPair && oauth.isDPoPNonceError(err)) {
t.log('error', inspect(err, { depth: Infinity }))
t.log('retrying with a newly obtained dpop nonce')
par = await request()
Expand Down Expand Up @@ -413,11 +409,7 @@ export const flow = (options?: MacroOptions) => {
result = await oauth.processAuthorizationCodeResponse(as, client, response)
}
} catch (err) {
if (
DPoPKeyPair &&
err instanceof oauth.ResponseBodyError &&
err.error === 'use_dpop_nonce'
) {
if (DPoPKeyPair && oauth.isDPoPNonceError(err)) {
t.log('error', inspect(err, { depth: Infinity }))
t.log('retrying with a newly obtained dpop nonce')
response = await request()
Expand Down Expand Up @@ -461,18 +453,9 @@ export const flow = (options?: MacroOptions) => {
t.log('userinfo endpoint response', { ...result })
} catch (err) {
t.log('error', inspect(err, { depth: Infinity }))
if (DPoPKeyPair && err instanceof oauth.WWWAuthenticateChallengeError) {
const { 0: challenge, length } = err.cause
if (
length === 1 &&
challenge.scheme === 'dpop' &&
challenge.parameters.error === 'use_dpop_nonce'
) {
t.log('retrying with a newly obtained dpop nonce')
response = await request()
} else {
throw err
}
if (DPoPKeyPair && oauth.isDPoPNonceError(err)) {
t.log('retrying with a newly obtained dpop nonce')
response = await request()
} else {
throw err
}
Expand Down Expand Up @@ -501,18 +484,9 @@ export const flow = (options?: MacroOptions) => {
accounts = await request()
} catch (err) {
t.log('error', inspect(err, { depth: Infinity }))
if (DPoPKeyPair && err instanceof oauth.WWWAuthenticateChallengeError) {
const { 0: challenge, length } = err.cause
if (
length === 1 &&
challenge.scheme === 'dpop' &&
challenge.parameters.error === 'use_dpop_nonce'
) {
t.log('retrying with a newly obtained dpop nonce')
accounts = await request()
} else {
throw err
}
if (DPoPKeyPair && oauth.isDPoPNonceError(err)) {
t.log('retrying with a newly obtained dpop nonce')
accounts = await request()
} else {
throw err
}
Expand Down
28 changes: 9 additions & 19 deletions examples/dpop.diff
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
diff --git a/examples/oauth.ts b/examples/dpop.ts
index d55e62d..29b3c7f 100644
index d55e62d..4cb7a95 100644
--- a/examples/oauth.ts
+++ b/examples/dpop.ts
@@ -15,6 +15,12 @@ let client_secret!: string
Expand All @@ -23,7 +23,7 @@ index d55e62d..29b3c7f 100644

const code_challenge_method = 'S256'
/**
@@ -64,16 +71,32 @@ let access_token: string
@@ -64,16 +71,29 @@ let access_token: string
const currentUrl: URL = getCurrentUrl()
const params = oauth.validateAuthResponse(as, client, currentUrl, state)

Expand Down Expand Up @@ -53,19 +53,16 @@ index d55e62d..29b3c7f 100644

- const result = await oauth.processAuthorizationCodeResponse(as, client, response)
+ let result = await processAuthorizationCodeResponse().catch(async (err) => {
+ if (err instanceof oauth.ResponseBodyError) {
+ if (result.error === 'use_dpop_nonce') {
+ // the AS-signalled nonce is now cached, retrying
+ response = await authorizationCodeGrantRequest()
+ return processAuthorizationCodeResponse()
+ }
+ if (oauth.isDPoPNonceError(err)) {
+ response = await authorizationCodeGrantRequest()
+ return processAuthorizationCodeResponse()
+ }
+ throw err
+ })

console.log('Access Token Response', result)
;({ access_token } = result)
@@ -81,11 +104,29 @@ let access_token: string
@@ -81,11 +101,22 @@ let access_token: string

// Protected Resource Request
{
Expand All @@ -84,16 +81,9 @@ index d55e62d..29b3c7f 100644
+ { DPoP },
+ )
+ let response = await protectedResourceRequest().catch((err) => {
+ if (err instanceof oauth.WWWAuthenticateChallengeError) {
+ const { 0: challenge, length } = err.cause
+ if (
+ length === 1 &&
+ challenge.scheme === 'dpop' &&
+ challenge.parameters.error === 'use_dpop_nonce'
+ ) {
+ // the AS-signalled nonce is now cached, retrying
+ return protectedResourceRequest()
+ }
+ if (oauth.isDPoPNonceError(err)) {
+ // the RS-signalled nonce is now cached, retrying
+ return protectedResourceRequest()
+ }
+ throw err
+ })
Expand Down
22 changes: 6 additions & 16 deletions examples/dpop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,9 @@ let access_token: string
oauth.processAuthorizationCodeResponse(as, client, response)

let result = await processAuthorizationCodeResponse().catch(async (err) => {
if (err instanceof oauth.ResponseBodyError) {
if (result.error === 'use_dpop_nonce') {
// the AS-signalled nonce is now cached, retrying
response = await authorizationCodeGrantRequest()
return processAuthorizationCodeResponse()
}
if (oauth.isDPoPNonceError(err)) {
response = await authorizationCodeGrantRequest()
return processAuthorizationCodeResponse()
}
throw err
})
Expand All @@ -114,16 +111,9 @@ let access_token: string
{ DPoP },
)
let response = await protectedResourceRequest().catch((err) => {
if (err instanceof oauth.WWWAuthenticateChallengeError) {
const { 0: challenge, length } = err.cause
if (
length === 1 &&
challenge.scheme === 'dpop' &&
challenge.parameters.error === 'use_dpop_nonce'
) {
// the AS-signalled nonce is now cached, retrying
return protectedResourceRequest()
}
if (oauth.isDPoPNonceError(err)) {
// the RS-signalled nonce is now cached, retrying
return protectedResourceRequest()
}
throw err
})
Expand Down
10 changes: 5 additions & 5 deletions examples/fapi2-message-signing.diff
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
diff --git a/examples/fapi2.ts b/examples/fapi2-message-signing.ts
index e49247d..5857c0c 100644
index bba1f24..b16f16f 100644
--- a/examples/fapi2.ts
+++ b/examples/fapi2-message-signing.ts
@@ -25,6 +25,11 @@ let DPoPKeys!: oauth.CryptoKeyPair
Expand Down Expand Up @@ -45,7 +45,7 @@ index e49247d..5857c0c 100644

const pushedAuthorizationRequest = () =>
oauth.pushedAuthorizationRequest(as, client, clientAuth, params, {
@@ -92,7 +108,7 @@ let request_uri: string
@@ -90,7 +106,7 @@ let request_uri: string
let access_token: string
{
const currentUrl: URL = getCurrentUrl()
Expand All @@ -54,16 +54,16 @@ index e49247d..5857c0c 100644

const authorizationCodeGrantRequest = () =>
oauth.authorizationCodeGrantRequest(
@@ -108,7 +124,7 @@ let access_token: string
@@ -106,7 +122,7 @@ let access_token: string
let response = await authorizationCodeGrantRequest()

const processAuthorizationCodeResponse = () =>
- oauth.processAuthorizationCodeResponse(as, client, response)
+ oauth.processAuthorizationCodeResponse(as, client, response, true)

let result = await processAuthorizationCodeResponse().catch(async (err) => {
if (err instanceof oauth.ResponseBodyError) {
@@ -121,6 +137,9 @@ let access_token: string
if (oauth.isDPoPNonceError(err)) {
@@ -117,6 +133,9 @@ let access_token: string
throw err
})

Expand Down
33 changes: 11 additions & 22 deletions examples/fapi2-message-signing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,10 @@ let request_uri: string
const processPushedAuthorizationResponse = () =>
oauth.processPushedAuthorizationResponse(as, client, response)
let result = await processPushedAuthorizationResponse().catch(async (err) => {
if (err instanceof oauth.ResponseBodyError) {
if (result.error === 'use_dpop_nonce') {
// the AS-signalled nonce is now cached, retrying
response = await pushedAuthorizationRequest()
return processPushedAuthorizationResponse()
}
if (oauth.isDPoPNonceError(err)) {
// the AS-signalled nonce is now cached, retrying
response = await pushedAuthorizationRequest()
return processPushedAuthorizationResponse()
}
throw err
})
Expand Down Expand Up @@ -127,12 +125,10 @@ let access_token: string
oauth.processAuthorizationCodeResponse(as, client, response, true)

let result = await processAuthorizationCodeResponse().catch(async (err) => {
if (err instanceof oauth.ResponseBodyError) {
if (result.error === 'use_dpop_nonce') {
// the AS-signalled nonce is now cached, retrying
response = await authorizationCodeGrantRequest()
return processAuthorizationCodeResponse()
}
if (oauth.isDPoPNonceError(err)) {
// the AS-signalled nonce is now cached, retrying
response = await authorizationCodeGrantRequest()
return processAuthorizationCodeResponse()
}
throw err
})
Expand All @@ -156,16 +152,9 @@ let access_token: string
{ DPoP },
)
let response = await protectedResourceRequest().catch((err) => {
if (err instanceof oauth.WWWAuthenticateChallengeError) {
const { 0: challenge, length } = err.cause
if (
length === 1 &&
challenge.scheme === 'dpop' &&
challenge.parameters.error === 'use_dpop_nonce'
) {
// the AS-signalled nonce is now cached, retrying
return protectedResourceRequest()
}
if (oauth.isDPoPNonceError(err)) {
// the RS-signalled nonce is now cached, retrying
return protectedResourceRequest()
}
throw err
})
Expand Down
41 changes: 15 additions & 26 deletions examples/fapi2.diff
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
diff --git a/examples/oauth.ts b/examples/fapi2.ts
index d55e62d..e49247d 100644
index d55e62d..bba1f24 100644
--- a/examples/oauth.ts
+++ b/examples/fapi2.ts
@@ -9,12 +9,22 @@ let algorithm!:
Expand All @@ -26,7 +26,7 @@ index d55e62d..e49247d 100644

// End of prerequisites

@@ -23,36 +33,56 @@ const as = await oauth
@@ -23,36 +33,54 @@ const as = await oauth
.then((response) => oauth.processDiscoveryResponse(issuer, response))

const client: oauth.Client = { client_id }
Expand Down Expand Up @@ -66,12 +66,10 @@ index d55e62d..e49247d 100644
+ const processPushedAuthorizationResponse = () =>
+ oauth.processPushedAuthorizationResponse(as, client, response)
+ let result = await processPushedAuthorizationResponse().catch(async (err) => {
+ if (err instanceof oauth.ResponseBodyError) {
+ if (result.error === 'use_dpop_nonce') {
+ // the AS-signalled nonce is now cached, retrying
+ response = await pushedAuthorizationRequest()
+ return processPushedAuthorizationResponse()
+ }
+ if (oauth.isDPoPNonceError(err)) {
+ // the AS-signalled nonce is now cached, retrying
+ response = await pushedAuthorizationRequest()
+ return processPushedAuthorizationResponse()
+ }
+ throw err
+ })
Expand Down Expand Up @@ -101,7 +99,7 @@ index d55e62d..e49247d 100644

// now redirect the user to authorizationUrl.href
}
@@ -62,18 +92,34 @@ let state: string | undefined
@@ -62,18 +90,32 @@ let state: string | undefined
let access_token: string
{
const currentUrl: URL = getCurrentUrl()
Expand Down Expand Up @@ -134,19 +132,17 @@ index d55e62d..e49247d 100644

- const result = await oauth.processAuthorizationCodeResponse(as, client, response)
+ let result = await processAuthorizationCodeResponse().catch(async (err) => {
+ if (err instanceof oauth.ResponseBodyError) {
+ if (result.error === 'use_dpop_nonce') {
+ // the AS-signalled nonce is now cached, retrying
+ response = await authorizationCodeGrantRequest()
+ return processAuthorizationCodeResponse()
+ }
+ if (oauth.isDPoPNonceError(err)) {
+ // the AS-signalled nonce is now cached, retrying
+ response = await authorizationCodeGrantRequest()
+ return processAuthorizationCodeResponse()
+ }
+ throw err
+ })

console.log('Access Token Response', result)
;({ access_token } = result)
@@ -81,11 +127,29 @@ let access_token: string
@@ -81,11 +123,22 @@ let access_token: string

// Protected Resource Request
{
Expand All @@ -165,16 +161,9 @@ index d55e62d..e49247d 100644
+ { DPoP },
+ )
+ let response = await protectedResourceRequest().catch((err) => {
+ if (err instanceof oauth.WWWAuthenticateChallengeError) {
+ const { 0: challenge, length } = err.cause
+ if (
+ length === 1 &&
+ challenge.scheme === 'dpop' &&
+ challenge.parameters.error === 'use_dpop_nonce'
+ ) {
+ // the AS-signalled nonce is now cached, retrying
+ return protectedResourceRequest()
+ }
+ if (oauth.isDPoPNonceError(err)) {
+ // the RS-signalled nonce is now cached, retrying
+ return protectedResourceRequest()
+ }
+ throw err
+ })
Expand Down
33 changes: 11 additions & 22 deletions examples/fapi2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,10 @@ let request_uri: string
const processPushedAuthorizationResponse = () =>
oauth.processPushedAuthorizationResponse(as, client, response)
let result = await processPushedAuthorizationResponse().catch(async (err) => {
if (err instanceof oauth.ResponseBodyError) {
if (result.error === 'use_dpop_nonce') {
// the AS-signalled nonce is now cached, retrying
response = await pushedAuthorizationRequest()
return processPushedAuthorizationResponse()
}
if (oauth.isDPoPNonceError(err)) {
// the AS-signalled nonce is now cached, retrying
response = await pushedAuthorizationRequest()
return processPushedAuthorizationResponse()
}
throw err
})
Expand Down Expand Up @@ -111,12 +109,10 @@ let access_token: string
oauth.processAuthorizationCodeResponse(as, client, response)

let result = await processAuthorizationCodeResponse().catch(async (err) => {
if (err instanceof oauth.ResponseBodyError) {
if (result.error === 'use_dpop_nonce') {
// the AS-signalled nonce is now cached, retrying
response = await authorizationCodeGrantRequest()
return processAuthorizationCodeResponse()
}
if (oauth.isDPoPNonceError(err)) {
// the AS-signalled nonce is now cached, retrying
response = await authorizationCodeGrantRequest()
return processAuthorizationCodeResponse()
}
throw err
})
Expand All @@ -137,16 +133,9 @@ let access_token: string
{ DPoP },
)
let response = await protectedResourceRequest().catch((err) => {
if (err instanceof oauth.WWWAuthenticateChallengeError) {
const { 0: challenge, length } = err.cause
if (
length === 1 &&
challenge.scheme === 'dpop' &&
challenge.parameters.error === 'use_dpop_nonce'
) {
// the AS-signalled nonce is now cached, retrying
return protectedResourceRequest()
}
if (oauth.isDPoPNonceError(err)) {
// the RS-signalled nonce is now cached, retrying
return protectedResourceRequest()
}
throw err
})
Expand Down
Loading

0 comments on commit 06493e3

Please sign in to comment.