Skip to content

Commit

Permalink
refactor!: remove client_secret_jwt
Browse files Browse the repository at this point in the history
  • Loading branch information
panva committed May 5, 2022
1 parent 3d6fc04 commit 7611169
Show file tree
Hide file tree
Showing 5 changed files with 3 additions and 114 deletions.
4 changes: 0 additions & 4 deletions .github/workflows/conformance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,6 @@ jobs:
- client_auth_type: client_secret_post
plan: oidcc-client-test-plan

# client_secret_jwt
- client_auth_type: client_secret_jwt
plan: oidcc-client-test-plan

# request_object
- request_type: request_object
plan: oidcc-client-test-plan
Expand Down
3 changes: 1 addition & 2 deletions conformance/ava.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ function needsSecret(variant: Record<string, string>) {
case undefined:
case 'client_secret_basic':
case 'client_secret_post':
case 'client_secret_jwt':
return true
default:
return false
Expand All @@ -106,7 +105,7 @@ const DEFAULTS: Record<typeof PLAN_NAME, Record<string, string>> = {
client_registration: 'static_client',
request_type: 'plain_http_request', // plain_http_request, request_object
response_type: 'code',
client_auth_type: 'client_secret_basic', // none, client_secret_basic, client_secret_post, client_secret_jwt, private_key_jwt
client_auth_type: 'client_secret_basic', // none, client_secret_basic, client_secret_post, private_key_jwt
},
'oidcc-client-basic-certification-test-plan': {
request_type: 'plain_http_request',
Expand Down
7 changes: 1 addition & 6 deletions docs/types/TokenEndpointAuthMethod.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Type alias: TokenEndpointAuthMethod

Ƭ **TokenEndpointAuthMethod**: ``"client_secret_basic"`` \| ``"client_secret_post"`` \| ``"client_secret_jwt"`` \| ``"private_key_jwt"`` \| ``"none"``
Ƭ **TokenEndpointAuthMethod**: ``"client_secret_basic"`` \| ``"client_secret_post"`` \| ``"private_key_jwt"`` \| ``"none"``

Supported Client Authentication Methods.

Expand All @@ -21,11 +21,6 @@ as `application/x-www-form-urlencoded` body parameters.
The `client_assertion` is signed using a private key supplied
as an [options parameter](../interfaces/AuthenticatedRequestOptions.md#clientprivatekey).

- **`client_secret_jwt`** uses the HTTP request body to send
[`client_id`](../interfaces/Client.md#client_id), `client_assertion_type`, and `client_assertion`
as `application/x-www-form-urlencoded` body parameters.
The `client_assertion` is signed using the [`client_secret`](../interfaces/Client.md#client_secret).

- **`none`** (public client) uses the HTTP request body to send only
[`client_id`](../interfaces/Client.md#client_id)
as `application/x-www-form-urlencoded` body parameter.
Expand Down
40 changes: 1 addition & 39 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,6 @@ export interface PrivateKey {
* The `client_assertion` is signed using a private key supplied
* as an {@link AuthenticatedRequestOptions.clientPrivateKey options parameter}.
*
* - **`client_secret_jwt`** uses the HTTP request body to send
* {@link Client.client_id `client_id`}, `client_assertion_type`, and `client_assertion`
* as `application/x-www-form-urlencoded` body parameters.
* The `client_assertion` is signed using the {@link Client.client_secret `client_secret`}.
*
* - **`none`** (public client) uses the HTTP request body to send only
* {@link Client.client_id `client_id`}
* as `application/x-www-form-urlencoded` body parameter.
Expand All @@ -66,7 +61,6 @@ export interface PrivateKey {
export type TokenEndpointAuthMethod =
| 'client_secret_basic'
| 'client_secret_post'
| 'client_secret_jwt'
| 'private_key_jwt'
| 'none'

Expand Down Expand Up @@ -1096,22 +1090,6 @@ async function privateKeyJwt(
)
}

/**
* Generates a unique client assertion to be used in HS256 `client_secret_jwt`
* authenticated requests.
*/
async function clientSecretJwt(as: AuthorizationServer, client: Client, secret: string) {
const key = await crypto.subtle.importKey(
'raw',
buf(secret),
{ name: 'HMAC', hash: 'SHA-256' },
false,
['sign'],
)

return jwt({ alg: 'HS256' }, clientAssertion(as, client), key)
}

function assertIssuer(metadata: AuthorizationServer): metadata is AuthorizationServer {
if (typeof metadata !== 'object' || metadata === null) {
throw new TypeError('"issuer" must be an object')
Expand Down Expand Up @@ -1188,16 +1166,6 @@ async function clientAuthentication(
body.set('client_secret', assertClientSecret(client.client_secret))
break
}
case 'client_secret_jwt': {
assertNoClientPrivateKey('client_secret_jwt', clientPrivateKey)
body.set('client_id', client.client_id)
body.set('client_assertion_type', 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer')
body.set(
'client_assertion',
await clientSecretJwt(as, client, assertClientSecret(client.client_secret)),
)
break
}
case 'private_key_jwt': {
assertNoClientSecret('private_key_jwt', client.client_secret)
if (clientPrivateKey === undefined) {
Expand Down Expand Up @@ -1229,7 +1197,7 @@ async function clientAuthentication(
* Minimal JWT sign() implementation.
*/
async function jwt(
header: CompactJWSHeaderParameters | ClientSecretJWTHeaderParameters,
header: CompactJWSHeaderParameters,
claimsSet: Record<string, unknown>,
key: CryptoKey,
) {
Expand Down Expand Up @@ -2358,10 +2326,6 @@ export interface IDToken extends JWTPayload {
readonly azp?: string
}

interface ClientSecretJWTHeaderParameters {
alg: 'HS256'
}

interface CompactJWSHeaderParameters {
alg: JWSAlgorithm
kid?: string
Expand Down Expand Up @@ -3060,8 +3024,6 @@ function subtleAlgorithm(key: CryptoKey): AlgorithmIdentifier | RsaPssParams | E
case 'RSASSA-PKCS1-v1_5':
checkRsaKeyAlgorithm(<RsaKeyAlgorithm>key.algorithm)
return { name: key.algorithm.name }
case 'HMAC':
return { name: key.algorithm.name }
}
throw new UnsupportedOperationError()
}
Expand Down
63 changes: 0 additions & 63 deletions test/client_auth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -351,69 +351,6 @@ for (const alg of ['RS', 'ES', 'PS'].map((s) => [`${s}256`]).flat()) {
})
}

test('client_secret_jwt', async (t) => {
const tIssuer: lib.AuthorizationServer = {
...issuer,
revocation_endpoint: endpoint('test-csjwt'),
token_endpoint: endpoint('token'),
}

t.context
.intercept({
path: '/test-csjwt',
method: 'POST',
headers(headers) {
return !('authorization' in headers)
},
body(body) {
const params = new URLSearchParams(body)
t.false(params.has('client_secret'))
t.true(params.has('client_assertion'))
t.is(params.get('client_id'), client.client_id)
t.is(
params.get('client_assertion_type'),
'urn:ietf:params:oauth:client-assertion-type:jwt-bearer',
)

const { alg } = jose.decodeProtectedHeader(params.get('client_assertion')!)
t.is(alg, 'HS256')
const assertion = jose.decodeJwt(params.get('client_assertion')!)
t.deepEqual(assertion.aud, [tIssuer.issuer, tIssuer.token_endpoint])
t.is(assertion.iss, client.client_id)
t.is(assertion.sub, client.client_id)
t.is(typeof assertion.exp, 'number')
t.is(typeof assertion.iat, 'number')
t.is(typeof assertion.nbf, 'number')
t.is(typeof assertion.jti, 'string')

return true
},
})
.reply(200, '')

await lib.revocationRequest(
tIssuer,
{
...client,
client_secret: 'foo',
token_endpoint_auth_method: 'client_secret_jwt',
},
'token',
)
await t.throwsAsync(
lib.revocationRequest(
{ ...issuer, revocation_endpoint: endpoint('test-csjwt') },
{
...client,
token_endpoint_auth_method: 'client_secret_jwt',
},
'token',
),
{ message: '"client.client_secret" property must be a non-empty string' },
)
t.pass()
})

test('none', async (t) => {
t.context
.intercept({
Expand Down

0 comments on commit 7611169

Please sign in to comment.