Sign-in
A Mini App can sign in the person using Cowork, with their Micromeet account, and then call Micromeet on their behalf from its own backend. The page never sees a password, a token or the Mini App's secret: Cowork gives the page a one-time code, and the Mini App's backend exchanges that code for tokens.
Only an installed Mini App whose package Micromeet signed, with at least one verified server domain, can sign a person in (see Build and Sign). The module is missing on built-in Mini Apps.
MAESTROSDK.auth.login(params?) Not yet released
Asks Cowork for a one-time code for this Mini App and the person signed in to Cowork.
Parameters
| Field | Type | Required | Description |
|---|---|---|---|
scopes | string[] | No | What the Mini App asks for, for example ['profile:read']. Leave it out to ask for everything Micromeet allowed this Mini App |
The first time, Cowork shows the person a card with the Mini App's name and developer, what it asks for, and the account it will use; Allow or Cancel, Cancel by default. The card shows only on the tab the person is looking at. After the person allowed it once, later calls for the same scopes give a code without a card.
Returns
Promise<{ ok: true; code: string; region: 'SG' | 'HK' | 'ID'; expiresIn: number } | { ok: false; error: string }>
The code works once, for 5 minutes (expiresIn in seconds). Send code and region to your backend.
error | What happened |
|---|---|
unsigned | The package is not signed by Micromeet, or the page is not an installed Mini App |
tampered | A file of the Mini App changed after it was installed; Cowork closed it |
host_signed_out | Nobody is signed in to Cowork, or the page was opened for another account. Cowork opens its sign-in if this is the tab the person is looking at |
user_cancelled | The person cancelled, the tab was in the background, or the account changed while the card was up |
app_not_available | The AppID is not registered in this region, or it is disabled |
version_not_available | This version is not registered, or it was disabled: update the Mini App |
no_server_domain | This version has no verified server domain, or one of its domains is no longer verified (see Server domains) |
scope_denied | A scope Micromeet did not allow for this Mini App, or scopes is not a list of strings |
rate_limited | Too many codes in a minute; try again shortly |
network | Cowork could not reach Micromeet |
MAESTROSDK.auth.status() Not yet released
Promise<{ signed: boolean; host: 'cowork'; hostSignedIn: boolean }>. signed is true when the package's signature is valid and none of its files changed; hostSignedIn when someone is signed in to Cowork. Use it to decide whether to show a sign-in button.
In the Mini App's backend
The backend keeps the client secret Micromeet gave when it registered the AppID, one for each region the Mini App is registered in; never put it in the page or the package. It runs on one of the Mini App's verified server domains (see Server domains). A step-by-step example is in Build a Sign-in Mini App.
Requests from the page
The page's origin is miniapp://<appId>. Answer its requests with Access-Control-Allow-Origin: miniapp://<appId>, and its preflight (OPTIONS) with the methods and headers it sends; otherwise they fail in the page before they reach your code. Keep Micromeet's tokens in the backend and give the page a session of your own.
The helper
@micromeet-ai/miniapp-sdk/server works from ESM or CommonJS on Node.js 18 or later.
import { createMiniappAuthClient, MiniappAuthError } from '@micromeet-ai/miniapp-sdk/server';
const auth = createMiniappAuthClient({ appId: 'ai.example.app', clientSecret: process.env.MINIAPP_SECRET_HK });
const tokens = await auth.exchangeCode({ code, region });
const me = await auth.profile({ accessToken: tokens.accessToken, region: tokens.region });| Option | Required | Description |
|---|---|---|
appId | Yes | The AppID |
clientSecret | Yes | The secret of the region this client calls; create one client per region |
coreUrl | No | (region) => address: which Micromeet to call. Default: production, by region |
fetch | No | Replaces the global fetch |
timeoutMs | No | Per request; default 15000 |
| Function | Returns |
|---|---|
exchangeCode({ code, region }) | Tokens: accessToken, expiresIn (seconds), refreshToken, scope (a list), user: { ref, name, email }, institution: { iid, name }, region |
refresh({ refreshToken, region }) | A new set of tokens; the old refresh token stops working, keep the new one |
revoke({ refreshToken, region }) | Nothing; signs the person out of the Mini App |
profile({ accessToken, region }) | { ref, name, email, institution: { iid, name }, region } (profile:read) |
call({ accessToken, region, path, body? }) | The data of a POST to a Micromeet route that accepts Mini App tokens |
On failure every function throws MiniappAuthError, with Micromeet's code and the HTTP status (see Errors below).
Tokens
| Token | Lifetime | Use |
|---|---|---|
| Access token | 15 minutes | Authorization: Bearer on the routes that accept Mini App tokens |
| Refresh token | 30 days | refresh gives a new pair; each refresh token works once |
- Use the region the code came with for every later call; a token works only in its region.
- A token is for the person and for the institution they had selected in Cowork when they signed in.
user.refis a stable id for this person in this Mini App (another Mini App gets another one): use it as your user key.- A changed password, signing out everywhere, leaving the institution, a disabled version or a disabled Mini App stops the tokens at their next request.
Scopes and routes
| Scope | Route | Returns |
|---|---|---|
profile:read | POST /share/miniapp/profile | { ref, name, email, institution: { iid, name }, region } |
A token works only on the routes in this table, for the scopes the person allowed, and never beyond what the person may do in Micromeet.
Errors
code | HTTP | What happened |
|---|---|---|
invalid_client | 401 | The AppID or the secret is wrong for this region, or the secret was replaced |
invalid_grant | 400 | The code is used, older than 5 minutes or for another AppID; the refresh token is used, revoked or older than 30 days; or the person changed the password, signed out everywhere or left the institution: sign in again |
app_not_available | 400 | The Mini App is disabled in this region |
version_not_available | 400 | The version the person signed in from was disabled: update the Mini App |
needLogin | 401 | On a route: the access token expired or no longer holds. Call refresh; if that fails, sign in again |
forbidden | 403 | On a route: the token does not hold the route's scope, or the person may not do this in Micromeet |
network | — | The helper could not reach Micromeet (status 0) |
params_invalid | 400, or — | A wrong grant_type; or, in the helper, an unknown region or a path that is not a route (status 0, no request sent) |
HTTP calls
A backend in another language makes the same calls. Each is a POST with a JSON body to the Micromeet of the code's region:
| Region | Address |
|---|---|
| SG | https://crms-api.micromeet.ai |
| HK | https://crms-api-hk.micromeet.ai |
| ID | https://crms-api-id.micromeet.ai |
| Path | Body | data in the answer |
|---|---|---|
/miniapp-open/auth/token | { "grant_type": "authorization_code", "app_id", "client_secret", "code" } | { access_token, token_type: "Bearer", expires_in, refresh_token, scope, user: { ref, name, email }, institution: { iid, name }, region }; scope is space-separated |
/miniapp-open/auth/token | { "grant_type": "refresh_token", "app_id", "client_secret", "refresh_token" } | The same |
/miniapp-open/auth/revoke | { "app_id", "client_secret", "refresh_token" } | { revoked: true } |
/share/miniapp/profile | {}, with Authorization: Bearer <access_token> | { ref, name, email, institution: { iid, name }, region } |
A success answers { "code": 0, "success": true, "data": … }. A failure answers { "code": "<error>", "msg": "…", "success": false } with the HTTP status in Errors above.
Related
- Build and Sign Package the Mini App and have Micromeet sign it
- Overview All modules of the Mini App SDK