diff --git a/examples/oauth.ts b/examples/dpop.ts index d55e62d..4cb7a95 100644 --- a/examples/oauth.ts +++ b/examples/dpop.ts @@ -15,6 +15,12 @@ let client_secret!: string * Server. */ let redirect_uri!: string +/** + * In order to take full advantage of DPoP you shall generate a random private key for every + * session. In the browser environment you shall use IndexedDB to persist the generated + * CryptoKeyPair. + */ +let DPoPKeys!: oauth.CryptoKeyPair // End of prerequisites @@ -24,6 +30,7 @@ const as = await oauth const client: oauth.Client = { client_id } const clientAuth = oauth.ClientSecretPost(client_secret) +const DPoP = oauth.DPoP(client, DPoPKeys) const code_challenge_method = 'S256' /** @@ -64,16 +71,29 @@ let access_token: string const currentUrl: URL = getCurrentUrl() const params = oauth.validateAuthResponse(as, client, currentUrl, state) - const response = await oauth.authorizationCodeGrantRequest( - as, - client, - clientAuth, - params, - redirect_uri, - code_verifier, - ) + const authorizationCodeGrantRequest = () => + oauth.authorizationCodeGrantRequest( + as, + client, + clientAuth, + params, + redirect_uri, + code_verifier, + { DPoP }, + ) + + let response = await authorizationCodeGrantRequest() + + const processAuthorizationCodeResponse = () => + oauth.processAuthorizationCodeResponse(as, client, response) - const result = await oauth.processAuthorizationCodeResponse(as, client, response) + let result = await processAuthorizationCodeResponse().catch(async (err) => { + if (oauth.isDPoPNonceError(err)) { + response = await authorizationCodeGrantRequest() + return processAuthorizationCodeResponse() + } + throw err + }) console.log('Access Token Response', result) ;({ access_token } = result) @@ -81,11 +101,22 @@ let access_token: string // Protected Resource Request { - const response = await oauth.protectedResourceRequest( - access_token, - 'GET', - new URL('https://rs.example.com/api'), - ) + const protectedResourceRequest = () => + oauth.protectedResourceRequest( + access_token, + 'GET', + new URL('https://rs.example.com/api'), + undefined, + undefined, + { DPoP }, + ) + let response = await protectedResourceRequest().catch((err) => { + if (oauth.isDPoPNonceError(err)) { + // the RS-signalled nonce is now cached, retrying + return protectedResourceRequest() + } + throw err + }) console.log('Protected Resource Response', await response.json()) }