-
-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
29 changed files
with
1,617 additions
and
446 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,11 @@ | ||
git diff HEAD:examples/code.ts examples/dpop.ts > examples/dpop.diff | ||
git diff HEAD:examples/code.ts examples/par.ts > examples/par.diff | ||
git diff HEAD:examples/code.ts examples/private_key_jwt.ts > examples/private_key_jwt.diff | ||
git diff HEAD:examples/code.ts examples/public.ts > examples/public.diff | ||
git diff HEAD:examples/fapi2.ts examples/fapi2-message-signing.ts > examples/fapi2-message-signing.diff | ||
git diff HEAD:examples/oauth.ts examples/oidc.ts > examples/oidc.diff | ||
git diff HEAD:examples/oauth.ts examples/dpop.ts > examples/dpop.diff | ||
git diff HEAD:examples/oauth.ts examples/par.ts > examples/par.diff | ||
git diff HEAD:examples/oauth.ts examples/jar.ts > examples/jar.diff | ||
git diff HEAD:examples/oauth.ts examples/jarm.ts > examples/jarm.diff | ||
git diff HEAD:examples/oauth.ts examples/client_secret_post.ts > examples/client_secret_post.diff | ||
git diff HEAD:examples/oauth.ts examples/private_key_jwt.ts > examples/private_key_jwt.diff | ||
git diff HEAD:examples/oauth.ts examples/public.ts > examples/public.diff | ||
git diff HEAD:examples/oauth.ts examples/fapi2.ts > examples/fapi2.diff | ||
git diff HEAD:examples/oauth.ts examples/fapi1-advanced.ts > examples/fapi1-advanced.diff | ||
git diff HEAD:examples/oauth.ts examples/refresh_token.ts > examples/refresh_token.diff |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,21 @@ | ||
A collection of examples for the most common use cases. | ||
|
||
- Authorization Code Flow - OpenID Connect [source](code.ts), or plain OAuth 2 [source](oauth.ts) | ||
- Public Client Authorization Code Flow - [source](public.ts) | [diff from code flow](public.diff) | ||
- Private Key JWT Client Authentication - [source](private_key_jwt.ts) | [diff from code flow](private_key_jwt.diff) | ||
- DPoP - [source](dpop.ts) | [diff from code flow](dpop.diff) | ||
- Pushed Authorization Request (PAR) - [source](par.ts) | [diff from code flow](par.diff) | ||
- Client Credentials Grant - [source](client_credentials.ts) | ||
- Device Authorization Grant - [source](device_authorization_grant.ts) | ||
- FAPI 1.0 Advanced (Private Key JWT, MTLS, JAR) - [source](fapi1-advanced.ts) | ||
- FAPI 2.0 Security Profile (Private Key JWT, PAR, DPoP) - [source](fapi2.ts) | ||
- FAPI 2.0 Message Signing (Private Key JWT, PAR, DPoP, JAR, JARM) - [source](fapi2-message-signing.ts) | [diff from FAPI 2.0 SP](fapi2-message-signing.diff) | ||
- Authorization Code Flow (OAuth 2.0) - [source](oauth.ts) | ||
- Authorization Code Flow (OpenID Connect) - [source](oidc.ts) | [diff](oidc.diff) | ||
- Extensions | ||
- DPoP - [source](dpop.ts) | [diff](dpop.diff) | ||
- JWT Secured Authorization Request (JAR) - [source](jar.ts) | [diff](jar.diff) | ||
- JWT Secured Authorization Response Mode (JARM) - [source](jarm.ts) | [diff](jarm.diff) | ||
- Pushed Authorization Request (PAR) - [source](par.ts) | [diff](par.diff) | ||
- Client Authentication | ||
- Client Secret in HTTP Authorization Header - [source](oauth.ts) | ||
- Client Secret in HTTP Body - [source](client_secret_post.ts) | [diff](client_secret_post.diff) | ||
- Private Key JWT Client Authentication - [source](private_key_jwt.ts) | [diff](private_key_jwt.diff) | ||
- Public Client - [source](public.ts) | [diff](public.diff) | ||
- Other Grants | ||
- Client Credentials Grant - [source](client_credentials.ts) | ||
- Device Authorization Grant - [source](device_authorization_grant.ts) | ||
- Refresh Token Grant - [source](refresh_token.ts) | [diff](refresh_token.diff) | ||
- FAPI | ||
- FAPI 1.0 Advanced (Private Key JWT, MTLS, JAR) - [source](fapi1-advanced.ts) | [diff](fapi1-advanced.diff) | ||
- FAPI 2.0 Security Profile (Private Key JWT, PAR, DPoP) - [source](fapi2.ts) | [diff](fapi2.diff) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
diff --git a/examples/oauth.ts b/examples/client_secret_post.ts | ||
index cc6d632..df5aefd 100644 | ||
--- a/examples/oauth.ts | ||
+++ b/examples/client_secret_post.ts | ||
@@ -24,7 +24,7 @@ const as = await oauth | ||
const client: oauth.Client = { | ||
client_id, | ||
client_secret, | ||
- token_endpoint_auth_method: 'client_secret_basic', | ||
+ token_endpoint_auth_method: 'client_secret_post', | ||
} | ||
|
||
const code_challenge_method = 'S256' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import * as oauth from '../src/index.js' // replace with an import of oauth4webapi | ||
|
||
// Prerequisites | ||
|
||
let issuer!: URL // Authorization server's Issuer Identifier URL | ||
let algorithm!: | ||
| 'oauth2' /* For .well-known/oauth-authorization-server discovery */ | ||
| 'oidc' /* For .well-known/openid-configuration discovery */ | ||
| undefined /* Defaults to 'oidc' */ | ||
let client_id!: string | ||
let client_secret!: string | ||
/** | ||
* Value used in the authorization request as redirect_uri pre-registered at the Authorization | ||
* Server. | ||
*/ | ||
let redirect_uri!: string | ||
|
||
// End of prerequisites | ||
|
||
const as = await oauth | ||
.discoveryRequest(issuer, { algorithm }) | ||
.then((response) => oauth.processDiscoveryResponse(issuer, response)) | ||
|
||
const client: oauth.Client = { | ||
client_id, | ||
client_secret, | ||
token_endpoint_auth_method: 'client_secret_post', | ||
} | ||
|
||
const code_challenge_method = 'S256' | ||
/** | ||
* The following MUST be generated for every redirect to the authorization_endpoint. You must store | ||
* the code_verifier and nonce in the end-user session such that it can be recovered as the user | ||
* gets redirected from the authorization server back to your application. | ||
*/ | ||
const code_verifier = oauth.generateRandomCodeVerifier() | ||
const code_challenge = await oauth.calculatePKCECodeChallenge(code_verifier) | ||
let state: string | undefined | ||
|
||
{ | ||
// redirect user to as.authorization_endpoint | ||
const authorizationUrl = new URL(as.authorization_endpoint!) | ||
authorizationUrl.searchParams.set('client_id', client.client_id) | ||
authorizationUrl.searchParams.set('redirect_uri', redirect_uri) | ||
authorizationUrl.searchParams.set('response_type', 'code') | ||
authorizationUrl.searchParams.set('scope', 'api:read') | ||
authorizationUrl.searchParams.set('code_challenge', code_challenge) | ||
authorizationUrl.searchParams.set('code_challenge_method', code_challenge_method) | ||
|
||
/** | ||
* We cannot be sure the AS supports PKCE so we're going to use state too. Use of PKCE is | ||
* backwards compatible even if the AS doesn't support it which is why we're using it regardless. | ||
*/ | ||
if (as.code_challenge_methods_supported?.includes('S256') !== true) { | ||
state = oauth.generateRandomState() | ||
authorizationUrl.searchParams.set('state', state) | ||
} | ||
|
||
// now redirect the user to authorizationUrl.href | ||
} | ||
|
||
// one eternity later, the user lands back on the redirect_uri | ||
// Authorization Code Grant Request & Response | ||
let access_token: string | ||
{ | ||
// @ts-expect-error | ||
const currentUrl: URL = getCurrentUrl() | ||
const params = oauth.validateAuthResponse(as, client, currentUrl, state) | ||
if (oauth.isOAuth2Error(params)) { | ||
console.error('Error Response', params) | ||
throw new Error() // Handle OAuth 2.0 redirect error | ||
} | ||
|
||
const response = await oauth.authorizationCodeGrantRequest( | ||
as, | ||
client, | ||
params, | ||
redirect_uri, | ||
code_verifier, | ||
) | ||
|
||
let challenges: oauth.WWWAuthenticateChallenge[] | undefined | ||
if ((challenges = oauth.parseWwwAuthenticateChallenges(response))) { | ||
for (const challenge of challenges) { | ||
console.error('WWW-Authenticate Challenge', challenge) | ||
} | ||
throw new Error() // Handle WWW-Authenticate Challenges as needed | ||
} | ||
|
||
const result = await oauth.processAuthorizationCodeOAuth2Response(as, client, response) | ||
if (oauth.isOAuth2Error(result)) { | ||
console.error('Error Response', result) | ||
throw new Error() // Handle OAuth 2.0 response body error | ||
} | ||
|
||
console.log('Access Token Response', result) | ||
;({ access_token } = result) | ||
} | ||
|
||
// Protected Resource Request | ||
{ | ||
const response = await oauth.protectedResourceRequest( | ||
access_token, | ||
'GET', | ||
new URL('https://rs.example.com/api'), | ||
) | ||
|
||
let challenges: oauth.WWWAuthenticateChallenge[] | undefined | ||
if ((challenges = oauth.parseWwwAuthenticateChallenges(response))) { | ||
for (const challenge of challenges) { | ||
console.error('WWW-Authenticate Challenge', challenge) | ||
} | ||
throw new Error() // Handle WWW-Authenticate Challenges as needed | ||
} | ||
|
||
console.log('Protected Resource Response', await response.json()) | ||
} |
Oops, something went wrong.