Session Lifecycle
This page explains how Mimeeq authentication sessions are established, maintained, and terminated — and what that means for pricing, features, and your integration code.
Sign-In Flow
Mimeeq supports two ways to sign users in: the built-in mmq-auth UI component and the programmatic signIn() method. They follow different validation paths.
┌─────────────────────────────────────────────────────────────────────┐
│ Sign-In Flow │
│ │
│ User submits credentials │
│ │ │
│ ▼ │
│ ┌─────────────────────┐ │
│ │ Credential check │── Fail ──► AuthError │
│ │ (email + password) │ (NotAuthorizedException, │
│ └────────┬────────────┘ UserNotFoundException, etc.) │
│ │ Pass │
│ ▼ │
│ ┌────────────────────┐ ┌────────────────────────────┐ │
│ │ mmq-auth component │ │ signIn() programmatic │ │
│ │ │ │ │ │
│ │ ► Runs customer │ │ ► Returns UserData │ │
│ │ access check │ │ ► NO customer access check │ │
│ │ ► User must be │ │ ► Caller responsible for │ │
│ │ Admin, or │ │ any access enforcement │ │
│ │ Partner for this│ │ │ │
│ │ customer │ └─────────────┬──────────────┘ │
│ └────────┬───────────┘ │ │
│ │ │ │
│ ┌─────┴─────┐ │ │
│ │ │ │ │
│ Access? No access │ │
│ │ │ │ │
│ │ Session terminated │ │
│ │ NoAccess error shown │ │
│ │ mimeeq-user-signed-out │ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ mimeeq-user-signed-in Session active │
│ Session active │
└─────────────────────────────────────────────────────────────────────┘
Using the mmq-auth Component
When a user signs in through the mmq-auth component, two checks happen in sequence:
-
Credential verification — the email and password are validated. If incorrect, an
AuthErroris returned with the appropriate error code. -
Customer access check — if credentials are valid, the user's account is checked for access to the current customer context. The user must belong to the customer as an admin or partner. If they don't have access, the session is immediately terminated and a
NoAccesserror state is shown in the UI.
If both checks pass, mimeeq-user-signed-in is dispatched and the session is active.
Using mimeeqAuth.authorization.signIn() Programmatically
The programmatic signIn() method performs credential verification but does not run the customer access check. It returns a UserData object on success or an AuthError on failure.
const result = await mimeeqAuth.authorization.signIn(email, password, customerId);
if (result && 'name' in result) {
// AuthError — check result.name for the error code
console.error(result.name, result.message);
} else {
// UserData — session is active
console.log('Signed in:', result.email);
}
The optional customerId parameter provides context during authentication. If you need to enforce customer-scoped access when using programmatic sign-in, you are responsible for implementing that check after signIn() returns.
Rate Limiting
To protect against brute-force attacks, sign-in attempts are rate limited. After repeated consecutive failed attempts, further sign-in requests are blocked temporarily. The user receives a LimitExceededException error during the lockout period and must wait before trying again. There is no way to bypass this from the client side.
Password Recovery
The forgot password flow always returns a generic success response regardless of whether the email address exists in the system. This is intentional — Mimeeq does not disclose whether a given email is registered.
Token Lifecycle
Mimeeq sessions are maintained by two tokens:
| Token | Lifetime | Purpose |
|---|---|---|
| Access token | 1 hour | Authenticates requests made by the embed |
| Refresh token | 3 months | Obtains new access tokens silently |
Sign In
│
▼
Access Token (1h) ◄──── Refresh ◄──── Refresh Token (3 months)
│ ▲
│ expires │ automatic
│ │ (≤60s before expiry)
▼ │
Token refresh ──────────────┘
│
│ Refresh token expired?
│
├── No ──► New access token, session continues
│
└── Yes ──► Session expired, user must sign in again
Token refresh is handled automatically — you do not need to manage it. The getToken() and getUserData() methods always fetch a fresh token when the refresh token is valid. The embed's request layer also proactively refreshes tokens that are close to expiry (within 60 seconds) before making requests.
In practice, a user who signs in once will remain authenticated for up to 3 months without any interaction required. After the refresh token expires, the next request requiring authentication will fail and the user will need to sign in again.
Session Expiry and Pricing Fallback
When a session expires or a user signs out while a configurator is already loaded, the impact depends on what type of data the embed needs. Resources that were loaded at startup are cached and remain available. Live data that requires authentication falls back to the unauthenticated state.
Authenticated Session Active
│
│ Product loaded:
│ ► 3D models, meshes, scenes ──── cached ✓
│ ► Materials, images ──────────── cached ✓
│ ► Rules (standard + modular) ─── cached ✓
│ ► Embed template config ──────── cached ✓
│ ► Custom fields, custom UI ───── cached ✓
│ ► Customer / template data ───── cached ✓
│
▼
Session Expires / Sign Out
│
│ Still works:
│ ► Option selection, configuration changes
│ ► 3D scene interaction (rotate, zoom)
│ ► History (undo/redo)
│
│ Falls back:
│ ► Pricing → reverts to public pricing
│ ► Company-specific price lists → lost
│ ► Currency / VAT from company → reverts to public defaults
│ ► Restricted products → no longer accessible on reload
│ ► Favourites / saved scenes → read-only until re-auth
│ ► Basket (if login-required) → add-to-cart disabled
│ ► File downloads (if restricted) → unavailable
│ ► 3D export (if restricted + enabled on product) → button hidden
│
└──► User signs in again → full authenticated state restored
Pricing Fallback in Detail
The most significant consequence of session expiry is the pricing transition. While authenticated, the configurator may be showing company-specific pricing — potentially in a different currency, with different VAT rules, and from a different price list than what public visitors see.
Once the session is no longer valid, all pricing requests fall back to public pricing. This means:
- The price list resolves from the embed template's Public Price List Group instead of the company assignment
- Currency may change (e.g., from EUR back to USD)
- VAT display may change (e.g., from inclusive to exclusive)
- Price type reverts to whatever is set on the public group
This transition happens silently — the configurator continues to display prices, but they are now public prices. The pricing.prices observer will emit the new values as they update.
If your integration relies on authenticated pricing, listen for mimeeq-user-signed-out and prompt the user to sign back in rather than letting them continue with public pricing silently.
document.addEventListener('mimeeq-user-signed-out', () => {
// Authenticated pricing is no longer active
showReauthPrompt('Your session has expired. Sign in to see your pricing.');
});
What About Already-Loaded Products?
A product that has already been loaded and rendered will continue to work interactively after session expiry. Option selection, 3D manipulation, and configuration history all operate on cached data and do not require ongoing authentication.
However, if the user navigates to a different product or reloads the page, products with Restricted or Private privacy will no longer load. The embed will render nothing — no error, just an empty space.
Authentication Events
Listen for these events to keep your application's state synchronized with the authentication state:
| Event | Payload | When it fires |
|---|---|---|
mimeeq-auth-loaded | — | Auth library is initialized and ready to use |
mimeeq-user-signed-in | { firstName, lastName, email } | Session successfully established |
mimeeq-user-signed-out | — | Session terminated (explicit sign-out or NoAccess enforcement) |
mimeeq-login-success | LoginSuccessEventPayload | Login UI completed successfully |
mimeeq-logout-success | — | Logout UI completed |
Waiting for the Auth Library
The auth library loads asynchronously. Wait for mimeeq-auth-loaded before calling any mimeeqAuth methods:
document.addEventListener('mimeeq-auth-loaded', () => {
// Safe to use mimeeqAuth methods
mimeeqAuth.authorization.getUserData().then((user) => {
if (user && !('name' in user)) {
updateUI('authenticated', user);
} else {
updateUI('anonymous');
}
});
});
Tracking Auth State Changes
// Respond to sign-in
document.addEventListener('mimeeq-user-signed-in', (event) => {
const { firstName, lastName, email } = event.detail;
showUserGreeting(firstName);
enableAuthenticatedFeatures();
});
// Respond to sign-out or session expiry
document.addEventListener('mimeeq-user-signed-out', () => {
clearUserGreeting();
disableAuthenticatedFeatures();
});
mimeeq-user-signed-in fires even in the NoAccess path — when a user's credentials are valid but they don't have access to the current customer, the sign-in event fires briefly before mimeeq-user-signed-out follows immediately. If you are using these events to drive application state, treat mimeeq-user-signed-out as the authoritative signal for the final session state.
Authentication Errors
Sign-in and session methods return an AuthError object when something goes wrong. The presence of a name field on the result distinguishes errors from success:
const result = await mimeeqAuth.authorization.signIn(email, password);
if (result && 'name' in result) {
// result is an AuthError
switch (result.name) {
case 'NotAuthorizedException':
showError('Incorrect email or password.');
break;
case 'LimitExceededException':
showError('Too many attempts. Please wait and try again.');
break;
case 'UserNotConfirmedException':
showError('Please verify your email address first.');
break;
default:
showError(result.message);
}
} else {
// result is UserData — sign-in succeeded
}
Error Codes
| Code | When it occurs |
|---|---|
NotAuthorizedException | Incorrect email or password |
UserNotFoundException | No account exists for this email |
UserNotConfirmedException | Account exists but email verification has not been completed |
UserAlreadyAuthenticatedException | A sign-in was attempted while a session is already active |
NoAccess | Credentials were valid but the user has no access to the current customer |
LimitExceededException | Too many failed sign-in attempts — the account is temporarily locked |
CodeMismatchException | The verification code provided during password reset is incorrect or expired |
NetworkError | A connectivity issue prevented the request from completing |
emptyUsername | Email field was empty |
emptyPassword | Password field was empty |
emptyCode | Verification code field was empty during password reset |
Checking Session State
You can check whether a user is currently signed in at any time:
// Get current user data (returns UserData or null)
const user = await mimeeqAuth.authorization.getUserData();
if (user && !('name' in user)) {
console.log('Signed in as:', user.email);
} else {
console.log('No active session');
}
// Get the current access token (for custom API calls)
const token = await mimeeqAuth.authorization.getToken();
Both getUserData() and getToken() automatically refresh the access token if needed. They return fresh data as long as the refresh token is still valid.
Sign-Out
Signing out terminates the session and clears all tokens:
const result = await mimeeqAuth.authorization.signOut();
if (result === true) {
// Session terminated successfully
window.location.reload(); // Reset application state
}
Reloading the page after sign-out ensures the application state is completely reset — cached authenticated data is cleared and the configurator reinitializes in the unauthenticated context.
Next Steps
- Authentication Methods — sign-in UI and programmatic methods
- User Profile — profile management for authenticated users
- Password Recovery — forgot password flow
- Pricing Overview — how pricing resolves by authentication state
- Product Visibility — how auth affects product access