Skip to content

feat(connectors): OAuth 1.0a engine — make ImmobilienScout24 actually authenticate#324

Merged
keysersoft merged 3 commits into
mainfrom
keysersoft/oauth1-immobilienscout24
Jun 13, 2026
Merged

feat(connectors): OAuth 1.0a engine — make ImmobilienScout24 actually authenticate#324
keysersoft merged 3 commits into
mainfrom
keysersoft/oauth1-immobilienscout24

Conversation

@keysersoft

@keysersoft keysersoft commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Problem

ImmobilienScout24 was unusable: every call returned 401, and the manifest had no instructions explaining where to get credentials (it was the only credential-requiring connector missing them). A customer hit exactly this.

Root cause: IS24 never adopted OAuth 2.0. Its API requires every request to be signed with HMAC-SHA1 per OAuth 1.0a (two-legged: consumer key + secret sign each request). Our connector was configured as OAUTH2 (token exchange + Bearer), which IS24 does not accept — so no credentials could ever work.

Changes

  • oauth1-signer.ts — OAuth 1.0a HMAC-SHA1 signer (two- and three-legged). RFC 3986 encoding, signature base string, param sorting.
  • OAUTH1 auth type in the REST engine. Signed after query/body are built, since the OAuth 1.0a signature folds in query + form-urlencoded body params.
  • OAUTH1 added to the AuthType enum — Prisma schema + migration (same pattern as the prior LOGIN_TOKEN enum addition; auto-applied by prisma migrate deploy on boot).
  • IS24 manifest: OAUTH2OAUTH1, two-legged authConfig (consumerKey/consumerSecret), accurate read-only description, and full instructions — where to get credentials (selfservice.immobilienscout24.de, business account required, sandbox/prod, partner approval, paid price list).

Testing

  • 19 unit tests pass (signer + engine).
  • Signature correctness proven: our base string reproduces the canonical Twitter OAuth example verbatim and the HMAC-SHA1 result was cross-verified independently with openssl dgst -sha1 -hmac (both agree).
  • Live structural check against the real IS24 API: with our signed header IS24 engages its OAuth layer (WWW-Authenticate: OAuth realm="IS24 API" + structured OAuth error); an unsigned request is rejected outright. Only a valid business credential remains (which the end user supplies).

Note on existing connectors

Runtime auth reads from the stored connector row, so the one existing IS24 connector (created under OAUTH2) should be re-created after deploy to pick up OAUTH1 + the new instructions, then have real IS24_CLIENT_ID/IS24_CLIENT_SECRET entered.

…was unauthenticatable)

ImmobilienScout24 never moved to OAuth 2.0: it requires every request to be
signed with HMAC-SHA1 per OAuth 1.0a (two-legged). The connector was configured
as OAUTH2 (token exchange + Bearer), so it returned 401 on every call no matter
what credentials a user entered — and the manifest had no `instructions`
telling users where to obtain credentials at all.

Changes:
- New `oauth1-signer.ts`: OAuth 1.0a HMAC-SHA1 signer (two- and three-legged).
  Signature base string + percent-encoding + param sorting cross-verified
  against the canonical Twitter vector AND independently with `openssl dgst`.
- New `OAUTH1` auth type in the REST engine. Signing happens after query/body
  are built (the signature folds in query + form-urlencoded body params),
  unlike Bearer/API-key auth.
- `OAUTH1` added to the AuthType enum (Prisma schema + migration, same pattern
  as the LOGIN_TOKEN addition).
- IS24 manifest: authType OAUTH2 -> OAUTH1, two-legged authConfig
  (consumerKey/consumerSecret), accurate read-only description, and full
  `instructions` covering where to get credentials (selfservice portal,
  business-account requirement, sandbox/prod, partner approval).

Tested: 19 engine/signer unit tests pass; live structural check against the
real IS24 API confirms our signed Authorization header engages IS24's OAuth
layer (returns `WWW-Authenticate: OAuth realm="IS24 API"`), where an unsigned
request is rejected outright — only valid credentials remain.
@keysersoft keysersoft requested a review from D3nisty as a code owner June 13, 2026 15:11
) {
bodyParams = {};
for (const [k, v] of new URLSearchParams(axiosConfig.data)) {
bodyParams[k] = v;
@keysersoft keysersoft merged commit f708234 into main Jun 13, 2026
10 of 11 checks passed
@keysersoft keysersoft deleted the keysersoft/oauth1-immobilienscout24 branch June 13, 2026 15:20
@github-actions github-actions Bot locked and limited conversation to collaborators Jun 13, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants