feat(auth): add web (authorization-code) auth mode#188
Open
ICantThinkOfAName-tech wants to merge 1 commit into
Open
feat(auth): add web (authorization-code) auth mode#188ICantThinkOfAName-tech wants to merge 1 commit into
ICantThinkOfAName-tech wants to merge 1 commit into
Conversation
Adds a third auth mode alongside Custom Connections and Bearer Token: standard OAuth2 Authorization Code flow with a refresh token persisted to disk, selected via XERO_AUTH_MODE=web. Needed because standard auth-code Xero apps reject the client_credentials grant (invalid_scope), and to support refresh-backed multi-tenant access. - WebAuthXeroClient: loads tokenset, refreshes on expiry, resolves tenant. - token-store.ts: JSON tokenset persistence (XERO_TOKENSET_PATH, 0600). - auth.ts: one-time consent CLI (`npm run auth`) — consent URL + local callback server, exchanges + saves the tokenset. - XERO_AUTH_MODE switch (web|custom|bearer); unset preserves prior behaviour. - README: web-auth setup; .gitignore: .xero-tokenset.json.
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 join this conversation on GitHub.
Already have an account?
Sign in to comment
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
Adds a third authentication mode — Web (Authorization Code) — alongside the existing Custom Connections and Bearer Token modes. It performs the standard OAuth2 authorization-code flow and persists a refresh token, so the server can run headless and auto-refresh.
Motivation
Standard OAuth2 (auth-code) Xero apps reject the
client_credentialsgrant used by Custom Connections (invalid_scope/ "Client credentials scope validation failed"), and Custom Connections don't support refresh-backed, multi-tenant access. Today the only non-custom option is a static bearer token that expires. This adds a first-class, refreshable web-auth path.What's added
WebAuthXeroClient(src/clients/xero-client.ts): loads the persisted tokenset, refreshes it on expiry, and resolves the tenant (XERO_TENANT_IDenv → persisted value →/connections). Surfaces a clear, actionable error pointing tonpm run authwhen no tokenset exists or a refresh fails.src/clients/token-store.ts: small JSON tokenset persistence helper atXERO_TOKENSET_PATH(default<repo>/.xero-tokenset.json, written0600).src/auth.ts+npm run auth: one-time consent CLI — builds the consent URL, opens it, runs a short-lived local callback server to capture the code, exchanges it, resolves the tenant, and saves the tokenset.XERO_AUTH_MODEselector (web|custom|bearer). When unset, behaviour is unchanged (bearer ifXERO_CLIENT_BEARER_TOKENis set, otherwise custom connections)..gitignoreentry for.xero-tokenset.json.Reuses xero-node's built-in OAuth (
initialize/buildConsentUrl/apiCallback/refreshToken) — no new dependencies.New env vars
XERO_AUTH_MODEwebselects this modeXERO_REDIRECT_URIhttp://localhost:5000/callbackXERO_SCOPESoffline_accessXERO_TOKENSET_PATH<repo>/.xero-tokenset.jsonXERO_TENANT_IDBackward compatibility
Fully additive. With
XERO_AUTH_MODEunset the selection logic is identical to before.Testing
Built clean and ran
npm run authend-to-end against a real Xero organisation (consent → tokenset saved → tenant resolved), then exercisedlist-invoices/list-contactswith automatic token refresh on expiry.