Skip to content

Commit

Permalink
feat: tests
Browse files Browse the repository at this point in the history
  • Loading branch information
njlie committed Jun 30, 2022
1 parent d0696d6 commit e67888b
Show file tree
Hide file tree
Showing 13 changed files with 30,584 additions and 173 deletions.
30,238 changes: 30,238 additions & 0 deletions .pnp.cjs

Large diffs are not rendered by default.

Binary file not shown.
Binary file not shown.
2 changes: 2 additions & 0 deletions packages/auth/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@adonisjs/fold": "^8.1.0",
"@koa/cors": "^3.1.0",
"@koa/router": "^10.0.0",
"@sinonjs/fake-timers": "^9.1.2",
"axios": "^0.26.1",
"jose": "^4.7.0",
"knex": "^0.21.17",
Expand All @@ -36,6 +37,7 @@
"@types/koa__router": "^8.0.11",
"@types/nock": "^11.1.0",
"@types/pino": "^7.0.5",
"@types/sinonjs__fake-timers": "^8.1.2",
"@types/uuid": "^8.3.0",
"nock": "^13.2.4",
"typescript": "^4.2.4"
Expand Down
234 changes: 183 additions & 51 deletions packages/auth/src/accessToken/routes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,16 @@ import { AccessToken } from './model'
import { Access } from '../access/model'
import { AccessTokenRoutes } from './routes'
import { createContext } from '../tests/context'

const KEY_REGISTRY_ORIGIN = 'https://openpayments.network'
const TEST_KID_PATH = '/keys/test-key'
const TEST_CLIENT_KEY = {
kid: KEY_REGISTRY_ORIGIN + TEST_KID_PATH,
x: 'test-public-key',
kty: 'OKP',
alg: 'EdDSA',
crv: 'Ed25519',
key_ops: ['sign', 'verify'],
use: 'sig'
}
import {
generateSigHeaders,
SIGNATURE_METHOD,
SIGNATURE_TARGET_URI
} from '../tests/signature'
import {
TEST_KID_PATH,
KEY_REGISTRY_ORIGIN,
TEST_CLIENT_KEY
} from '../grant/routes.test'

