Skip to content

Commit

Permalink
fix(auth): do not force validation of jwt for requests without auth h…
Browse files Browse the repository at this point in the history
…eader (#392)
  • Loading branch information
Silthus authored Feb 17, 2024
1 parent d912a16 commit e41f4b9
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 32 deletions.
26 changes: 13 additions & 13 deletions src/__tests__/areas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,36 +75,36 @@ describe('areas API', () => {
})
})

it('retrieves an area and lists associated organizations', async () => {
it('retrieves an area omitting organizations that exclude it', async () => {
const response = await queryAPI({
query: areaQuery,
operationName: 'area',
variables: { input: wa.metadata.area_id },
variables: { input: ca.metadata.area_id },
userUuid,
app
})

expect(response.statusCode).toBe(200)
const areaResult = response.body.data.area
expect(areaResult.uuid).toBe(muuidToString(wa.metadata.area_id))
expect(areaResult.organizations).toHaveLength(1)
expect(areaResult.organizations[0].orgId).toBe(muuidToString(alphaOrg.orgId))
expect(areaResult.uuid).toBe(muuidToString(ca.metadata.area_id))
// Even though alphaOrg associates with ca's parent, usa, it excludes
// ca and so should not be listed.
expect(areaResult.organizations).toHaveLength(0)
})

it('retrieves an area omitting organizations that exclude it', async () => {
it.each([userUuid, undefined])('retrieves an area and lists associated organizations', async (userId) => {
const response = await queryAPI({
query: areaQuery,
operationName: 'area',
variables: { input: ca.metadata.area_id },
userUuid,
variables: { input: wa.metadata.area_id },
userUuid: userId,
app
})

expect(response.statusCode).toBe(200)
const areaResult = response.body.data.area
expect(areaResult.uuid).toBe(muuidToString(ca.metadata.area_id))
// Even though alphaOrg associates with ca's parent, usa, it excludes
// ca and so should not be listed.
expect(areaResult.organizations).toHaveLength(0)
expect(areaResult.uuid).toBe(muuidToString(wa.metadata.area_id))
expect(areaResult.organizations).toHaveLength(1)
expect(areaResult.organizations[0].orgId).toBe(muuidToString(alphaOrg.orgId))
})
})
})
42 changes: 25 additions & 17 deletions src/auth/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ import { AuthUserType } from '../types.js'
import { verifyJWT } from './util.js'
import { logger } from '../logger.js'

const EMTPY_USER: AuthUserType = {
isBuilder: false,
roles: [],
uuid: undefined
}

/**
* Create a middleware context for Apollo server
*/
Expand All @@ -15,27 +21,29 @@ export const createContext = async ({ req }): Promise<any> => {
}
}

async function validateTokenAndExtractUser (req: Request): Promise<{ user: AuthUserType, token: string }> {
async function validateTokenAndExtractUser (req: Request): Promise<{ user: AuthUserType, token?: string }> {
const { headers } = req
// eslint-disable-next-line @typescript-eslint/dot-notation
const authHeader = String(headers?.['authorization'] ?? '')
if (!authHeader.startsWith('Bearer ')) {
throw new Error('Unauthorized. Please provide a valid JWT token in the Authorization header.')
if (authHeader.startsWith('Bearer ')) {
const token = authHeader.substring(7, authHeader.length).trim()
try {
const payload = await verifyJWT(token)
return {
user: {
isBuilder: payload?.scope?.includes('builder:default') ?? false,
roles: payload?.['https://tacos.openbeta.io/roles'] ?? [],
uuid: payload?.['https://tacos.openbeta.io/uuid'] != null ? muid.from(payload['https://tacos.openbeta.io/uuid']) : undefined
},
token
}
} catch (e) {
logger.error(`Can't verify JWT token ${e.toString() as string}`)
throw new Error("Unauthorized. Can't verify JWT token")
}
}

const token = authHeader.substring(7, authHeader.length).trim()
try {
const payload = await verifyJWT(token)
return {
user: {
isBuilder: payload?.scope?.includes('builder:default') ?? false,
roles: payload?.['https://tacos.openbeta.io/roles'] ?? [],
uuid: payload?.['https://tacos.openbeta.io/uuid'] != null ? muid.from(payload['https://tacos.openbeta.io/uuid']) : undefined
},
token
}
} catch (e) {
logger.error(`Can't verify JWT token ${e.toString() as string}`)
throw new Error("Unauthorized. Can't verify JWT token")
return {
user: EMTPY_USER
}
}
9 changes: 7 additions & 2 deletions src/utils/testUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,15 @@ export const queryAPI = async ({
})

const queryObj = { query, operationName, variables }
return await request(app ?? `http://localhost:${port}`)
let req = request(app ?? `http://localhost:${port}`)
.post(endpoint)
.send(queryObj)
.set('Authorization', 'Bearer placeholder-jwt-see-SpyOn')

if (userUuid != null) {
req = req.set('Authorization', 'Bearer placeholder-jwt-see-SpyOn')
}

return await req
}

export interface SetUpServerReturnType {
Expand Down

0 comments on commit e41f4b9

Please sign in to comment.