Skip to content

Commit

Permalink
tests: added tests that use node:crypto
Browse files Browse the repository at this point in the history
Signed-off-by: Berend Sliedrecht <[email protected]>
  • Loading branch information
berendsliedrecht committed Jul 11, 2024
1 parent df7aea3 commit 291505f
Show file tree
Hide file tree
Showing 27 changed files with 514 additions and 139 deletions.
6 changes: 5 additions & 1 deletion biome.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@
"linter": {
"enabled": true,
"rules": {
"recommended": true
"recommended": true,
"style": {
"useNodeAssertStrict": { "level": "error", "fix": "unsafe" },
"useNodejsImportProtocol": { "level": "off" }
}
}
}
}
33 changes: 10 additions & 23 deletions packages/core/__tests__/createEntityConfiguration.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import assert from 'node:assert'
import assert from 'node:assert/strict'
import { describe, it } from 'node:test'
import { createEntityConfiguration } from '../src/entityConfiguration'
import type { SignCallback } from '../src/utils'
Expand Down Expand Up @@ -27,7 +27,7 @@ describe('create entity configuration', () => {

it('should create a more complex entity configuration', async () => {
const entityConfiguration = await createEntityConfiguration({
signJwtCallback: signJwtCallback,
signJwtCallback,
claims: {
exp: 1,
iat: 1,
Expand All @@ -48,7 +48,7 @@ describe('create entity configuration', () => {
it('should not create a entity configuration when iss and sub are not equal', async () => {
await assert.rejects(
createEntityConfiguration({
signJwtCallback: signJwtCallback,
signJwtCallback,
claims: {
exp: 1,
iat: 1,
Expand All @@ -57,17 +57,14 @@ describe('create entity configuration', () => {
jwks: { keys: [{ kid: 'a', kty: 'EC' }] },
},
header: { kid: 'a', typ: 'entity-statement+jwt' },
}),
{
name: 'ZodError',
}
})
)
})

it('should not create a entity configuration when kid is not found in jwks.keys', async () => {
await assert.rejects(
createEntityConfiguration({
signJwtCallback: signJwtCallback,
signJwtCallback,
claims: {
exp: 1,
iat: 1,
Expand All @@ -76,18 +73,14 @@ describe('create entity configuration', () => {
jwks: { keys: [{ kid: 'a', kty: 'EC' }] },
},
header: { kid: 'invalid_id', typ: 'entity-statement+jwt' },
}),
{
name: 'Error',
message: "key with id: 'invalid_id' could not be found in the claims",
}
})
)
})

it("should not create a entity configuration when typ is not 'entity-statement+jwt'", async () => {
await assert.rejects(
createEntityConfiguration({
signJwtCallback: signJwtCallback,
signJwtCallback,
claims: {
exp: 1,
iat: 1,
Expand All @@ -97,17 +90,14 @@ describe('create entity configuration', () => {
},
// @ts-ignore
header: { kid: 'a', typ: 'invalid_typ' },
}),
{
name: 'ZodError',
}
})
)
})

it('should not create a entity configuration when jwks.keys include keys with the same kid', async () => {
await assert.rejects(
createEntityConfiguration({
signJwtCallback: signJwtCallback,
signJwtCallback,
claims: {
exp: 1,
iat: 1,
Expand All @@ -121,10 +111,7 @@ describe('create entity configuration', () => {
},
},
header: { kid: 'a', typ: 'entity-statement+jwt' },
}),
{
name: 'ZodError',
}
})
)
})
})
12 changes: 6 additions & 6 deletions packages/core/__tests__/createEntityStatement.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import assert from 'node:assert'
import assert from 'node:assert/strict'
import { describe, it } from 'node:test'
import { createEntityStatement } from '../src/entityStatement/createEntityStatement'
import type { SignCallback } from '../src/utils'
Expand Down Expand Up @@ -51,6 +51,11 @@ describe('create entity statement', () => {
it('should not create a basic entity statement with an invalid typ', async () => {
await assert.rejects(
createEntityStatement({
header: {
kid: 'a',
// @ts-ignore
typ: 'invalid-typ',
},
jwk: { kty: 'EC', kid: 'a' },
claims: {
exp: 1,
Expand All @@ -59,11 +64,6 @@ describe('create entity statement', () => {
sub: 'https://one.example.org',
jwks: { keys: [{ kty: 'EC', kid: 'b' }] },
},
header: {
kid: 'a',
// @ts-ignore
typ: 'invalid-typ',
},
signJwtCallback,
})
)
Expand Down
139 changes: 139 additions & 0 deletions packages/core/__tests__/e2e.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import assert from 'node:assert/strict'
import { subtle } from 'node:crypto'
import { describe, it } from 'node:test'

import nock from 'nock'

import { createEntityConfiguration, fetchEntityConfiguration } from '../src/entityConfiguration'
import { createEntityStatement, fetchEntityStatement } from '../src/entityStatement'
import type { SignCallback, VerifyCallback } from '../src/utils'

describe('End To End', async () => {
const key = await subtle.generateKey({ name: 'ECDSA', namedCurve: 'P-256' }, true, ['sign', 'verify'])
const exportedKey = await subtle.exportKey('jwk', key.publicKey)
const publicKeyJwk = {
kid: 'some-id',
kty: 'EC',
key_ops: exportedKey.key_ops,
x: exportedKey.x,
y: exportedKey.y,
}

const signJwtCallback: SignCallback = async ({ toBeSigned }) =>
new Uint8Array(await subtle.sign({ hash: 'SHA-256', name: 'ECDSA' }, key.privateKey, toBeSigned))

const verifyJwtCallback: VerifyCallback = async ({ signature, data }) =>
subtle.verify({ name: 'ECDSA', hash: 'SHA-256' }, key.publicKey, signature, data)

it('should fetch an entity configuration', async () => {
const iss = 'https://example.org'

const claims = {
iss,
sub: iss,
exp: new Date(),
iat: new Date(),
jwks: {
keys: [publicKeyJwk],
},
}

const entityConfigurationJwt = await createEntityConfiguration({
signJwtCallback,
claims,
header: {
kid: 'some-id',
typ: 'entity-statement+jwt',
},
})

const scope = nock(iss).get('/.well-known/openid-federation').reply(200, entityConfigurationJwt, {
'content-type': 'application/entity-statement+jwt',
})

const fetchedEntityConfigurationClaims = await fetchEntityConfiguration({
entityId: iss,
verifyJwtCallback,
})

assert.deepStrictEqual(fetchedEntityConfigurationClaims, claims)

scope.done()
})

it('should fetch an entity statement', async () => {
const iss = 'https://example.org'
const sub = 'https://sub.example.org'

const entityConfigurationJwt = await createEntityConfiguration({
signJwtCallback,
claims: {
iss,
sub: iss,
exp: new Date(),
iat: new Date(),
jwks: {
keys: [publicKeyJwk],
},
source_endpoint: `${iss}/fetch`,
},
header: {
kid: 'some-id',
typ: 'entity-statement+jwt',
},
})

const entityStamentClaims = {
iss,
sub: iss,
exp: new Date(),
iat: new Date(),
jwks: {
keys: [],
},
authority_hints: [iss],
metadata: {
federation_entity: {
organization_name: 'my org!',
},
},
}

const entityStatementJwt = await createEntityStatement({
signJwtCallback,
claims: entityStamentClaims,
header: {
kid: 'some-id',
typ: 'entity-statement+jwt',
},
jwk: publicKeyJwk,
})

const scope = nock(iss)
.get('/.well-known/openid-federation')
.reply(200, entityConfigurationJwt, {
'content-type': 'application/entity-statement+jwt',
})
.get('/fetch')
.query({ iss, sub })
.reply(200, entityStatementJwt, {
'content-type': 'application/entity-statement+jwt',
})

const fetchedEntityConfigurationClaims = await fetchEntityConfiguration({
entityId: iss,
verifyJwtCallback,
})

const fetchedEntityStatementClaims = await fetchEntityStatement({
iss,
sub,
issEntityConfiguration: fetchedEntityConfigurationClaims,
verifyJwtCallback,
})

assert.deepStrictEqual(fetchedEntityStatementClaims, entityStamentClaims)

scope.done()
})
})
10 changes: 5 additions & 5 deletions packages/core/__tests__/fetchEntityConfiguration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import nock from 'nock'
describe('fetch entity configuration', () => {
const verifyJwtCallback: VerifyCallback = () => Promise.resolve(true)

const signCallback: SignCallback = () => Promise.resolve(new Uint8Array(10).fill(42))
const signJwtCallback: SignCallback = () => Promise.resolve(new Uint8Array(10).fill(42))

it('should fetch a simple entity configuration', async () => {
const entityId = 'https://example.org'
Expand All @@ -24,7 +24,7 @@ describe('fetch entity configuration', () => {
const entityConfiguration = await createEntityConfiguration({
header: { kid: 'a', typ: 'entity-statement+jwt' },
claims,
signJwtCallback: signCallback,
signJwtCallback,
})

const scope = nock(entityId).get('/.well-known/openid-federation').reply(200, entityConfiguration, {
Expand Down Expand Up @@ -55,21 +55,21 @@ describe('fetch entity configuration', () => {
const entityConfiguration = await createEntityConfiguration({
header: { kid: 'a', typ: 'entity-statement+jwt' },
claims,
signJwtCallback: signCallback,
signJwtCallback,
})

const scope = nock(entityId).get('/.well-known/openid-federation').reply(200, entityConfiguration, {
'content-type': 'invalid-type',
})

await assert.rejects(fetchEntityConfiguration({ entityId, verifyJwtCallback }), { name: 'Error' })
await assert.rejects(fetchEntityConfiguration({ entityId, verifyJwtCallback }))

scope.done()
})

it('should not fetch an entity configuration when there is no entity configuration', async () => {
const entityId = 'https://examplethree.org'

await assert.rejects(fetchEntityConfiguration({ entityId, verifyJwtCallback }), { name: 'TypeError' })
await assert.rejects(fetchEntityConfiguration({ entityId, verifyJwtCallback }))
})
})
Loading

0 comments on commit 291505f

Please sign in to comment.