describe('Access Token Routes', (): void => {
let deps: IocContract<AppServices>
Expand Down Expand Up @@ -111,36 +109,63 @@ describe('Access Token Routes', (): void => {
}
)
test('Cannot introspect fake token', async (): Promise<void> => {
const requestBody = {
access_token: v4(),
proof: 'httpsig',
resource_server: 'test'
}
const { signature, sigInput, contentDigest } = await generateSigHeaders(
requestBody
)
const ctx = createContext(
{
headers: { Accept: 'application/json' }
headers: {
Accept: 'application/json',
'Content-Digest': contentDigest,
Signature: signature,
'Signature-Input': sigInput
}
},
{}
)
ctx.request.body = {
access_token: v4(),
proof: 'httpsig',
resource_server: 'test'
}
await expect(accessTokenRoutes.introspect(ctx)).rejects.toMatchObject({
status: 404,
ctx.request.body = requestBody
ctx.method = SIGNATURE_METHOD
ctx.request.url = SIGNATURE_TARGET_URI
await expect(accessTokenRoutes.introspect(ctx)).resolves.toBeUndefined()
expect(ctx.status).toBe(404)
expect(ctx.body).toMatchObject({
error: 'invalid_client',
message: 'token not found'
})
})

test('Cannot introspect if no token passed', async (): Promise<void> => {
const requestBody = {
proof: 'httpsig',
resource_server: 'test'
}

const { signature, sigInput, contentDigest } = await generateSigHeaders(
requestBody
)
const ctx = createContext(
{
headers: { Accept: 'application/json' }
headers: {
Accept: 'application/json',
'Content-Digest': contentDigest,
Signature: signature,
'Signature-Input': sigInput
}
},
{}
)
ctx.request.body = {
proof: 'httpsig',
resource_server: 'test'
}
await expect(accessTokenRoutes.introspect(ctx)).rejects.toMatchObject({
status: 400,
ctx.request.body = requestBody
ctx.method = SIGNATURE_METHOD
ctx.request.url = SIGNATURE_TARGET_URI
await expect(accessTokenRoutes.introspect(ctx)).resolves.toBeUndefined()
expect(ctx.status).toBe(400)
expect(ctx.body).toEqual({
error: 'invalid_request',
message: 'invalid introspection request'
})
})
Expand All @@ -149,19 +174,33 @@ describe('Access Token Routes', (): void => {
const scope = nock(KEY_REGISTRY_ORIGIN)
.get(TEST_KID_PATH)
.reply(200, {
keys: [TEST_CLIENT_KEY]
keys: [TEST_CLIENT_KEY.jwk]
})

const requestBody = {
access_token: token.value,
proof: 'httpsig',
resource_server: 'test'
}

const { signature, sigInput, contentDigest } = await generateSigHeaders(
requestBody
)
const ctx = createContext(
{
headers: { Accept: 'application/json' }
headers: {
Accept: 'application/json',
'Content-Digest': contentDigest,
Signature: signature,
'Signature-Input': sigInput
},
method: SIGNATURE_METHOD,
url: SIGNATURE_TARGET_URI
},
{}
)
ctx.request.body = {
access_token: token.value,
proof: 'httpsig',
resource_server: 'test'
}

ctx.request.body = requestBody
await expect(accessTokenRoutes.introspect(ctx)).resolves.toBeUndefined()
expect(ctx.status).toBe(200)
expect(ctx.response.get('Content-Type')).toBe(
Expand All @@ -177,26 +216,52 @@ describe('Access Token Routes', (): void => {
limits: access.limits
}
],
key: { proof: 'httpsig', jwk: TEST_CLIENT_KEY }
key: {
proof: 'httpsig',
jwk: {
...TEST_CLIENT_KEY.jwk,
nbf: expect.any(Number),
exp: expect.any(Number),
revoked: false
}
}
})
scope.isDone()
})

test('Successfully introspects expired token', async (): Promise<void> => {
const now = new Date(new Date().getTime() + 4000)
const scope = nock(KEY_REGISTRY_ORIGIN)
.get(TEST_KID_PATH)
.reply(200, {
keys: [TEST_CLIENT_KEY.jwk]
})
const now = new Date(new Date().getTime())
jest.useFakeTimers('modern')
jest.setSystemTime(now)
const requestBody = {
access_token: token.value,
proof: 'httpsig',
resource_server: 'test'
}

const { signature, sigInput, contentDigest } = await generateSigHeaders(
requestBody
)
const ctx = createContext(
{
headers: { Accept: 'application/json' }
headers: {
Accept: 'application/json',
'Content-Digest': contentDigest,
Signature: signature,
'Signature-Input': sigInput
},
method: SIGNATURE_METHOD,
url: SIGNATURE_TARGET_URI
},
{}
)
ctx.request.body = {
access_token: token.value,
proof: 'httpsig',
resource_server: 'test'
}

ctx.request.body = requestBody
await expect(accessTokenRoutes.introspect(ctx)).resolves.toBeUndefined()
expect(ctx.status).toBe(200)
expect(ctx.response.get('Content-Type')).toBe(
Expand All @@ -205,13 +270,15 @@ describe('Access Token Routes', (): void => {
expect(ctx.body).toEqual({
active: false
})

scope.isDone()
})
})

describe('Revocation', (): void => {
let grant: Grant
let token: AccessToken
let id: string
let managementId: string

beforeEach(
async (): Promise<void> => {
Expand All @@ -222,49 +289,114 @@ describe('Access Token Routes', (): void => {
grantId: grant.id,
...BASE_TOKEN
})
id = token.id
managementId = token.managementId
}
)

test('Returns status 404 if token does not exist', async (): Promise<void> => {
id = v4()
managementId = v4()

const scope = nock(KEY_REGISTRY_ORIGIN)
.get(TEST_KID_PATH)
.reply(200, {
keys: [TEST_CLIENT_KEY.jwk]
})

const requestBody = {
access_token: token.value,
proof: 'httpsig',
resource_server: 'test'
}

const { signature, sigInput, contentDigest } = await generateSigHeaders()
const ctx = createContext(
{
headers: { Accept: 'application/json' }
headers: {
Accept: 'application/json',
'Content-Digest': contentDigest,
Signature: signature,
'Signature-Input': sigInput
}
},
{ id }
{ managementId }
)

ctx.request.body = requestBody

await expect(accessTokenRoutes.revoke(ctx)).rejects.toMatchObject({
status: 404,
message: 'token not found'
})

scope.isDone()
})

test('Returns status 204 if token has not expired', async (): Promise<void> => {
const scope = nock(KEY_REGISTRY_ORIGIN)
.get(TEST_KID_PATH)
.reply(200, {
keys: [TEST_CLIENT_KEY.jwk]
})

const requestBody = {
access_token: token.value,
proof: 'httpsig',
resource_server: 'test'
}
const { signature, sigInput, contentDigest } = await generateSigHeaders()
const ctx = createContext(
{
headers: { Accept: 'application/json' }
headers: {
Accept: 'application/json',
'Content-Digest': contentDigest,
Signature: signature,
'Signature-Input': sigInput
}
},
{ id }
{ managementId }
)

ctx.method = SIGNATURE_METHOD
ctx.request.url = SIGNATURE_TARGET_URI
ctx.request.body = requestBody
await token.$query(trx).patch({ expiresIn: 10000 })
await accessTokenRoutes.revoke(ctx)
expect(ctx.response.status).toBe(204)
scope.isDone()
})

test('Returns status 204 if token has expired', async (): Promise<void> => {
const scope = nock(KEY_REGISTRY_ORIGIN)
.get(TEST_KID_PATH)
.reply(200, {
keys: [TEST_CLIENT_KEY.jwk]
})

const requestBody = {
access_token: token.value,
proof: 'httpsig',
resource_server: 'test'
}
const { signature, sigInput, contentDigest } = await generateSigHeaders()
const ctx = createContext(
{
headers: { Accept: 'application/json' }
headers: {
Accept: 'application/json',
'Content-Digest': contentDigest,
Signature: signature,
'Signature-Input': sigInput
}
},
{ id }
{ managementId }
)

ctx.method = SIGNATURE_METHOD
ctx.request.url = SIGNATURE_TARGET_URI
ctx.request.body = requestBody
await token.$query(trx).patch({ expiresIn: -1 })
await accessTokenRoutes.revoke(ctx)
expect(ctx.response.status).toBe(204)
scope.isDone()
})
})
})

0 comments on commit e67888b

Please sign in to comment.