feat(cloudflare-access): Handle Access organization does not exist and Access not available cases (#898)
parent
cd6c667ee2
commit
b71d817f71
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'@hono/cloudflare-access': minor
|
||||
---
|
||||
|
||||
Handle Access organization does not exist and Access not available cases
|
|
@ -45,7 +45,6 @@ app.get('/', (c) => {
|
|||
export default app
|
||||
```
|
||||
|
||||
|
||||
## Errors throw by the middleware
|
||||
|
||||
| Error | HTTP Code |
|
||||
|
@ -55,6 +54,8 @@ export default app
|
|||
| Authentication error: Token is expired | 401 |
|
||||
| Authentication error: Expected team name {your-team-name}, but received ${different-team-signed-token} | 401 |
|
||||
| Authentication error: Invalid Token | 401 |
|
||||
| Authentication error: The Access Organization 'my-team-name' does not exist | 500 |
|
||||
| Authentication error: Received unexpected HTTP code 500 from Cloudflare Access | 500 |
|
||||
|
||||
## Author
|
||||
|
||||
|
|
|
@ -116,6 +116,8 @@ describe('Cloudflare Access middleware', async () => {
|
|||
const keyPair2 = await generateJWTKeyPair();
|
||||
const keyPair3 = await generateJWTKeyPair();
|
||||
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
vi.stubGlobal('fetch', async () => {
|
||||
return Response.json({
|
||||
keys: [
|
||||
|
@ -124,6 +126,7 @@ describe('Cloudflare Access middleware', async () => {
|
|||
],
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
const app = new Hono()
|
||||
|
||||
|
@ -131,6 +134,12 @@ describe('Cloudflare Access middleware', async () => {
|
|||
app.get('/hello-behind-access', (c) => c.text('foo'))
|
||||
app.get('/access-payload', (c) => c.json(c.get('accessPayload')))
|
||||
|
||||
app.onError((err, c) => {
|
||||
return c.json({
|
||||
err: err.toString(),
|
||||
}, 500)
|
||||
})
|
||||
|
||||
it('Should be throw Missing bearer token when nothing is sent', async () => {
|
||||
const res = await app.request('http://localhost/hello-behind-access')
|
||||
expect(res).not.toBeNull()
|
||||
|
@ -248,4 +257,34 @@ describe('Cloudflare Access middleware', async () => {
|
|||
"exp":expect.any(Number)
|
||||
})
|
||||
})
|
||||
|
||||
it('Should throw an error, if the access organization does not exist', async () => {
|
||||
vi.stubGlobal('fetch', async () => {
|
||||
return Response.json({success: false}, {status: 404})
|
||||
})
|
||||
|
||||
const res = await app.request('http://localhost/hello-behind-access', {
|
||||
headers: {
|
||||
'cf-access-jwt-assertion': 'asdads'
|
||||
}
|
||||
})
|
||||
expect(res).not.toBeNull()
|
||||
expect(res.status).toBe(500)
|
||||
expect(await res.json()).toEqual({"err":"Error: Authentication error: The Access Organization 'my-cool-team-name' does not exist"})
|
||||
})
|
||||
|
||||
it('Should throw an error, if the access certs url is unavailable', async () => {
|
||||
vi.stubGlobal('fetch', async () => {
|
||||
return Response.json({success: false}, {status: 500})
|
||||
})
|
||||
|
||||
const res = await app.request('http://localhost/hello-behind-access', {
|
||||
headers: {
|
||||
'cf-access-jwt-assertion': 'asdads'
|
||||
}
|
||||
})
|
||||
expect(res).not.toBeNull()
|
||||
expect(res.status).toBe(500)
|
||||
expect(await res.json()).toEqual({"err":"Error: Authentication error: Received unexpected HTTP code 500 from Cloudflare Access"})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { createMiddleware } from 'hono/factory'
|
||||
import { Context } from 'hono'
|
||||
import { HTTPException } from 'hono/http-exception'
|
||||
|
||||
export type CloudflareAccessPayload = {
|
||||
aud: string[],
|
||||
|
@ -89,6 +90,14 @@ async function getPublicKeys(accessTeamName: string) {
|
|||
},
|
||||
})
|
||||
|
||||
if (!result.ok) {
|
||||
if (result.status === 404) {
|
||||
throw new HTTPException(500, { message: `Authentication error: The Access Organization '${accessTeamName}' does not exist` })
|
||||
}
|
||||
|
||||
throw new HTTPException(500, { message: `Authentication error: Received unexpected HTTP code ${result.status} from Cloudflare Access` })
|
||||
}
|
||||
|
||||
const data: any = await result.json()
|
||||
|
||||
// Because we keep CryptoKey's in memory between requests, we need to make sure they are refreshed once in a while
|
||||
|
|
Loading…
Reference in New Issue