Customer & User Management

Overview

Covers all customer or user facing authentication endpoints, and support for social/SSO login.

Important: these endpoints are table-driven. By default they authenticate against aurora_customers, but they can target another designated table via authTable when allowed by your deployment.

Auth Table Routing

The same authentication logic can be directed to different identity tables:

  • aurora_customers - default for customer logins.
  • aurora_app_users - common for application user/member auth.
  • custom auth tables - supported when explicitly configured and allowed.

Allowed tables are controlled by server config.

Customer Password Auth Endpoints

POST/customers/signup

Registers a new user in aurora_customers unless authTable overrides the destination table.

Request Body

{
	"email": "customer@example.com",
	"password": "Str0ngPass!",
	"firstname": "Alex",
	"lastname": "Taylor",
	"displayname": "Alex T",
	"appID": 42,
	"authTable": "aurora_customers"
}

Success Response (200 OK)

{
	"status": "Success",
	"_id": "2b9a1c8d1e...",
	"email": "customer@example.com",
	"emailverified": true,
	"firstname": "Alex",
	"lastname": "Taylor",
	"displayname": "Alex T"
}

Rules: password must satisfy complexity policy (uppercase, lowercase, digit, special char, minimum length). Duplicate email returns 409.

POST/customers/login

Authenticates against aurora_customers by default, or another designated authTable. Returns user profile payload (no JWT token from this legacy route).

Request Body

{
	"email": "customer@example.com",
	"password": "Str0ngPass!",
	"appID": 42,
	"authTable": "aurora_customers",
	"extraFields": "phone,address"
}

Success Response (200 OK)

{
	"status": "Success",
	"message": "Login successful",
	"data": {
		"_id": "7c4f0a1d0b...",
		"email": "customer@example.com",
		"firstname": "Alex",
		"lastname": "Taylor",
		"displayname": "Alex T",
		"emailverified": true
	}
}

Error Response (401 Unauthorized)

{
	"status": "Failed",
	"message": "Invalid credentials",
	"data": {}
}

Notes: legacy hashes are upgraded to bcrypt after successful login.

POST/customers/reset-password

Sets a new password using a one-time reset token. Works against the selected authTable.

Request Body

{
	"password": "NewStr0ngPass!",
	"confirmPassword": "NewStr0ngPass!",
	"token": "abc123def456",
	"reset_password_token": "abc123def456",
	"authTable": "aurora_customers"
}

Success Response (200 OK)

{
	"status": "Success",
	"message": "Password reset successfully"
}

Compatibility note: include both token and reset_password_token with identical values.

POST/customers/request-reset

Sends reset email for an account in the selected authentication table.

Request Body

{
	"email": "customer@example.com",
	"appID": 42,
	"url": "https://app.example.com/customer/reset",
	"authTable": "aurora_customers"
}

Success Response (200 OK)

{
	"status": "Success",
	"message": "Email with reset password instructions was sent to customer@example.com."
}

App User Endpoints

App-user routes mirror customer routes but are commonly executed with "authTable": "aurora_app_users".

POST/user/app/signup

Same payload shape as /customers/signup; set authTable to route to aurora_app_users (or another designated auth table).

POST/user/app/login

Same payload shape as /customers/login; set authTable to your target auth table.

POST/user/app/reset-password

Same payload shape as /customers/reset-password.

POST/user/app/request-reset

Same payload shape as /customers/request-reset.

WorkOS AuthKit OAuth

WorkOS AuthKit adds social login/SSO while preserving Infomaxim JWT tokens as the stable API identity format. The linked user can be created in aurora_customers or another allowed authTable.

Flow Summary

  1. Call POST /auth/oauth/authkit/start to obtain an authorization URL.
  2. Redirect browser to WorkOS.
  3. WorkOS returns code and state via the shared redirect relay.
  4. Client sends code and state to POST /auth/oauth/authkit/callback.
  5. API links/creates identity row and returns Infomaxim JWT tokens.

POST/auth/oauth/authkit/start

Creates WorkOS authorization URL for the requested auth table and app context.

Request Body

{
	"authTable": "aurora_customers",
	"state": "random-csrf-state-string",
	"codeChallenge": "base64url-encoded-sha256-of-verifier",
	"codeChallengeMethod": "S256"
}

Success Response (200 OK)

