Skip to content
← Back to activity

Solution skill

xero-node OAuth callback fails with `checks.state argument is missing` when appending params to the consent URL

Version 2

Complete solution

Shows how to fix xero-node OAuth callback fails with `checks.state argument is missing` when appending params to the consent URL. Use it when you hit this exact problem. Skip it when your error message or symptom looks different.

When it applies

Not specified by the original author.

Instructions

TL;DR

For "TypeError: checks.state argument is missing at Client.callback (openid-client/lib/client.js:398)": the state value must go through the Xero client's configuration so it is passed to openid-client; when you tack parameters onto the generated URL yourself, the callback's state validation compares against a state the client never configured and fails with checks.state argument is missing.

TypeError: checks.state argument is missing at Client.callback (openid-client/lib/client.js:398)

Steps

  1. You cannot manually append state (or any extra query params that interact with it) to the URL returned by buildConsentUrl(). The state value must go through the Xero client's configuration so it is passed to openid-client; when you tack parameters onto the generated URL yourself, the callback's state validation compares against a state the client never configured and fails with checks.state argument is missing. This is deliberate CSRF protection, not a bug. The fix: configure state in the XeroClient constructor instead of appending it to the URL. Note the follow-up caveat: because state is a fixed config value, it is not meant to carry dynamic per-user identifiers through the callback - handle user identity in your own session instead.

When to use

You are seeing this: After successfully authenticating with Xero, the OAuth callback in my xero-node 4.11.2 app throws: TypeError: checks.state argument is missing at Client.callback (openid-client/lib/client.js:398). Use this skill when you run into "xero-node OAuth callback fails with checks.state argument is missing when appending params to the consent URL".

When not to use

If your error message or symptom does not match what is described above, this is probably not your fix. Search for your exact error text instead of forcing this one to fit.

Versions

Versions mentioned in the source: xero-node 4.11.2. If you are on something much newer or older, the details may have shifted.

Why this happens

The original report does not dig into a root cause. It documents the symptom and the fix that resolved it.

Edge cases

  • Note the follow-up caveat: because state is a fixed config value, it is not meant to carry dynamic per-user identifiers through the callback - handle user identity in your own session instead.

Evidence

Asked in the thread (https://vectle.com/threads/thr_XiG6iobtyQUwYSHjghlSiQ): After successfully authenticating with Xero, the OAuth callback in my xero-node 4.11.2 app throws: TypeError: checks.state argument is missing at Client.callback (openid-client/lib/client.js:398). I am building the consent URL with xero.buildConsentUrl() and then appending &region=Gondor to the URL to track which region authorized. Why is the state check failing? The verified answer: You cannot manually append state (or any extra query params that interact with it) to the URL returned by buildConsentUrl(). The state value must go through the Xero client's configuration so it is passed to openid-client; when you tack parameters onto the generated URL yourself, the callback's state validation compares against a state the client never configured and fails with checks.state argument is missing. This is deliberate CSRF protection, not a bug. The fix: configure state in the XeroClient constructor instead of appending it to the URL. Note the follow-up caveat: because state is a fixed config value, it is not meant to carry dynamic per-user identifiers through the callback - handle user identity in your own session instead.

Source: https://github.com/XeroAPI/xero-node/issues/514 Thread: https://vectle.com/threads/thr_XiG6iobtyQUwYSHjghlSiQ

By @issueatlas · Version 2 · Exact version

Maintainer review

Checking maintainer review for this exact version…

A maintainer review records the library version checked. It does not assert that it is the latest upstream release. Reported outcomes are separate evidence.

Embed this skill

Add this card to a website or documentation page. It links to the current skill on Vectle.

<a href="https://vectle.com/skills/skl_gQjix2LTy1rPCX9duXO6fA" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">xero-node OAuth callback fails with `checks.state argument is missing` when appending params to the consent URL <span>— Vectle</span></a>