oauth4webapi
Advanced tools
Comparing version 2.0.6 to 2.1.0
@@ -48,27 +48,63 @@ type JsonObject = { | ||
* | ||
* @example CryptoKey algorithm for the `PS256` JWS Algorithm Identifier | ||
* @example CryptoKey algorithm for the `PS256`, `PS384`, or `PS512` JWS Algorithm Identifiers | ||
* | ||
* ```ts | ||
* interface Ps256Algorithm extends RsaHashedKeyAlgorithm { | ||
* interface RSAPSSAlgorithm extends RsaHashedKeyAlgorithm { | ||
* name: 'RSA-PSS' | ||
* hash: { name: 'SHA-256' | 'SHA-384' | 'SHA-512' } | ||
* } | ||
* | ||
* interface PS256 extends RSAPSSAlgorithm { | ||
* hash: { name: 'SHA-256' } | ||
* } | ||
* | ||
* interface PS384 extends RSAPSSAlgorithm { | ||
* hash: { name: 'SHA-384' } | ||
* } | ||
* | ||
* interface PS512 extends RSAPSSAlgorithm { | ||
* hash: { name: 'SHA-512' } | ||
* } | ||
* ``` | ||
* | ||
* @example CryptoKey algorithm for the `ES256` JWS Algorithm Identifier | ||
* @example CryptoKey algorithm for the `ES256`, `ES384`, or `ES512` JWS Algorithm Identifiers | ||
* | ||
* ```ts | ||
* interface Es256Algorithm extends EcKeyAlgorithm { | ||
* interface ECDSAAlgorithm extends EcKeyAlgorithm { | ||
* name: 'ECDSA' | ||
* namedCurve: 'P-256' | 'P-384' | 'P-521' | ||
* } | ||
* | ||
* interface ES256 extends ECDSAAlgorithm { | ||
* namedCurve: 'P-256' | ||
* } | ||
* | ||
* interface ES384 extends ECDSAAlgorithm { | ||
* namedCurve: 'P-384' | ||
* } | ||
* | ||
* interface ES512 extends ECDSAAlgorithm { | ||
* namedCurve: 'P-521' | ||
* } | ||
* ``` | ||
* | ||
* @example CryptoKey algorithm for the `RS256` JWS Algorithm Identifier | ||
* @example CryptoKey algorithm for the `RS256`, `RS384`, or `RS512` JWS Algorithm Identifiers | ||
* | ||
* ```ts | ||
* interface Rs256Algorithm extends RsaHashedKeyAlgorithm { | ||
* interface ECDSAAlgorithm extends RsaHashedKeyAlgorithm { | ||
* name: 'RSASSA-PKCS1-v1_5' | ||
* hash: { name: 'SHA-256' | 'SHA-384' | 'SHA-512' } | ||
* } | ||
* | ||
* interface RS256 extends ECDSAAlgorithm { | ||
* hash: { name: 'SHA-256' } | ||
* } | ||
* | ||
* interface RS384 extends ECDSAAlgorithm { | ||
* hash: { name: 'SHA-384' } | ||
* } | ||
* | ||
* interface RS512 extends ECDSAAlgorithm { | ||
* hash: { name: 'SHA-512' } | ||
* } | ||
* ``` | ||
@@ -83,8 +119,8 @@ * | ||
* ```ts | ||
* interface EdDSAAlgorithm extends KeyAlgorithm { | ||
* name: 'Ed25519' | ||
* interface EdDSA extends KeyAlgorithm { | ||
* name: 'Ed25519' | 'Ed448' | ||
* } | ||
* ``` | ||
*/ | ||
export type JWSAlgorithm = 'PS256' | 'ES256' | 'RS256' | 'EdDSA'; | ||
export type JWSAlgorithm = 'PS256' | 'ES256' | 'RS256' | 'EdDSA' | 'ES384' | 'PS384' | 'RS384' | 'ES512' | 'PS512' | 'RS512'; | ||
/** | ||
@@ -1087,2 +1123,4 @@ * Authorization Server Metadata | ||
modulusLength?: number; | ||
/** (EdDSA algorithms only) The EdDSA sub-type. Default is `Ed25519`. */ | ||
crv?: 'Ed25519' | 'Ed448'; | ||
} | ||
@@ -1089,0 +1127,0 @@ /** |
let USER_AGENT; | ||
if (typeof navigator === 'undefined' || !navigator.userAgent?.startsWith?.('Mozilla/5.0 ')) { | ||
const NAME = 'oauth4webapi'; | ||
const VERSION = 'v2.0.6'; | ||
const VERSION = 'v2.1.0'; | ||
USER_AGENT = `${NAME}/${VERSION}`; | ||
@@ -116,3 +116,14 @@ } | ||
} | ||
const SUPPORTED_JWS_ALGS = ['PS256', 'ES256', 'RS256', 'EdDSA']; | ||
const SUPPORTED_JWS_ALGS = [ | ||
'PS256', | ||
'ES256', | ||
'RS256', | ||
'PS384', | ||
'ES384', | ||
'RS384', | ||
'PS512', | ||
'ES512', | ||
'RS512', | ||
'EdDSA', | ||
]; | ||
function processDpopNonce(response) { | ||
@@ -267,2 +278,6 @@ const url = new URL(response.url); | ||
return 'PS256'; | ||
case 'SHA-384': | ||
return 'PS384'; | ||
case 'SHA-512': | ||
return 'PS512'; | ||
default: | ||
@@ -276,2 +291,6 @@ throw new UnsupportedOperationError('unsupported RsaHashedKeyAlgorithm hash name'); | ||
return 'RS256'; | ||
case 'SHA-384': | ||
return 'RS384'; | ||
case 'SHA-512': | ||
return 'RS512'; | ||
default: | ||
@@ -285,2 +304,6 @@ throw new UnsupportedOperationError('unsupported RsaHashedKeyAlgorithm hash name'); | ||
return 'ES256'; | ||
case 'P-384': | ||
return 'ES384'; | ||
case 'P-521': | ||
return 'ES512'; | ||
default: | ||
@@ -290,3 +313,3 @@ throw new UnsupportedOperationError('unsupported EcKeyAlgorithm namedCurve'); | ||
} | ||
function determineJWSAlgorithm(key) { | ||
function keyToJws(key) { | ||
switch (key.algorithm.name) { | ||
@@ -300,2 +323,3 @@ case 'RSA-PSS': | ||
case 'Ed25519': | ||
case 'Ed448': | ||
return 'EdDSA'; | ||
@@ -323,3 +347,3 @@ default: | ||
return jwt({ | ||
alg: determineJWSAlgorithm(key), | ||
alg: keyToJws(key), | ||
kid, | ||
@@ -408,3 +432,3 @@ }, clientAssertion(as, client), key); | ||
const input = `${b64u(buf(JSON.stringify(header)))}.${b64u(buf(JSON.stringify(claimsSet)))}`; | ||
const signature = b64u(await crypto.subtle.sign(subtleAlgorithm(key), key, buf(input))); | ||
const signature = b64u(await crypto.subtle.sign(keyToSubtle(key), key, buf(input))); | ||
return `${input}.${signature}`; | ||
@@ -456,3 +480,3 @@ } | ||
return jwt({ | ||
alg: determineJWSAlgorithm(key), | ||
alg: keyToJws(key), | ||
typ: 'oauth-authz-req+jwt', | ||
@@ -478,3 +502,3 @@ kid, | ||
const proof = await jwt({ | ||
alg: determineJWSAlgorithm(privateKey), | ||
alg: keyToJws(privateKey), | ||
typ: 'dpop+jwt', | ||
@@ -720,3 +744,5 @@ jwk: await publicJwk(publicKey), | ||
case alg === 'ES256' && jwk.crv !== 'P-256': | ||
case alg === 'EdDSA' && jwk.crv !== 'Ed25519': | ||
case alg === 'ES384' && jwk.crv !== 'P-384': | ||
case alg === 'ES512' && jwk.crv !== 'P-521': | ||
case alg === 'EdDSA' && !(jwk.crv === 'Ed25519' || jwk.crv === 'Ed448'): | ||
return false; | ||
@@ -1224,15 +1250,39 @@ } | ||
} | ||
function subtleAlgorithm(key) { | ||
function ecdsaHashName(namedCurve) { | ||
switch (namedCurve) { | ||
case 'P-256': | ||
return 'SHA-256'; | ||
case 'P-384': | ||
return 'SHA-384'; | ||
case 'P-521': | ||
return 'SHA-512'; | ||
default: | ||
throw new UnsupportedOperationError(); | ||
} | ||
} | ||
function keyToSubtle(key) { | ||
switch (key.algorithm.name) { | ||
case 'ECDSA': | ||
return { name: key.algorithm.name, hash: { name: 'SHA-256' } }; | ||
case 'RSA-PSS': | ||
checkRsaKeyAlgorithm(key.algorithm); | ||
return { | ||
name: key.algorithm.name, | ||
saltLength: 256 >> 3, | ||
hash: { name: ecdsaHashName(key.algorithm.namedCurve) }, | ||
}; | ||
case 'RSA-PSS': { | ||
checkRsaKeyAlgorithm(key.algorithm); | ||
switch (key.algorithm.hash.name) { | ||
case 'SHA-256': | ||
case 'SHA-384': | ||
case 'SHA-512': | ||
return { | ||
name: key.algorithm.name, | ||
saltLength: parseInt(key.algorithm.hash.name.slice(-3), 10) >> 3, | ||
}; | ||
default: | ||
throw new UnsupportedOperationError(); | ||
} | ||
} | ||
case 'RSASSA-PKCS1-v1_5': | ||
checkRsaKeyAlgorithm(key.algorithm); | ||
return { name: key.algorithm.name }; | ||
case 'Ed448': | ||
case 'Ed25519': | ||
@@ -1270,3 +1320,3 @@ return { name: key.algorithm.name }; | ||
const input = `${protectedHeader}.${payload}`; | ||
const verified = await crypto.subtle.verify(subtleAlgorithm(key), key, signature, buf(input)); | ||
const verified = await crypto.subtle.verify(keyToSubtle(key), key, signature, buf(input)); | ||
if (!verified) { | ||
@@ -1432,23 +1482,35 @@ throw new OPE('JWT signature verification failed'); | ||
} | ||
async function importJwk(alg, jwk) { | ||
const { ext, key_ops, use, ...key } = jwk; | ||
let algorithm; | ||
function algToSubtle(alg, crv) { | ||
switch (alg) { | ||
case 'PS256': | ||
algorithm = { name: 'RSA-PSS', hash: { name: 'SHA-256' } }; | ||
break; | ||
case 'PS384': | ||
case 'PS512': | ||
return { name: 'RSA-PSS', hash: { name: `SHA-${alg.slice(-3)}` } }; | ||
case 'RS256': | ||
algorithm = { name: 'RSASSA-PKCS1-v1_5', hash: { name: 'SHA-256' } }; | ||
break; | ||
case 'RS384': | ||
case 'RS512': | ||
return { name: 'RSASSA-PKCS1-v1_5', hash: { name: `SHA-${alg.slice(-3)}` } }; | ||
case 'ES256': | ||
algorithm = { name: 'ECDSA', namedCurve: 'P-256' }; | ||
break; | ||
case 'EdDSA': | ||
algorithm = { name: 'Ed25519' }; | ||
break; | ||
case 'ES384': | ||
return { name: 'ECDSA', namedCurve: `P-${alg.slice(-3)}` }; | ||
case 'ES512': | ||
return { name: 'ECDSA', namedCurve: 'P-521' }; | ||
case 'EdDSA': { | ||
switch (crv) { | ||
case 'Ed25519': | ||
return { name: 'Ed25519' }; | ||
case 'Ed448': | ||
return { name: 'Ed448' }; | ||
default: | ||
throw new UnsupportedOperationError(); | ||
} | ||
} | ||
default: | ||
throw new UnsupportedOperationError(); | ||
} | ||
return crypto.subtle.importKey('jwk', key, algorithm, true, ['verify']); | ||
} | ||
async function importJwk(alg, jwk) { | ||
const { ext, key_ops, use, ...key } = jwk; | ||
return crypto.subtle.importKey('jwk', key, algToSubtle(alg, jwk.crv), true, ['verify']); | ||
} | ||
export async function deviceAuthorizationRequest(as, client, parameters, options) { | ||
@@ -1529,33 +1591,13 @@ assertAs(as); | ||
export async function generateKeyPair(alg, options) { | ||
let algorithm; | ||
if (!validateString(alg)) { | ||
throw new TypeError('"alg" must be a non-empty string'); | ||
} | ||
switch (alg) { | ||
case 'PS256': | ||
algorithm = { | ||
name: 'RSA-PSS', | ||
hash: { name: 'SHA-256' }, | ||
modulusLength: options?.modulusLength ?? 2048, | ||
publicExponent: new Uint8Array([0x01, 0x00, 0x01]), | ||
}; | ||
break; | ||
case 'RS256': | ||
algorithm = { | ||
name: 'RSASSA-PKCS1-v1_5', | ||
hash: { name: 'SHA-256' }, | ||
modulusLength: options?.modulusLength ?? 2048, | ||
publicExponent: new Uint8Array([0x01, 0x00, 0x01]), | ||
}; | ||
break; | ||
case 'ES256': | ||
algorithm = { name: 'ECDSA', namedCurve: 'P-256' }; | ||
break; | ||
case 'EdDSA': | ||
algorithm = { name: 'Ed25519' }; | ||
break; | ||
default: | ||
throw new UnsupportedOperationError(); | ||
const algorithm = algToSubtle(alg, alg === 'EdDSA' ? options?.crv ?? 'Ed25519' : undefined); | ||
if (alg.startsWith('PS') || alg.startsWith('RS')) { | ||
Object.assign(algorithm, { | ||
modulusLength: options?.modulusLength ?? 2048, | ||
publicExponent: new Uint8Array([0x01, 0x00, 0x01]), | ||
}); | ||
} | ||
return (crypto.subtle.generateKey(algorithm, options?.extractable ?? false, ['sign', 'verify'])); | ||
} |
{ | ||
"name": "oauth4webapi", | ||
"version": "2.0.6", | ||
"version": "2.1.0", | ||
"description": "OAuth 2 / OpenID Connect for Web Platform API JavaScript runtimes", | ||
@@ -69,4 +69,4 @@ "keywords": [ | ||
"ava": "^5.1.0", | ||
"edge-runtime": "^2.0.2", | ||
"esbuild": "^0.16.1", | ||
"edge-runtime": "^2.0.4", | ||
"esbuild": "^0.17.0", | ||
"jose": "^4.11.1", | ||
@@ -73,0 +73,0 @@ "patch-package": "^6.5.0", |
@@ -42,3 +42,3 @@ # OAuth 2 / OpenID Connect for Web Platform API JavaScript runtimes | ||
```js | ||
import * as oauth2 from 'https://deno.land/x/oauth4webapi@v2.0.6/mod.ts' | ||
import * as oauth2 from 'https://deno.land/x/oauth4webapi@v2.1.0/mod.ts' | ||
``` | ||
@@ -45,0 +45,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
120822
2718