Interactive OAuth

Interactive OAuth uses the Authorization Code flow with PKCE (RFC 7636). Use this mode for applications where each end user authenticates individually — patient portals, clinician apps, and integrations where the access token must represent a specific user identity rather than the organization.

App registration

Contact your Huli organization admin to register your application. You will need to provide:

  • Redirect URIs — the exact URIs your application will use for the OAuth callback. Wildcards are not permitted. Include all environments (development, staging, production).
  • Display name — shown on the consent screen.
  • Requested scopes — the scopes your app will request (see Scopes).

You receive a client_id. Public clients (SPAs, mobile apps, the CLI) do not receive a client_secret — PKCE replaces the secret.

Authorization endpoint

https://app.huli.ai/oauth/authorize

Build the authorization URL:

# Generate PKCE verifier and challenge
CODE_VERIFIER=$(openssl rand -base64 48 | tr -d '=+/' | head -c 64)
CODE_CHALLENGE=$(echo -n "$CODE_VERIFIER" | openssl dgst -sha256 -binary | base64 | tr '+/' '-_' | tr -d '=')

AUTH_URL="https://app.huli.ai/oauth/authorize\
?response_type=code\
&client_id=your-client-id\
&redirect_uri=https%3A%2F%2Fyourapp.example.com%2Fcallback\
&scope=system%2FPatient.rs%20system%2FAppointment.rs\
&state=$(openssl rand -hex 16)\
&code_challenge=${CODE_CHALLENGE}\
&code_challenge_method=S256"

echo "$AUTH_URL"

Open the URL in a browser. The user authenticates to HuliPractice and sees the consent screen listing the requested scopes. After approval, the browser redirects to your redirect_uri with a code query parameter.

Token exchange

POST/auth/token
curl -X POST https://api.huli.ai/auth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "code=<code from redirect>" \
  -d "redirect_uri=https://yourapp.example.com/callback" \
  -d "client_id=your-client-id" \
  -d "code_verifier=${CODE_VERIFIER}"

Successful response:

{
  "access_token": "eyJhbGciOiJSUzM4NCJ9...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4...",
  "scope": "system/Patient.rs system/Appointment.rs"
}

Default TTLs: access token 1h, refresh token 30 days.

Refreshing access tokens

curl -X POST https://api.huli.ai/auth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "refresh_token=dGhpcyBpcyBhIHJlZnJlc2ggdG9rZW4..." \
  -d "client_id=your-client-id"

Refresh tokens are single-use (rotation). Each refresh issues a new access token and a new refresh token. Store the new refresh token immediately — the old one is invalidated.

PKCE requirements

PKCE is required for all public clients. Requests to the authorization endpoint without code_challenge and code_challenge_method=S256 return an error.

Never use code_challenge_method=plain. The S256 method is enforced.

State parameter

Always pass state. Verify the state returned in the redirect matches what you sent. This prevents CSRF attacks on the redirect.

Consent screen

The consent screen at app.huli.ai/oauth/authorize shows:

  • Your application name (set at registration).
  • The organization the user is authenticated to.
  • The scopes being requested (in plain language).

The user must actively click Authorize — there is no auto-approval.

Token identity

Interactive OAuth tokens carry the identity of the authenticated user. The access token encodes the user's identity, their organization_id, and the granted scopes. Resource operations are audited against the user, not just the application.

This is the primary distinction from admin bearer tokens and SMART backend services, which represent the application/key rather than an individual.

CLI usage

Interactive OAuth is a supported v1 auth mode on the API. The huli CLI does not include an interactive-login subcommand for it — for CLI access use SMART backend services (huli auth setup) or an admin bearer token. See the CLI reference for the full huli auth reference.