Skip to content

Commit

Permalink
refactor: better type for oauth.customFetch implementations, updated …
Browse files Browse the repository at this point in the history
…examples
  • Loading branch information
panva committed Oct 7, 2024
1 parent c8f78ab commit a06efb5
Show file tree
Hide file tree
Showing 32 changed files with 215 additions and 185 deletions.
2 changes: 1 addition & 1 deletion conformance/runner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ export const flow = (options?: MacroOptions) => {
authorizationUrl.searchParams.set('response_type', response_type)
}

let DPoP!: CryptoKeyPair
let DPoP!: oauth.CryptoKeyPairType
if (usesDpop(variant)) {
DPoP = await oauth.generateKeyPair(JWS_ALGORITHM as oauth.JWSAlgorithm)
authorizationUrl.searchParams.set(
Expand Down
2 changes: 1 addition & 1 deletion examples/client_credentials.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as oauth from '../src/index.js' // replace with an import of oauth4webapi
import * as oauth from 'oauth4webapi'

// Prerequisites

Expand Down
2 changes: 1 addition & 1 deletion examples/client_secret_post.diff
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
diff --git a/examples/oauth.ts b/examples/client_secret_post.ts
index a3321ad..18a90ba 100644
index a3b923c..6185acc 100644
--- a/examples/oauth.ts
+++ b/examples/client_secret_post.ts
@@ -24,7 +24,7 @@ const as = await oauth
Expand Down
4 changes: 2 additions & 2 deletions examples/client_secret_post.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as oauth from '../src/index.js' // replace with an import of oauth4webapi
import * as oauth from 'oauth4webapi'

// Prerequisites

let getCurrentUrl!: (...args: any) => URL
let issuer!: URL // Authorization server's Issuer Identifier URL
let algorithm!:
| 'oauth2' /* For .well-known/oauth-authorization-server discovery */
Expand Down Expand Up @@ -63,7 +64,6 @@ let state: string | undefined
// Authorization Code Grant Request & Response
let access_token: string
{
// @ts-expect-error
const currentUrl: URL = getCurrentUrl()
const params = oauth.validateAuthResponse(as, client, currentUrl, state)

Expand Down
2 changes: 1 addition & 1 deletion examples/device_authorization_grant.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as oauth from '../src/index.js' // replace with an import of oauth4webapi
import * as oauth from 'oauth4webapi'

// Prerequisites

Expand Down
4 changes: 2 additions & 2 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 a3321ad..7152d81 100644
index a3b923c..412494c 100644
--- a/examples/oauth.ts
+++ b/examples/dpop.ts
@@ -14,6 +14,12 @@ let client_secret!: string
Expand All @@ -11,7 +11,7 @@ index a3321ad..7152d81 100644
+ * session. In the browser environment you shall use IndexedDB to persist the generated
+ * CryptoKeyPair.
+ */
+let DPoP!: CryptoKeyPair
+let DPoP!: oauth.CryptoKeyPairType

// End of prerequisites

Expand Down
6 changes: 3 additions & 3 deletions examples/dpop.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as oauth from '../src/index.js' // replace with an import of oauth4webapi
import * as oauth from 'oauth4webapi'

// Prerequisites

let getCurrentUrl!: (...args: any) => URL
let issuer!: URL // Authorization server's Issuer Identifier URL
let algorithm!:
| 'oauth2' /* For .well-known/oauth-authorization-server discovery */
Expand All @@ -19,7 +20,7 @@ let redirect_uri!: string
* session. In the browser environment you shall use IndexedDB to persist the generated
* CryptoKeyPair.
*/
let DPoP!: CryptoKeyPair
let DPoP!: oauth.CryptoKeyPairType

// End of prerequisites

Expand Down Expand Up @@ -69,7 +70,6 @@ let state: string | undefined
// Authorization Code Grant Request & Response
let access_token: string
{
// @ts-expect-error
const currentUrl: URL = getCurrentUrl()
const params = oauth.validateAuthResponse(as, client, currentUrl, state)

Expand Down
54 changes: 25 additions & 29 deletions examples/fapi1-advanced.diff
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
diff --git a/examples/oauth.ts b/examples/fapi1-advanced.ts
index a3321ad..bcfb028 100644
index a3b923c..32526fa 100644
--- a/examples/oauth.ts
+++ b/examples/fapi1-advanced.ts
@@ -1,3 +1,4 @@
+import * as undici from 'undici'
import * as oauth from '../src/index.js' // replace with an import of oauth4webapi
import * as oauth from 'oauth4webapi'

// Prerequisites
@@ -8,12 +9,30 @@ let algorithm!:
| 'oidc' /* For .well-known/openid-configuration discovery */
Expand All @@ -30,24 +30,24 @@ index a3321ad..bcfb028 100644
+ * A key that is pre-registered at the Authorization Server that the client is supposed to sign its
+ * Request Objects with.
+ */
+let jarPrivateKey!: CryptoKey
+let jarPrivateKey!: oauth.CryptoKeyType
+/**
+ * A key that the client has pre-registered at the Authorization Server for use with Private Key JWT
+ * client authentication method.
+ */
+let clientPrivateKey!: CryptoKey
+let clientPrivateKey!: oauth.CryptoKeyType

// End of prerequisites

@@ -23,8 +42,7 @@ const as = await oauth

const client: oauth.Client = {
client_id,
- client_secret,
- token_endpoint_auth_method: 'client_secret_basic',
+ token_endpoint_auth_method: 'private_key_jwt',
}

const code_challenge_method = 'S256'
@@ -33,39 +51,46 @@ const code_challenge_method = 'S256'
* the code_verifier and nonce in the end-user session such that it can be recovered as the user
Expand All @@ -71,7 +71,7 @@ index a3321ad..bcfb028 100644
+
+ request = await oauth.issueRequestObject(as, client, params, jarPrivateKey)
+}

{
// redirect user to as.authorization_endpoint
const authorizationUrl = new URL(as.authorization_endpoint!)
Expand All @@ -91,16 +91,16 @@ index a3321ad..bcfb028 100644
- authorizationUrl.searchParams.set('state', state)
- }
+ authorizationUrl.searchParams.set('request', request)

// now redirect the user to authorizationUrl.href
}

// one eternity later, the user lands back on the redirect_uri
+// Detached Signature ID Token Validation
// Authorization Code Grant Request & Response
let access_token: string
{
// @ts-expect-error

- const currentUrl: URL = getCurrentUrl()
- const params = oauth.validateAuthResponse(as, client, currentUrl, state)
+ const authorizationResponse: URLSearchParams | URL = getAuthorizationResponseOrURLWithFragment()
Expand All @@ -110,20 +110,18 @@ index a3321ad..bcfb028 100644
+ authorizationResponse,
+ nonce,
+ )

const response = await oauth.authorizationCodeGrantRequest(
as,
@@ -73,9 +98,28 @@ let access_token: string
@@ -73,9 +98,26 @@ let access_token: string
params,
redirect_uri,
code_verifier,
+ {
+ clientPrivateKey,
+ // @ts-expect-error
+ [oauth.customFetch]: (...args) => {
+ // @ts-expect-error
+ return undici.fetch(args[0], {
+ ...args[1],
+ [oauth.customFetch]: (url, init) => {
+ return undici.fetch(url, {
+ ...init,
+ dispatcher: new undici.Agent({
+ connect: {
+ key: mtlsClientKey,
Expand All @@ -134,27 +132,25 @@ index a3321ad..bcfb028 100644
+ },
+ },
)

- const result = await oauth.processAuthorizationCodeOAuth2Response(as, client, response)
+ const result = await oauth.processAuthorizationCodeOpenIDResponse(as, client, response)
+
+ // Check ID Token signature for non-repudiation purposes
+ await oauth.validateIdTokenSignature(as, result)

console.log('Access Token Response', result)
;({ access_token } = result)
@@ -87,6 +131,23 @@ let access_token: string
@@ -87,6 +129,21 @@ let access_token: string
access_token,
'GET',
new URL('https://rs.example.com/api'),
+ undefined,
+ undefined,
+ {
+ // @ts-expect-error
+ [oauth.customFetch]: (...args) => {
+ // @ts-expect-error
+ return undici.fetch(args[0], {
+ ...args[1],
+ [oauth.customFetch]: (url, init) => {
+ return undici.fetch(url, {
+ ...init,
+ dispatcher: new undici.Agent({
+ connect: {
+ key: mtlsClientKey,
Expand All @@ -165,5 +161,5 @@ index a3321ad..bcfb028 100644
+ },
+ },
)

console.log('Protected Resource Response', await response.json())
24 changes: 10 additions & 14 deletions examples/fapi1-advanced.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import * as undici from 'undici'
import * as oauth from '../src/index.js' // replace with an import of oauth4webapi
import * as oauth from 'oauth4webapi'

// Prerequisites

let getAuthorizationResponseOrURLWithFragment!: (...args: any) => URL
let issuer!: URL // Authorization server's Issuer Identifier URL
let algorithm!:
| 'oauth2' /* For .well-known/oauth-authorization-server discovery */
Expand All @@ -27,12 +28,12 @@ let mtlsClientCertificate!: string
* A key that is pre-registered at the Authorization Server that the client is supposed to sign its
* Request Objects with.
*/
let jarPrivateKey!: CryptoKey
let jarPrivateKey!: oauth.CryptoKeyType
/**
* A key that the client has pre-registered at the Authorization Server for use with Private Key JWT
* client authentication method.
*/
let clientPrivateKey!: CryptoKey
let clientPrivateKey!: oauth.CryptoKeyType

// End of prerequisites

Expand Down Expand Up @@ -83,7 +84,6 @@ let request: string
// Authorization Code Grant Request & Response
let access_token: string
{
// @ts-expect-error
const authorizationResponse: URLSearchParams | URL = getAuthorizationResponseOrURLWithFragment()
const params = await oauth.validateDetachedSignatureResponse(
as,
Expand All @@ -100,11 +100,9 @@ let access_token: string
code_verifier,
{
clientPrivateKey,
// @ts-expect-error
[oauth.customFetch]: (...args) => {
// @ts-expect-error
return undici.fetch(args[0], {
...args[1],
[oauth.customFetch]: (url, init) => {
return undici.fetch(url, {
...init,
dispatcher: new undici.Agent({
connect: {
key: mtlsClientKey,
Expand Down Expand Up @@ -134,11 +132,9 @@ let access_token: string
undefined,
undefined,
{
// @ts-expect-error
[oauth.customFetch]: (...args) => {
// @ts-expect-error
return undici.fetch(args[0], {
...args[1],
[oauth.customFetch]: (url, init) => {
return undici.fetch(url, {
...init,
dispatcher: new undici.Agent({
connect: {
key: mtlsClientKey,
Expand Down
28 changes: 14 additions & 14 deletions examples/fapi2-message-signing.diff
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
diff --git a/examples/fapi2.ts b/examples/fapi2-message-signing.ts
index 732a72d..cb9a00a 100644
index ca2ed9b..968eac8 100644
--- a/examples/fapi2.ts
+++ b/examples/fapi2-message-signing.ts
@@ -24,6 +24,11 @@ let DPoP!: CryptoKeyPair
@@ -24,6 +24,11 @@ let DPoP!: oauth.CryptoKeyPairType
* client authentication method.
*/
let clientPrivateKey!: CryptoKey
let clientPrivateKey!: oauth.CryptoKeyType
+/**
+ * A key that is pre-registered at the Authorization Server that the client is supposed to sign its
+ * Request Objects with.
+ */
+let jarPrivateKey!: CryptoKey
+let jarPrivateKey!: oauth.CryptoKeyType

// End of prerequisites

@@ -45,8 +50,8 @@ const code_challenge_method = 'S256'
const code_verifier = oauth.generateRandomCodeVerifier()
const code_challenge = await oauth.calculatePKCECodeChallenge(code_verifier)

-// Pushed Authorization Request & Response (PAR)
-let request_uri: string
+// Signed Request Object (JAR)
Expand All @@ -42,26 +42,26 @@ index 732a72d..cb9a00a 100644
+ const params = new URLSearchParams()
+ params.set('client_id', client.client_id)
+ params.set('request', request)

const pushedAuthorizationRequest = () =>
oauth.pushedAuthorizationRequest(as, client, params, {
@@ -94,27 +110,30 @@ let access_token: string
{
// @ts-expect-error

const currentUrl: URL = getCurrentUrl()
- const params = oauth.validateAuthResponse(as, client, currentUrl)
+ const params = await oauth.validateJwtAuthResponse(as, client, currentUrl)

const authorizationCodeGrantRequest = () =>
oauth.authorizationCodeGrantRequest(as, client, params, redirect_uri, code_verifier, { DPoP })

let response = await authorizationCodeGrantRequest()

- const processAuthorizationCodeOAuth2Response = () =>
- oauth.processAuthorizationCodeOAuth2Response(as, client, response)
+ const processAuthorizationCodeOpenIDResponse = () =>
+ oauth.processAuthorizationCodeOpenIDResponse(as, client, response)

- let result = await processAuthorizationCodeOAuth2Response().catch(async (err) => {
+ let result = await processAuthorizationCodeOpenIDResponse().catch(async (err) => {
if (err instanceof oauth.ResponseBodyError) {
Expand All @@ -74,7 +74,7 @@ index 732a72d..cb9a00a 100644
}
throw err
})

+ // Check ID Token signature for non-repudiation purposes
+ await oauth.validateIdTokenSignature(as, result)
+
Expand Down
Loading

0 comments on commit a06efb5

Please sign in to comment.