

# **WORKFORCEOS**

**FRONTEND GUIDE FOR AI CODING AGENTS - PART 2 - Authentication Management**

This document covers the authentication features of the **workforceos** project: registration, login, logout, and session management. The project introduction, API conventions, home page, and multi-tenancy setup were covered in the previous introductory prompt — make sure those are implemented before proceeding.

All auth APIs use the auth service base URL with the `/auth-api` prefix (e.g., `https://workforceos.mindbricks.co/auth-api`).

### FRONTEND_URL

The `FRONTEND_URL` environment variable is automatically set on the auth service from the project's **frontendUrl** setting in Basic Project Settings. It is used by the auth service for:
- **Social login redirects** — after OAuth processing, the auth service redirects to `FRONTEND_URL + /auth/callback` (the frontend must have a page at this route; see the Social Login prompt for details)
- **Email notification links** — verification, password reset, and other links in emails point back to the frontend

Defaults if not configured:

| Environment | Default |
|-------------|---------|
| dev | `http://localhost:5173` |
| test | `https://workforceos.prw.mindbricks.com`   |
| stage | `https://workforceos-stage.mindbricks.co` |
| prod | `https://workforceos.mindbricks.co` |

You can customize `FRONTEND_URL` per environment by configuring the `frontendUrl` field in your project's Basic Project Settings (e.g., when using a custom domain).

## Registration Management


Since the application is multi-tenant, there will be two registration process. First one is the `company` register and the other one is `user` registration.

Users are either in SaaS level, like administrators, or in `company` tenant level like `company` owners, admins and users.

### SaaS Level User Registration

SaaS user registration is not public in the application, SaaS users can only be created through `createUser` api which can be called by the `superAdmin` or `saasAdmin` of the SaaS level. Creating a new SaaS user is handled through admin panel which will be described in the next prompt.

SaaS users belong to `root` tenant context and should login from the SaaS entry page. Tenant-end users should not use this login entry.

### Tenant -`company`- Registration

Tenant registraration, creating a new company, is always handled together with tenant owner registration.


Both tenant and tenant owner registration are public in the application, so there will be a company registration page in the frontend, that any user can provide their user and company information together.

Using the `registercompanyOwner` route of the auth API, send the required fields from your registration page. Please create a simple and polished registration page that includes only the necessary fields of the registration API.

The `registerCompanyOwner` API in the `auth` service is described with the request and response structure below.

Note that since the `registerCompanyOwner` API is a business API, it is versioned; call it with the given version like `/v1/registercompanyOwner`.

