Sign in
This page documents what your users see when they reach Huudis's sign-in screen. The wire-level OIDC details are covered in OIDC overview.
Where sign-in happens
Sign-in always happens on Huudis's domain, never on your app's. That's the whole point of an identity provider: passwords are entered into one trusted UI, not duplicated across every relying party.
When your user clicks "Sign in" in your app, your app redirects to:
https://huudis.com/login?client_id=oc_xxx&...
The query string preserves the OIDC client_id, redirect_uri, and state so Huudis can return the user to your app once they're authenticated.
What the user sees
The sign-in screen has four primary affordances:
- Email + password — the default. Two fields, one button.
- Social provider buttons — one button per identity provider configured on the workspace (Google, Apple, Facebook). Only shown when the provider is wired and enabled.
- "Forgot your password?" — link to the password-reset flow.
- "Don't have an account? Sign up" — switches to the sign-up form, which posts to
/api/v1/auth/signupwith the sameclient_id.
The branding on the sign-in screen is Huudis's. (Workspace-customised branding is on the roadmap; not shipped yet.)
Email + password
POST /api/v1/auth/login
Content-Type: application/json
{
"email": "alice@example.com",
"password": "<password>",
"clientId": "oc_xxx"
}
Successful response sets an HttpOnly, Secure session cookie on huudis.com, then redirects the browser through the OIDC flow to issue an authorization code for your app.
Errors
| Code | Meaning |
|---|---|
INVALID_CREDENTIALS |
Wrong email or password. We don't disclose which — both errors return the same response code. |
EMAIL_NOT_VERIFIED |
The user signed up but never clicked the verification link. The response includes a "resend" affordance. |
MFA_REQUIRED |
Password was correct but MFA is enrolled. Response includes an mfaChallengeToken. |
ACCOUNT_DISABLED |
A workspace admin disabled this user. Email support to re-enable. |
MFA challenge
When the password is correct but MFA is required, the response is:
{
"data": {
"mfaRequired": true,
"mfaChallengeToken": "mfc_xxxxxxxxxxxx",
"mfaChallengeExpiresAt": "2026-05-12T03:14:00.000Z",
"factors": [
{ "id": "fct_xxx", "kind": "totp", "label": "1Password" },
{ "id": "fct_yyy", "kind": "webauthn", "label": "iPhone Touch ID" }
]
}
}
Huudis renders a chooser if the user has more than one factor; otherwise it posts straight to:
POST /api/v1/mfa/verify-login
{
"mfaChallengeToken": "mfc_xxx",
"factorId": "fct_xxx",
"code": "123456"
}
On success, the session cookie is set and the OIDC flow completes. On failure, the challenge token can be retried — but it expires in 5 minutes and is invalidated after 5 failed attempts.
Sign in with an existing Huudis session
If the user already has a Huudis session cookie (because they signed into another Forjio product earlier today), they don't see the sign-in screen at all — Huudis silently issues an authorization code and redirects back to your app. This is single sign-on.
To force a fresh prompt anyway, pass prompt=login on the authorize URL:
/api/v1/oidc/authorize?...&prompt=login
To force a fresh prompt and force MFA, pass prompt=login mfa.
Next
- Forgot password — password reset flow.
- Social providers — configuring Google, Apple, Facebook.
- OIDC overview — the wire view.