Repository navigation
Sign JWT logins in LOGIN_TOKEN and add the noon Marketplace adapter - #1236
Merged
Merged
Conversation
helpcodeai
force-pushed
the
feat/noon-marketplace
branch
from
October 24, 2026 18:45
a5c2355 to
e1d25a6
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
noon's Partner API logs in with a JWT the client signs with its service account key, not with a password, so a noon Marketplace adapter was not possible. This lets
LOGIN_TOKENsign that JWT for each login (#1235) and adds thenoon-marketplaceadapter (noon.com marketplace in the UAE, Saudi Arabia and Egypt) as its first user.Changes
Engine
LOGIN_TOKENtakes an optionalsignedJwtblock (privateKey,algorithmdefault RS256,claims, optionalkeyId,ttlSeconds,outputParam). Every login signs a new token (iat= now in whole seconds, randomjti, then the claims;exponly withttlSeconds), available to the login body as${signedJwt}. With it,usernameandpasswordare not required.private_key_jwtclient assertions:signJwtwas extracted fromsignClientAssertion(same key parsing, algorithms and errors; the client assertion's claims are unchanged). A claim whose{{VARIABLE}}is empty fails the login with an error naming it; key errors never contain key material; the signed token is masked in the login debug log.LOGIN_TOKENfailure hint now says "credentials (email and password, or a signing key)".catalog.spec.tschecksLOGIN_TOKENadapters by the same rules as the engine:cookieNameoptional withcookieMode: "all", and withsignedJwta key and${signedJwt}in the login body instead of username/password.docs/connectors/login-token-auth.md(field reference, placeholder, "Signed JWT logins", security note) anddocs/tool-definition.md.Adapter
noon-marketplace(intl, e-commerce, 27 tools; 545 adapters listed, up from 544)sub=NOON_KEY_ID, posted withNOON_PROJECT_CODEto/identity/public/v1/api/login; the session cookies (30 days) are sent back on every call, withUser-AgentandX-Project. Variables:NOON_KEY_ID,NOON_PRIVATE_KEY,NOON_PROJECT_CODE, from the service account key file.Cloud and self-hosted behave the same: the JWT is signed by the backend that runs the connector, and the private key is stored encrypted like any other credential.
Type
Testing
Not tested against a live noon account: we have no noon credentials. The adapter's live spec signs its own JWT and reads whoami, warehouses, categories and export categories:
NOON_KEY_ID=… NOON_PRIVATE_KEY=… NOON_PROJECT_CODE=… RUN_NOON_MARKETPLACE_LIVE=1 npx jest src/adapters/intl/noon-marketplace(inpackages/backend). The login endpoint itself answers an empty body withINVALID_ARGUMENT: Not enough segments, i.e. it expects exactly this JWT.Commands (repository root unless noted):
packages/backend:npx jest src/connectors/engines/login-token src/connectors/engines/client-assertion: 79 passed. New signedJwt tests: login sends a valid RS256 token (signature checked with the public key),iatin seconds,jtiper login,exp/kidonly when configured, empty claim variable named, bad key not quoted, username/password still required withoutsignedJwt.packages/backend:npm test: first run 753 suites passed, 1 failed (catalog.spec.ts, the static check above, fixed in the last commit), 22,470 tests passed;npx jest src/adapters/catalog.spec.tsafter the fix: 9,951 passed.packages/backend:npx tsc --noEmit -p tsconfig.jsonclean;npm run lint0 errors, 11 pre-existing warnings (unrelatedeslint --fixrewrites reverted).node scripts/validate-adapters.mjs --warn: exit 0, no warning fornoon-marketplace.node scripts/regenerate-catalog.mjs, thennode scripts/adapter-count.mjs --check:OK: every quoted count equals 545 adapters (25 keyless, 8383 tools).(after the rebase on Add 15 catalog adapters and fill gaps in 19 existing ones #1233)Rebased on main after #1233 merged: counts updated to 545, catalog regenerated;
npx jest src/adapters/catalog.spec.ts src/connectors/engines/login-token.service.spec.ts src/connectors/engines/client-assertion src/adapters/intl/noon-marketplace.live.spec.ts: 4 suites, 10,345 passed, 1 skipped (the gated live call);npx tsc --noEmit -p tsconfig.jsonclean.Checklist
npm test)Related Issues
Closes #1235