lumnik. / scenarios All scenarios · Français

The SaaS behind OAuth2 read without losing a page

Goal Read an OAuth2-protected SaaS without losing a page, and say why when access is refused.

Some orders arrive through a recent SaaS. It gives a client id and a secret, and wants a short-lived token.

manifests/10-orders.yaml
apiVersion: connectors.lumnik.io/v1kind: Connectormetadata:  name: scenario-saas-b  connector_type: rest-generic  scopes: [ecommerce]spec:  base_url: http://host.docker.internal:8098  auth:    kind: oauth2    token_url: http://host.docker.internal:8098/oauth/token    client_id: lumnik-orders    client_secret_env: SCENARIO_SAAS_B_CLIENT_SECRET  endpoints:    - id: orders      path: /api/orders      method: GET      pagination:        kind: page        page_param: page        size_param: size        size: 25        start_page: 1        has_more_path: "$.has_more"        response_path: "$.data"      target:        kind: hybrid        table: ext.saas_orders_b        unique_key: "$.id"        promote:          - { name: customer, path: "$.customer", type: text }          - { name: total, path: "$.total", type: decimal }          - { name: status, path: "$.status", type: text }      incremental:        mode: full
$ lm connector run scenario-saas-b
run scheduled: 8cef175c-419b-4b7a-8b45-a53d536ef2db

$ lm run get 8cef175c-419b-4b7a-8b45-a53d536ef2db
ID        CONNECTOR        ENDPOINT  STATUS     IN   OUT  SKIPPED  DEAD-LETTERS  STARTED           ENDED
8cef175c  scenario-saas-b  orders    Completed  200  200  0        0             2026-11-03 17:08  2026-11-03 17:09
$ lm connector run scenario-saas-b
run scheduled: 9d2928c7-301f-4376-991c-40eb864554cc

$ lm run get 9d2928c7-301f-4376-991c-40eb864554cc
ID        CONNECTOR        ENDPOINT  STATUS     IN   OUT  SKIPPED  DEAD-LETTERS  STARTED           ENDED
9d2928c7  scenario-saas-b  orders    Completed  200  200  0        0             2026-11-03 17:09  2026-11-03 17:10
$ lm source rest test scenario-saas-b
ENDPOINT  METHOD  STATUS  ITEMS  VERDICT
orders    GET     -       0      OAuth2 token refused by the authorization server: HTTP 401 invalid_client
Error: 1 of 1 enabled endpoint(s) did not answer with readable data

$ lm connector run scenario-saas-b
run scheduled: 404c6db3-1334-4494-a9e0-8cfdf0173375

$ lm run get 404c6db3-1334-4494-a9e0-8cfdf0173375
ID        CONNECTOR        ENDPOINT  STATUS  IN  OUT  SKIPPED  DEAD-LETTERS  STARTED           ENDED
404c6db3  scenario-saas-b  orders    Failed  0   0    0        0             2026-11-03 17:10  2026-11-03 17:10
✖ run failed: OAuth2 token refused by the authorization server: HTTP 401 invalid_client

Limits

  • Client credentials only: no browser sign-in, no refresh token, no mTLS.
  • A token under 8 characters is refused: too short to be told from the data the source sends back.
  • Simulated SaaS, synthetic orders.

Sales · SaaS

Orders arrive through a SaaS.

Protected by OAuth2.

30-second tokens, a 40-second run

The problem

The token expires during the read.

  • 30 seconds of life.
  • 40 seconds of reading.

What is not changed

The SaaS stays as it is.

  • Its authorization server.
  • A client id, a secret.

The trap

A page refused in silence.

  • An expired token.
  • A key rotation mid-run.

What had to be written

kind: oauth2

One line.

  • The token asked for and renewed in time.
  • The secret stored, never in the manifest.
  • A 35-line scenario, one manifest.

A refusal

invalid_client, said plainly.

  • At the preflight and on the run.
  • Neither secret nor token shown.

The limit

Client credentials only.

  • No browser, no refresh token.

Try it

The scenario replays locally.

Every step is published with its output.

This scenario runs on lumnik Open, free and open source.

Try lumnik Open →