OAuth & Access

OAuth Connect

A Meta/Google-style "Connect with Washeej" flow: your button opens a popup with a dedicated Washeej sign-in and consent page, then returns the user to your app with an authorization code.

When to use OAuth Connect vs API keys Use OAuth Connect when end users of your platform link their own Washeej accounts (multi-tenant). Use API keys (client-id/client-secret from API Settings) only for server-to-server integration with a single Washeej account you own.

Prerequisites

  1. Create a Developer App in the Developer Portal — you get client_id (wa_…) and client_secret (was_…).
  2. Register your callback URL as a redirect URI on the app. Apps without registered redirect URIs cannot use the authorize flow.
  3. Select the scopes your app needs — users can never grant more than the app registered.

Step 1 — Authorize URL

Point your "Connect with Washeej" button at the authorize endpoint. Add display=popup when opening in a popup window.

Authorize URL
https://app.washeej.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=code&scope=messages:send%20messages:read%20devices:read&state=RANDOM_CSRF&code_challenge=CHALLENGE&code_challenge_method=S256&display=popup
  • If the user is not signed in, Washeej shows a dedicated OAuth sign-in page (compact, popup-friendly, shows your app name) — not the public login page. Password and social sign-in both resume the flow.
  • The consent screen lists the requested permissions with Allow / Cancel.
  • Allow → redirect to redirect_uri?code=wac_…&state=…
  • Cancel → redirect to redirect_uri?error=access_denied&error_description=…&state=… — always handle this case.

Popup pattern (recommended UX)

Open the authorize URL in a popup; your redirect_uri page posts the result back to the opener and closes itself. The code→token exchange must happen on your backend — never expose client_secret in the browser.

JavaScript (partner site)
// 1. Open the Connect popup
const authorizeUrl = 'AUTHORIZE_URL_FROM_STEP_1';
const popup = window.open(authorizeUrl, 'washeej_connect',
  'width=480,height=720,menubar=no,toolbar=no');

// 2. Your redirect_uri page (on YOUR domain) receives ?code=&state=
//    and notifies the opener, then closes itself:
//    window.opener.postMessage({ source: 'washeej', code, state }, 'https://your-app.example.com');
//    window.close();

// 3. Listen for the result in the parent window
window.addEventListener('message', (event) => {
  if (event.origin !== 'https://your-app.example.com') return;
  if (event.data && event.data.source === 'washeej' && event.data.code) {
    // Verify event.data.state matches what you generated, then
    // send the code to YOUR backend to exchange it for tokens.
  }
});

Step 2 — Exchange the code

Codes expire after 10 minutes and are single-use.

cURL
curl -X POST "https://app.washeej.com/oauth/token" \
  -d "grant_type=authorization_code" \
  -d "code=AUTH_CODE" \
  -d "redirect_uri=REDIRECT_URI" \
  -d "client_id=APP_ID" \
  -d "client_secret=APP_SECRET" \
  -d "code_verifier=VERIFIER"
Response
{
  "access_token": "wat_...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "wrt_...",
  "scope": "messages:send messages:read devices:read"
}

Use the access token as Authorization: Bearer wat_… on all API v1 endpoints. Access tokens live 1 hour; refresh tokens live 30 days.

Step 3 — Refresh tokens

Refresh rotates both tokens: the old pair is revoked and a new pair is returned.

cURL
curl -X POST "https://app.washeej.com/oauth/token" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=wrt_..." \
  -d "client_id=APP_ID" \
  -d "client_secret=APP_SECRET"

Disconnect / revoke

Two ways to disconnect at any time:

  • From your platform: a "Disconnect" button that calls the revoke endpoint with either token, then deletes your stored tokens.
  • From Washeej: the user opens Dashboard → Developer → Connected Apps and revokes your app — your stored tokens stop working, so handle 401 invalid_token by prompting to reconnect.
cURL
curl -X POST "https://app.washeej.com/oauth/revoke" \
  -d "token=wat_...or_wrt_..."

Security notes

  • Always send a random state and verify it on return (CSRF protection).
  • PKCE (code_challenge + code_verifier, S256) is strongly recommended.
  • redirect_uri must exactly match a URI registered on your Developer App — validated on both the authorize page and the approve action.
  • Granted scopes are the intersection of what you request and what the app registered.