QualityDocD ships two independent authentication systems that serve different integration audiences. The Node.js REST API (default portDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/juescoryisus/QualityDocD/llms.txt
Use this file to discover all available pages before exploring further.
5000) issues tenant-scoped JWTs identified by companySlug, making it the right choice for multi-tenant application clients. The .NET MVC API exposes a simpler /api/auth surface used by the PHP portal and external tooling integrations. Both systems sign tokens with HMAC-SHA256 and accept them through the standard Authorization: Bearer <token> HTTP header.
Overview
| Property | Node.js API | .NET API |
|---|---|---|
| Login endpoint | POST /auth/login | POST /api/auth/login |
| Signing secret | SESSION_SECRET env var | ApiAuth:JwtSecret config key |
| Algorithm | HS256 | HS256 |
| Token lifetime | 24 hours | 8 hours (expires_in: 28800) |
| Tenant scoping | Yes — via companySlug | No |
The Node.js API’s
SESSION_SECRET and the .NET API’s ApiAuth:JwtSecret are separate secrets. Tokens issued by one system are not valid on the other.Node.js API
POST /auth/login
Authenticates a user by email address within a specific company tenant. ThecompanySlug field resolves the tenant — it must exactly match the slug column in the companies table. The user is then looked up by email within that company, and the supplied password is verified against the stored bcrypt hash.
The user’s email address. Must belong to the company identified by
companySlug.The user’s plaintext password. Compared against a bcrypt hash server-side.
The URL-safe identifier of the company tenant (e.g.
"my-company"). Must match an existing record in the companies table.Signed JWT. Valid for 24 hours. Include this value in the
Authorization: Bearer header on subsequent requests.A snapshot of the authenticated user’s profile at login time.
token contains:
| Claim | Type | Description |
|---|---|---|
userId | number | The user’s primary key |
companyId | number | The user’s company |
companySlug | string | The company’s slug (e.g. "my-company") |
role | string | The user’s role string |
| Status | Condition |
|---|---|
400 Bad Request | One or more required fields (email, password, companySlug) are missing or not strings |
401 Unauthorized | The companySlug does not match any company, the email is not found within that company, or the password is incorrect |
POST /auth/validate
Verifies a JWT that was previously issued by the Node.js login endpoint and returns its decoded payload. This endpoint does not require anAuthorization header — the token is passed in the request body. It is primarily useful for server-side session checks (e.g. from a background worker or a second microservice).
A JWT string previously returned by
POST /auth/login.true if the token is a well-formed JWT signed with the correct secret and has not expired; false otherwise.The user’s primary key extracted from the token, or
null when valid is false.The user’s company ID, or
null when valid is false.The company’s slug string, or
null when valid is false.The user’s role string, or
null when valid is false.This endpoint always returns HTTP
200. An invalid or expired token produces { "valid": false, ... } rather than a 401. Check the valid field in your application logic.| Status | Condition |
|---|---|
400 Bad Request | The token field is missing from the request body |
.NET API
POST /api/auth/login
Authenticates a user against the .NET application’s SQL Server database. Theusername field is matched against the Username column in the Users table (case-sensitive depending on database collation). This endpoint is used by the PHP portal and any external integration that does not require multi-tenant scoping.
The user’s username. Matched against the
Username column in the Users table. The user must also have IsActive = true.The user’s plaintext password. Verified against a BCrypt hash stored in
PasswordHash.Signed JWT issued by the .NET
ApiTokenService. Valid for 8 hours (configurable via ApiAuth:ExpirationHours).Token lifetime in seconds. Default is
28800 (8 hours).The authenticated user’s profile.
| Status | Condition |
|---|---|
400 Bad Request | username or password is missing or blank |
401 Unauthorized | No matching active user found, or BCrypt verification fails |
POST /api/auth/validate
Verifies a JWT issued by the .NET login endpoint. The token is validated against theApiAuth:JwtSecret secret, the QualityDocD issuer, and the QualityDocD-Clients audience, with a 5-minute clock skew allowance.
A JWT string previously returned by
POST /api/auth/login.true when the token passes all validation checks (signature, issuer, audience, and expiry); false otherwise.The user’s primary key. Present only when
valid is true.The user’s login username. Present only when
valid is true.The user’s email address. Present only when
valid is true.The user’s role string. Present only when
valid is true.The user’s department. Present only when
valid is true.| Status | Condition |
|---|---|
400 Bad Request | The token field is missing or blank |
GET /api/auth/me
Returns the profile of the currently authenticated user. The token is read from theAuthorization: Bearer header (the same header used by all other protected endpoints). This is a convenient way for a client to confirm its identity and fetch up-to-date profile data without re-parsing the JWT locally.
Example request
The authenticated user’s primary key.
The authenticated user’s login username.
The authenticated user’s email address.
The authenticated user’s role string.
The authenticated user’s department.
| Status | Condition |
|---|---|
401 Unauthorized | The Authorization header is missing, malformed, or contains an invalid/expired token |