-
Notifications
You must be signed in to change notification settings - Fork 90
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(auth): improve GNAP error responses #2400
Conversation
✅ Deploy Preview for brilliant-pasca-3e80ec ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
packages/auth/src/grant/routes.ts
Outdated
@@ -364,16 +364,16 @@ async function revokeGrant( | |||
'GNAP ' | |||
)[1] | |||
if (!continueId || !continueToken) { | |||
ctx.throw(401, { error: 'invalid_request' }) | |||
ctx.throw(401, { error: { code: 'invalid_request', description: 'invalid continuation information' } }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to how you did above, should we add the description also as the second parameter to have it also exposed to the caller/client (like postman)? Or not for these 401 errors?
@@ -202,28 +199,48 @@ async function handleInteractionChoice( | |||
Buffer.from(config.identityServerSecret) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should there be also similar changes for L120 and L125?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought at first not to change those, as they're not being served by a GNAP endpoint. But now I think I'll make them uniform across the board.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should error responses in middleware such as this be update as well?
https://github.com/interledger/rafiki/blob/main/packages/auth/src/signature/middleware.ts#L44
Good catch, I forgot about those. |
packages/auth/src/grant/routes.ts
Outdated
ctx.throw(400, 'interaction_required', { | ||
error: { | ||
code: 'interaction_required', | ||
description: 'missing required request field' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be different from the invalid_client
description? Maybe
missing required request field 'interact'
and
missing required request field 'client'
respectively.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do you think about making GNAP error responses into an enum and then having a function to handle all of these throws?
packages/auth/src/grant/routes.ts
Outdated
} | ||
const grant = await deps.grantService.getByContinue(continueId, continueToken) | ||
if (!grant) { | ||
ctx.throw(404, { error: 'unknown_request' }) | ||
ctx.throw(404, 'unknown_request', { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should this also be invalid_request
?
@@ -101,7 +102,12 @@ async function createGrant( | |||
try { | |||
noInteractionRequired = canSkipInteraction(deps.config, ctx.request.body) | |||
} catch (err) { | |||
ctx.throw(400, 'identifier_required', { error: 'identifier_required' }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no idea where I got stuff like identifier_required
or internal_server_error
. I've restricted error responses to the ones that are listed in https://datatracker.ietf.org/doc/html/draft-ietf-gnap-core-protocol-18#section-3.6
@@ -144,12 +157,26 @@ async function createPendingGrant( | |||
const { body } = ctx.request | |||
const { grantService, interactionService, config } = deps | |||
if (!body.interact) { | |||
ctx.throw(400, 'interaction_required', { error: 'interaction_required' }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I changed this from interaction_required
because that seems to be more for if a resource (likely only a grant) requires interaction in order to be accessed.
@@ -294,9 +297,11 @@ describe('Signature Service', (): void => { | |||
resource_server: 'test' | |||
} | |||
await expect(tokenHttpsigMiddleware(ctx, next)).rejects.toMatchObject({ | |||
status: 400, | |||
error: 'invalid_request', | |||
message: 'invalid signature headers' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've change this and other error responses to 401
as it is a failure to verify the signature. I also chose invalid_client
as the code because of the following description:
"invalid_client":
The request was made from a client that was not recognized or allowed by the AS, or the client's signature validation failed.
(emphasis mine)
Not so small anymore... |
@@ -119,20 +120,25 @@ async function rotateToken( | |||
newToken = await deps.accessTokenService.rotate(ctx.accessToken.id, trx) | |||
|
|||
if (!newToken) { | |||
ctx.throw() | |||
throw new Error('invalid access token') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not throw an internal server error with this error message? I know that this is kind of what we are doing here, but should we do a ctx.throw
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think because we end up catching the error and then call ctx.throw
below
packages/auth/src/grant/routes.ts
Outdated
error: { | ||
code: GNAPErrorCode.InvalidRequest, | ||
description: 'access identifier required' | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we call generateGNAPErrorResponse
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, yes we should
@@ -119,20 +120,25 @@ async function rotateToken( | |||
newToken = await deps.accessTokenService.rotate(ctx.accessToken.id, trx) | |||
|
|||
if (!newToken) { | |||
ctx.throw() | |||
throw new Error('invalid access token') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think because we end up catching the error and then call ctx.throw
below
ctx.throw( | ||
400, | ||
GNAPErrorCode.InvalidRotation, | ||
generateGNAPErrorResponse(GNAPErrorCode.InvalidRotation, errorMessage) | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ctx.throw( | |
400, | |
GNAPErrorCode.InvalidRotation, | |
generateGNAPErrorResponse(GNAPErrorCode.InvalidRotation, errorMessage) | |
) | |
throwGNAPError(ctx, 400, GNAPErrorCode.InvalidRotation, message) |
what do you think of something like this also? then we wouldn't need to define the GNAPErrorCode.X
value twice
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it, looks cleaner that way too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM ✅
🚢 it
…r GNAP error codes
b1baa45
to
c335b90
Compare
* feat(auth): improve GNAP error responses * fix: add extra arg to ctx.throw * feat: middleware error improvements * feat: add error messages to grant details endpoint * fix: update error messages in grant routes * feat: create utility function to generate GNAP errors, create enum for GNAP error codes * feat: helper function throws instead of generates response
* feat(backend): webhook max retry * fix: tighten filter * Update packages/documentation/src/content/docs/integration/deployment.md Co-authored-by: Max Kurapov <max@interledger.org> * test: address review feedback * chore: add feature requests to contributing.md (#2542) * chore: enable graphql protection - maxDepth, blockFieldSuggestions, maxCost (#2537) * chore: add graphql depth restriction * feat: properly enable graphql armor * style: remove unnecessary space * chore: add armor to auth admin server * fix(deps): update module github.com/aws/aws-sdk-go to v1.50.38 (#2543) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update dependency @interledger/open-payments to v6.7.2 (#2544) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(frontend): add X-Frame-Options header (#2538) * chore(deps): update dependency @types/lodash to ^4.17.0 (#2546) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @types/react to ^18.2.66 (#2545) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update dependency @interledger/open-payments to v6.8.0 (#2547) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update module github.com/aws/aws-sdk-go to v1.51.0 (#2548) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update dependency @interledger/docs-design-system to ^0.3.2 (#2549) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update dependency axios to v1.6.8 (#2556) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update dependency isbot to v5 (#2553) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update typescript-eslint monorepo to v7 (#2552) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update dependency koa to ^2.15.1 (#2551) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency postcss to ^8.4.36 (#2559) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update helm release redis to v18.19.3 (#2561) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * feat(bruno): use polling in grant continuation (#2550) * chore: fetch latest OP schemas * feat(bruno): use polling for grant continuation * docs: update * fix: bruno tests * chore(deps): update pnpm to v8.15.5 (#2563) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * feat(telemetry): LIVENET now points to new livenet NLB (#2523) * feat(telemetry): LIVENET now points to new livenet NLB * Update packages/backend/src/config/app.ts Co-authored-by: Max Kurapov <max@interledger.org> * Update packages/backend/src/config/app.ts Co-authored-by: Max Kurapov <max@interledger.org> --------- Co-authored-by: Max Kurapov <max@interledger.org> Co-authored-by: Sabine Schaller <sabine@interledger.org> * feat(auth): improve GNAP error responses (#2400) * feat(auth): improve GNAP error responses * fix: add extra arg to ctx.throw * feat: middleware error improvements * feat: add error messages to grant details endpoint * fix: update error messages in grant routes * feat: create utility function to generate GNAP errors, create enum for GNAP error codes * feat: helper function throws instead of generates response * feat: integration tests (#2380) * feat: setup basic test env * feat: seed integration environment - cmd to start integration environment and run tests - seeds environment on test run - extracts common MASE functionality into new mock-account-servicing-lib * refactor(localenv,integration): move graphql url to config from seed - moves graphql url to config from seed - also removes self section which only contained unused properties * refactor: move testenv configuration into new dir * refactor: cleanup env vars * feat: add webhook server, fix env vars * chore: comment * feat: start grant request test * fix: eslint errors * fix: docker compose env vars * feat: add --build arg * fix: incoming-payment grant initiation request Grant request was failing with invalid signature. This was fixed by directing hte backend to use the same private key being used to create the open payments client. * fix: ts error * feat: implement tests through Create Quote * chore: upgrade op client * feat: partially implemented grant request outgoing payment test * feat: rework to host.docker.internal - switches hostname to host.docker.internal to resolve url mismatch problem - finishes grant request outgoing payment test - cleans up some configuration and test variables * feat: add p2p flow test * feat: add continuation step with consent mocking * fix: rm obsolete type cast to any and comment * feat: add create ougoing payment test * fix: bad pnpm-lock merge * feat: build deps in mock ase job * feat: get non existant wallet address test * fix: update open payments pkg * chore: fix lint warnings * feat: implement continuation polling * chore: test cleanup * refactor: generate gql in tests instead of import from lib * chore: rm old comment * chore: use latest http-singature-utils to match other deps * chore: pnpm i * chore: use latest koa-bodyparser * chore: rm engine strict * chore: revert rm engine strict - fixes netlify ci failure but ultimately not the correct fix * chore(integration): dont ignore env, rm example env * refactor: use docker healthcheck for running tests * chore: move healthcheck to last started docker container * feat: use latest open payments pkg, no body requird on continuation * chore: pnpm i, fix broken lockfile (no apollo version) * refactor: move webhook event enum to types * refactor: move run integration script to test/integration * Update packages/mock-account-servicing-lib/package.json Co-authored-by: Sabine Schaller <sabine@interledger.org> * refactor: simplify mock-account-servicing-entity ci step * feat(integration): exit run-tests early if containers fail to start * feat: use pino logger * refactor: rename mock account servicing lib * refactor: rename class files to camel case * fix: import correct body parser * refactor: poll instead of delay * refactor: simplify call to poll condition only * fix: update filenames * refactor: change filename name to kebab case --------- Co-authored-by: Sabine Schaller <sabine@interledger.org> * fix(deps): update dependency isbot to ^5.1.2 (#2567) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update dependency @types/react to ^18.2.67 (#2566) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * fix(deps): update module github.com/aws/aws-sdk-go to v1.51.2 (#2565) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * chore(deps): update helm release redis to v18.19.4 (#2570) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * feat(backend): make SPSP optional (#2560) * feat: flag to enable/disable SPSP * test: update to cover all cases * docs: add link to glossary * chore: fix lockfile * test: address feedback * delete lockfile * add lockfile * delete lockfile * fix lockfile this time? * fix: formatting --------- Co-authored-by: Max Kurapov <max@interledger.org> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: xplicit <111863110+beniaminmunteanu@users.noreply.github.com> Co-authored-by: Nathan Lie <lie4nathan@gmail.com> Co-authored-by: Blair Currey <12960453+BlairCurrey@users.noreply.github.com>
Changes proposed in this pull request
code
field that refers to a particular GNAP error and adescription
field that explains what went wrong.Context
Fixes #2344.
Just a small PR to update all the GNAP error responses to be more detailed.
Checklist
fixes #number