-
Notifications
You must be signed in to change notification settings - Fork 89
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
chore(backend): update wallet address middleware & error handling #2722
Conversation
✅ Deploy Preview for brilliant-pasca-3e80ec ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
packages/backend/src/index.ts
Outdated
@@ -318,8 +318,7 @@ export function initIocContainer( | |||
return createWalletAddressKeyRoutes({ | |||
config: await deps.use('config'), | |||
logger: await deps.use('logger'), | |||
walletAddressKeyService: await deps.use('walletAddressKeyService'), | |||
walletAddressService: await deps.use('walletAddressService') |
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.
unused now
@@ -95,7 +95,7 @@ export function createTokenIntrospectionMiddleware({ | |||
const access = tokenInfo.access.find((access: Access) => { | |||
if ( | |||
access.type !== requestType || | |||
(access.identifier && access.identifier !== ctx.walletAddress.url) | |||
(access.identifier && access.identifier !== ctx.walletAddressUrl) |
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.
at this point, in the token introspection middleware, we only have ctx.walletAddressUrl
in the context
@@ -30,16 +30,6 @@ export async function getWalletAddress( | |||
deps: ServiceDependencies, | |||
ctx: WalletAddressContext | |||
): Promise<void> { | |||
if (!ctx.walletAddress) { |
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.
we're already handling this in the wallet address middleware
@@ -426,7 +429,6 @@ export class App { | |||
// Create incoming payment | |||
router.post<DefaultState, SignedCollectionContext<IncomingCreateBody>>( |
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.
now, each route follows as such:
- validate against the OpenAPI spec (since we need all of the request parameters, including the walletAddressUrl ones to be always valid)
- Get wallet address URL, from either request body, query params, or the resource itself
- do token introspection
- do http sig verification (if required)
- fetch (poll for) walletAddress via the walletAddressUrl from step 2, add it onto the ctx
- Call the actual route
packages/backend/src/app.ts
Outdated
walletAddressServerSpec, | ||
{ | ||
path: '/', | ||
method: HttpMethod.GET | ||
}, | ||
validatorMiddlewareOptions | ||
), | ||
getWalletAddressUrlFromPath, | ||
createWalletAddressMiddleware({ errorCodeOnMissing: 404 }), |
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.
usually, we call 400 (since 404 doesn't really make sense when doing a e.g. GET/POST outgoing payment, since its not the resource that's missing, its the wallet address request body or query param that points to an invalid wallet address).
…essForSubresource
…on routes themselves
packages/backend/src/app.ts
Outdated
getWalletAddressUrlFromPath, | ||
createSpspMiddleware(this.config.spspEnabled), |
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.
do not call getWalletAddressForSubresource
here and in the jwks.json route since we have different behaviours in these routes for handling deps.config.walletAddressUrl === ctx.walletAddressUrl
This is much better. Low coupling/high cohesion. 👍 |
): Promise<void> { | ||
if (!ctx.walletAddress) { | ||
// The instance's wallet address is only relevant for the /jwks.json route, so "hide" it when directly requested |
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.
Does this mean we just shouldn't have a /GET
route for the wallet address? If we still need this route then when would we need it? Comment seems to suggest we only need the /jwks.json
route IMO but maybe im not following.
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.
When I call the Examples > Open Payments > Get receiver wallet address
bruno request (which creates the wallet address) then call Open Payments APIs > Get a Wallet Address
I receive the the wallet address.
If I copy/paste the url into the browser http://localhost:4000/accounts/asmith
then I see Could not get wallet address
.
How should it be working? It seems like the bruno request should not return the wallet address according to this comment.
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.
deps.config.walletAddressUrl
is the configured wallet address for the Rafiki instance itself, i.e. its the wallet address used to get incoming payments/incoming payment grants when creating "remote" incoming payments at other Rafikis. e.g. https://ilp.rafiki.money/.well-known/pay/.
Maybe I can word this comment better, but we actually don't want to resolve https://ilp.rafiki.money/.well-known/pay/ ever (this shouldn't be a wallet address which resources can be created on, its not for an actual user account). As a result, we only care about the https://ilp.rafiki.money/.well-known/pay/jwks.json path, since it gets looked up to check the keys of the rafiki instance when validating the grant on another rafiki.
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.
All other "normal" wallet addresses, should get resolved as usual with the correct asset, publicName, auth/resourceServer urls (since they represent actual user accounts)
Actually, it is odd you don't see http://localhost:4000/accounts/asmith. Can you try a different wallet address?
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.
Ah that makes sense, thank you for the context.
Same result with http://localhost:3000/accounts/gfranklin
in the browser, but not with bruno. This is not the case on main - this request works as expected in the browser. The only difference between bruno and the browser I see is the host header that gets added in the pre-request script. Not sure if that's the actual difference.
Here is the error:
{"level":30,"time":1715787978022,"pid":1,"hostname":"cloud-nine-wallet-backend","method":"GET","path":"/accounts/gfranklin","message":"Could not get wallet address","msg":"Received error when handling SPSP request"}
Looks like its failing at the if (!walletAddress?.isActive) {
check of the spspsMiddleware
.
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.
going back just 1 step further it looks like if (ctx.accepts('application/spsp4+json')) {
resolves to false with the bruno request, and true for the browser.
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 happens when we call http://localhost:3000/accounts/gfranklin
in the browser, or without the host header in bruno, is we actually end up updating the wallet address via the wallet_address.not_found
webhook event. (ie if you request http://localhost:3000/accounts/gfranklin
on main, the wallet address will end up changing from https://cloud-nine-wallet-backend/accounts/gfranklin
to http://localhost:3000/accounts/gfranklin
.
This PR is different for SPSP request since we use walletAddressService.getByUrl
instead of walletAddressService.getOrPollByUrl
. However, I think this PR has same behaviour when we request a wallet address without going through SPSP as well just by requesting the wallet address with Accept: application/json
. I think we should update the MASE code to prevent this, and seems like a separate issue in general.
I'm not sure why I decided to use walletAddressService.getByUrl
in SPSP instead of polling (maybe I assume if you are using SPSP then we should already have a wallet address)?
This makes me wonder if we should default to returning the Open Payments wallet address actually, and only return the SPSP details if explicitly requested?
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.
This makes me wonder if we should default to returning the Open Payments wallet address actually, and only return the SPSP details if explicitly requested?
Chatted w Sabine regarding this, decision made to return Open Payments wallet address by default when fetching it. Also made a change to return SPSP wallet address only if 'application/spsp4+json'
is present in accept header explicitly, and decided that using getByUrl
was sufficient in the SPSP lookup.
…ET spsp accept header explicit
15cc4a6
to
7f6a65a
Compare
createWalletAddressMiddleware(), | ||
getWalletAddressUrlFromPath, |
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.
Basically, if we are fetching the SPSP payment pointer, we don't need to call the validator middleware since its not Open Payments related
if (ctx.accepts('application/spsp4+json')) { | ||
if (ctx.request.header.accept?.includes(SPSP_CONTENT_TYPE_V4)) { |
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.
this ctx.accepts
was the reason why by default when fetching the wallet address, the SPSP details were returned, since usually, the accept
header included catch all */*
route, which to ctx.accepts
would be truthy.
Now, we need to explicitly add application/spsp4+json
in the header to get the SPSP details
Going to close and re-open to see if I can get past the stuck actions (I think affected by their degradation here) |
Changes proposed in this pull request
To finalize the standardization of Open Payments route errors in
backend
, this PR splits upwalletAddressMiddleware
into several separate middlewares. One group of them deals with adding the walletAddressUrl onto the ctx (from several resources), whilegetWalletAddressForSubresource
simply polls for the active wallet address by using thectx.walletAddressUrl
itself. Each of the middlewares is then added explicity to the route.The benefits:
openPaymentsServerErrorMiddleware
(i.e. we don't usectx.throw
at all in other places)walletAddressUrl
is added to thectx
as a middleware specific to the route route, meaning we can remove all-encompassing logic inwalletAddressMiddleware
. Likewise, we don't need to actually fetch the wallet address before doing token introspection and http sig verificationOther changes:
accept
header to include'application/spsp4+json'
explicitlyContext
Fixes #1905 for backend
Checklist
fixes #number