{
	"status": "Success",
	"authorizationUrl": "https://auth.workos.com/sso/authorize?...",
	"state": "encrypted-state-token"
}

POST/auth/oauth/authkit/callback

Exchanges code for Infomaxim JWT token pair and linked user profile in the selected authTable.

Request Body

{
	"code": "01HXYZ...",
	"authTable": "aurora_customers",
	"codeVerifier": "your-pkce-code-verifier",
	"state": "encrypted-state-token"
}

Success Response (200 OK)

{
	"status": "Success",
	"token": {
		"access_token": "eyJhbGciOi...",
		"refresh_token": "eyJhbGciOi...",
		"expires_in": 3600
	},
	"user": {
		"_id": "encrypted-user-id",
		"email": "user@example.com",
		"emailverified": true
	}
}

Security: provider tokens stay server-side; client receives only Infomaxim tokens.

JavaScript Examples (Simple HTML site pattern)

The following snippets reflect the same browser implementation approach used in a simple HTML site signin.html and payment.html.

1) Start social OAuth (Google/Apple)

function startOAuthFlow(provider) {
	var endpoints = ['/api/auth/oauth/authkit/start', '/auth/oauth/authkit/start'];

	function iterate(index) {
		if (index >= endpoints.length) {
			return Promise.reject(new Error('Unable to start sign-in.'));
		}

		return fetch(endpoints[index], {
			method: 'POST',
			headers: { 'Content-Type': 'application/json' },
			body: JSON.stringify({
				provider: provider,
				redirectUri: window.location.origin + '/signin.html',
				authTable: 'aurora_customers'
			})
		})
		.then(function (r) { return r.json(); })
		.then(function (result) {
			var authUrl = (result.data && result.data.authorizationUrl) || result.authorizationUrl;
			if (authUrl) {
				window.location.href = authUrl;
				return;
			}
			return iterate(index + 1);
		});
	}

	return iterate(0).catch(function (err) {
		alert(err.message || 'Unable to start sign-in.');
	});
}

2) Handle callback and persist JWT

var params = new URLSearchParams(window.location.search);
var code = params.get('code');
var state = params.get('state');

if (code) {
	fetch('/api/auth/oauth/authkit/callback', {
		method: 'POST',
		headers: { 'Content-Type': 'application/json' },
		body: JSON.stringify({
			code: code,
			state: state,
			redirectUri: window.location.origin + '/signin.html',
			authTable: 'aurora_customers'
		})
	})
	.then(function (r) { return r.json(); })
	.then(function (result) {
		var payload = result && result.data ? result.data : result;
		var token = payload && payload.token ? payload.token.access_token : '';
		if (!token) {
			throw new Error((payload && payload.message) || result.message || 'Sign-in failed');
		}
		sessionStorage.setItem('auth_token', token);
		localStorage.setItem('auth_token', token);
		window.location.href = 'payment.html';
	})
	.catch(function (err) {
		alert(err.message || 'Sign-in failed');
	});
}

3) Attach token to protected commerce calls

function getJsonHeaders() {
	var token = sessionStorage.getItem('auth_token') || localStorage.getItem('auth_token') || '';
	var headers = { 'Content-Type': 'application/json' };
	if (token) {
		headers.Authorization = 'Bearer ' + token;
	}
	return headers;
}

fetch('/api/ecommerce/addCart', {
	method: 'POST',
	headers: getJsonHeaders(),
	body: JSON.stringify({
		_orderID: 'encrypted-order-id',
		items: [{ productID: 1, Qty: 1, Price: 900 }]
	})
});

4) Direct secure sign-in redirect mode (Simple HTML site flow=signin)

function startAuthKitDirectSignIn() {
	return fetch('/api/auth/oauth/authkit/start', {
		method: 'POST',
		headers: { 'Content-Type': 'application/json' },
		body: JSON.stringify({
			flow: 'signin',
			redirectUri: window.location.origin + '/signin.html',
			authTable: 'aurora_customers'
		})
	})
	.then(function (r) { return r.json(); })
	.then(function (result) {
		var authUrl = (result.data && result.data.authorizationUrl) || result.authorizationUrl;
		if (!authUrl) {
			throw new Error('Unable to redirect to secure sign in.');
		}
		window.location.href = authUrl;
	});
}