Registering a `company` and its owner is indeed a user registration which also creates a `company` and assigns its ownership to the created user. The created user instance will have got the `id` of the `company` in its `companyId property automatically.

The provided api body should also include a nested object for the company data object instance to be created.

```json
{
  //..
  "email": "joe.doe@example.com",
  "fullname": "Joe Doe",
  "avatar": "...",
  //..
  "company": {
    //.. 
    "name": "Babil",
    "fullname": "Babil Online BookStore Ltd.",
    "avatar": "..."
  }
}
```


### `Register Companyowner` API
This api is used by public users to register themselves as tenant owners to create both a user account and a company account they own.


**Rest Route**

The `registerCompanyOwner` API REST controller can be triggered via the following route:

`/v1/registercompanyowner`


**Rest Request Parameters**


The `registerCompanyOwner` api has got 6 regular request parameters  

| Parameter              | Type                   | Required | Population                   |
| ---------------------- | ---------------------- | -------- | ---------------------------- |
| avatar  | String  | false | request.body?.["avatar"] |
| socialCode  | String  | false | request.body?.["socialCode"] |
| password  | String  | true | request.body?.["password"] |
| email  | String  | true | request.body?.["email"] |
| company  | Object  | true | request.body?.["company"] |
| fullname  | String  | true | request.body?.["fullname"] |
**avatar** : The avatar url of the user. If not sent, a default random one will be generated.
**socialCode** : Send this social code if it is sent to you after a social login authetication of an unregistred user. The users profile data will be complemented from the autheticated social profile using this code. If you provide the social code there is no need to give full profile data of the user, just give the ones that are not included in social profiles.
**password** : The password defined by the the user that is being registered.
**email** : The email defined by the the user that is being registered.
**company** : The company informatiion for the tenant that the created user will own.
**fullname** : The full name defined by the the user that is being registered.



**REST Request**
To access the api you can use the **REST** controller with the path **POST  /v1/registercompanyowner**
```js
  axios({
    method: 'POST',
    url: '/v1/registercompanyowner',
    data: {
            avatar:"String",  
            socialCode:"String",  
            password:"String",  
            email:"String",  
            company:"Object",  
            fullname:"String",  
    
    },
    params: {
    
        }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "201",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "user",
	"method": "POST",
	"action": "create",
	"appVersion": "Version",
	"rowCount": 1,
	"user": {
		"id": "ID",
		"email": "String",
		"password": "String",
		"fullname": "String",
		"avatar": "String",
		"roleId": "String",
		"emailVerified": "Boolean",
		"companyId": "ID",
		"isActive": true,
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID"
	},
	"company": "Object"
}
```




After a successful registration, the frontend code should handle verification requirements with the same flow style as single-tenant mode. The registration response will include a `user` object in the root envelope; this object contains user information with an `id` field.

### Tenant -`company`- User Registration

User registration for company tenants is public in the application. Please create a simple and polished registration page that includes only the necessary fields of the registration API.

This registration targets an existing `company`, so the tenant context must be provided — attach the `company` codename to the request header.

Using the `registercompanyuser` route of the auth API, send the required fields from your registration page.

The `registerCompanyUser` API in the `auth` service is described with the request and response structure below.

Note that since the `registerCompanyUser` API is a business API, it is versioned; call it with the given version like `/v1/registercompanyuser`.


### `Register Companyuser` API
This route is used by public users to register themselves to tenants that are created by tenant owners.


**Rest Route**

The `registerCompanyUser` API REST controller can be triggered via the following route:

`/v1/registercompanyuser`


**Rest Request Parameters**


The `registerCompanyUser` api has got 5 regular request parameters  

| Parameter              | Type                   | Required | Population                   |
| ---------------------- | ---------------------- | -------- | ---------------------------- |
| socialCode  | String  | false | request.body?.["socialCode"] |
| password  | String  | true | request.body?.["password"] |
| email  | String  | true | request.body?.["email"] |
| fullname  | String  | true | request.body?.["fullname"] |
| avatar  | String  | false | request.body?.["avatar"] |
**socialCode** : Send this social code if it is sent to you after a social login authetication of an unregistred user. The users profile data will be complemented from the autheticated social profile using this code. If you provide the social code there is no need to give full profile data of the user, just give the ones that are not included in social profiles.
**password** : The password defined by the the user that is being registered.
**email** : The email defined by the the user that is being registered.
**fullname** : The full name defined by the the user that is being registered.
**avatar** : The avatar url of the user. A random avatar will be generated if not provided



**REST Request**
To access the api you can use the **REST** controller with the path **POST  /v1/registercompanyuser**
```js
  axios({
    method: 'POST',
    url: '/v1/registercompanyuser',
    data: {
            socialCode:"String",  
            password:"String",  
            email:"String",  
            fullname:"String",  
            avatar:"String",  
    
    },
    params: {
    
        }
  });
```   
**REST Response**


```json
{
	"status": "OK",
	"statusCode": "201",
	"elapsedMs": 126,
	"ssoTime": 120,
	"source": "db",
	"cacheKey": "hexCode",
	"userId": "ID",
	"sessionId": "ID",
	"requestId": "ID",
	"dataName": "user",
	"method": "POST",
	"action": "create",
	"appVersion": "Version",
	"rowCount": 1,
	"user": {
		"id": "ID",
		"email": "String",
		"password": "String",
		"fullname": "String",
		"avatar": "String",
		"roleId": "String",
		"emailVerified": "Boolean",
		"companyId": "ID",
		"isActive": true,
		"recordVersion": "Integer",
		"createdAt": "Date",
		"updatedAt": "Date",
		"_owner": "ID"
	}
}
```




After a successful registration, the frontend code should handle verification requirements with the same flow style as single-tenant mode. Verification Management will be given in the next prompt. The registration response will include a `user` object in the root envelope; this object contains user information with an `id` field.


## Login Management

### Login Identifier Model

The **primary login identifier** for this application is the **email address**. Users register and log in using their email and password.
No mobile field is stored in the user data model. The login page should include an email input and a password input.


### Login Flow

After successful registration and completing any required verifications, the user can log in. Please create a minimal, polished login page as described above.

Note that this page should respect the deployment (environment) selection option made in the home page to set the base URL. If the user reaches this page directly skipping home page, the default `production` deployment will be used.

The login API returns a created session. This session can be retrieved later with the access token using the `/currentuser` system route.

Any request that requires login must include a valid token. When a user logs in successfully, the response JSON includes a JWT access token in the `accessToken` field. Under normal conditions, this token is also set as a cookie and consumed automatically. However, since AI coding agents' preview options may fail to use cookies, ensure that each request includes the access token in the Bearer authorization header.

If the login fails due to verification requirements, the response JSON includes an `errCode`. If it is `EmailVerificationNeeded`, start the email verification flow; if it is `MobileVerificationNeeded`, start the mobile verification flow.

After a successful login, you can access session (user) information at any time with the `/currentuser` API. On inner pages, show brief profile information (avatar, name, etc.) using the session information.

Note that the session/currentuser response has no `id` property; instead, the values for the user and session are exposed as `userId` and `sessionId`. The response combines user and session information.

The login, logout, and currentuser APIs are as follows. They are system routes and are not versioned.

### `POST /login` — User Login

**Purpose:**
Verifies user credentials and creates an authenticated session with a JWT access token.

**Access Routes:**

#### Request Parameters

| Parameter  | Type   | Required | Source                  |
| ---------- | ------ | -------- | ----------------------- |
| `username` | String | Yes      | `request.body.username` |
| `password` | String | Yes      | `request.body.password` |

#### Behavior

* Authenticates credentials and returns a session object.
* Sets cookie: `projectname-access-token[-tenantCodename]`
* Adds the same token in response headers.
* Accepts either `username` or `email` fields (if both exist, `username` is prioritized). The `mobile` field is also accepted when the user has a mobile number on file.

#### Example

```js
axios.post("/login", {
  email: "user@example.com",
  password: "securePassword"
});
```

#### Success Response

```json
{
  "sessionId": "e81c7d2b-4e95-9b1e-842e-3fb9c8c1df38",
  "userId": "d92b9d4c-9b1e-4e95-842e-3fb9c8c1df38",
  "email": "user@example.com",
  "fullname": "John Doe",
  //...
  "accessToken": "ey7....",
  "userBucketToken": "e56d....",
  "sessionNeedsEmail2FA": true,
  "sessionNeedsMobile2FA": true,

}
```

> **Note on bucket tokens:** The `userBucketToken` is for the **external bucket service** (used for general file uploads like documents and product images). **User avatars do not use the external bucket service** — they are uploaded via database buckets (dbBuckets) built into the auth service using the regular `accessToken`. See the Profile or Bucket Management sections for dbBucket avatar upload details.

> **Two-Factor Authentication (2FA):** When the login response contains `sessionNeedsEmail2FA: true or sessionNeedsMobile2FA: true`, the session is **not yet fully authorized**. The `accessToken` is valid but all protected API calls will return `403` until 2FA is completed. **Do not treat this login as successful** — instead, store the `accessToken`, `userId`, and `sessionId`, and navigate the user to a 2FA verification page. The 2FA flow details are covered in the **Verification Management** prompt.

### Error Responses

* `401 Unauthorized`: Invalid credentials
* `403 Forbidden`: Email/mobile verification or 2FA pending
* `400 Bad Request`: Missing parameters

---

### `POST /logout` — User Logout

**Purpose:**
Terminates the current session and clears associated authentication tokens.

#### Behavior

* Invalidates the session (if it exists).
* Clears cookie `projectname-access-token[-tenantCodename]`.
* Returns a confirmation response (always `200 OK`).

#### Example

```js
axios.post("/logout", {}, {
  headers: { "Authorization": "Bearer your-jwt-token" }
});
```

#### Notes

* Can be called without a session (idempotent behavior).
* Works for both cookie-based and token-based sessions.

#### Success Response

```json
{ "status": "OK", "message": "User logged out successfully" }
```

### `GET /currentuser` — Current Session

**Purpose**
Returns the currently authenticated user's session.

**Route Type**
`sessionInfo`

**Authentication**
Requires a valid access token (header or cookie).

#### Request

*No parameters.*

#### Example

```js
axios.get("/currentuser", {
  headers: { Authorization: "Bearer <jwt>" }
});
```

#### Success (200)

Returns the session object (identity, tenancy, token metadata):

```json
{
  "sessionId": "9cf23fa8-07d4-4e7c-80a6-ec6d6ac96bb9",
  "userId": "d92b9d4c-9b1e-4e95-842e-3fb9c8c1df38",
  "email": "user@example.com",
  "fullname": "John Doe",
  "roleId": "user",
  "tenantId": "abc123",
  "accessToken": "jwt-token-string",
  "...": "..."
}
```

Note that the `currentuser` API returns a session object, so there is no `id` property, instead, the values for the user and session are exposed as `userId` and `sessionId`. The response is a mix of user and session information.

#### Errors

* **401 Unauthorized** — No active session/token

  ```json
  { "status": "ERR", "message": "No login found" }
  ```

**Notes**

* Commonly called by web/mobile clients after login to hydrate session state.
* Includes key identity/tenant fields and a token reference (if applicable).
* Ensure a valid token is supplied to receive a 200 response.

After you complete this step, please ensure you have not made the following common mistakes:

1. The raw `/currentuser` API mixes session and user data into a single flat envelope. There is **no `id` property on the raw response** — use `userId` and `sessionId`. 
2. Note that any API call to the auth service should use the `/auth-api` prefix after the application's base URL.

**After this prompt, the user may give you new instructions to update your output or provide subsequent prompts about the project.**
