# Momayaz auth.md

Agent registration and authenticated access for Momayaz for Digital Solutions, a software development agency with a client and staff collaboration platform.

## Discovery and supported registration

Agents can use the user-claimed service_auth flow for an existing verified account. The person signs in and explicitly approves the requested scopes; registration alone grants no access. Anonymous registration and third-party identity assertions are not supported.

- [Protected Resource Metadata](/.well-known/oauth-protected-resource/api) identifies the platform resource and authorization server.
- [Authorization Server metadata](/.well-known/oauth-authorization-server) is the source of truth for the issuer, token and revocation endpoints, and supported registration types.
- [Agent registration endpoint](/agent/identity): POST application/json after the user asks to connect an agent. The procedure is documented below; do not submit registration during passive discovery.

## Scopes

- platform:read: read data the approving account can access, subject to its current role, company and project permissions.
- platform:write: perform authorized changes within the approving account's existing permissions. Request it only for a user-authorized workflow; request both scopes when the workflow also reads data.

## Service information

[Pricing and packages](/packages) · [Terms of service](/terms) · [Privacy policy](/privacy) · [Refund policy](/refund-policy).
For integration assistance, contact [contact@momayaz.co](mailto:contact@momayaz.co) or use the [contact page](/contact).

## Public access

Public packages, published blog posts, discovery documents and the read-only MCP endpoint at /mcp require no account, API key or payment. See [API documentation](/docs/api) and [OpenAPI](/openapi.json).

## Client and staff access

People register at [/register](/register), verify their email and sign in at [/login](/login). The website uses a NextAuth credentials session. Protected API requests are authorized against the current account and resource permissions; a public discovery request grants no access to projects, invoices, messages or files.

## Operator-managed agent access

Authenticated administrators provision integration credentials with POST /api/admin/mcp-clients (name and allowedRoles) and revoke them with DELETE /api/admin/mcp-clients?id=<client-id>. The creation response contains the credential once; listing clients never returns its plaintext. The private local MCP server uses X-Service-Key together with X-Act-As-User. Credentials must be delivered through a secure channel and kept out of browser code, prompts and public documents. Account and per-client role restrictions still apply.

## OAuth for existing scoped integrations

Discover the issuer at [/.well-known/oauth-authorization-server](/.well-known/oauth-authorization-server) and the platform resource at [/.well-known/oauth-protected-resource/api](/.well-known/oauth-protected-resource/api). Public verification keys are at [/oauth/jwks](/oauth/jwks). These routes return HTTP 503 when the service's persistent signing key is unavailable; an unavailable token service is not permission to fall back to an untrusted issuer.

POST /oauth/token using application/x-www-form-urlencoded and HTTP Basic authentication. The Basic username is the issued MCP client ID and the password is its issued secret. Form parameters are grant_type=client_credentials, delegated_user_id=<authorized-user-id>, resource=<site-origin>/api, and scope=platform:read. Request both platform:read and platform:write when an authorized workflow must read and modify data. The legacy global service key cannot be exchanged.

The response contains access_token, token_type=Bearer, expires_in (at most 900 seconds) and scope. Send it as Authorization: Bearer <access_token> to the platform API. Do not send X-Service-Key or X-Act-As-User with a bearer token: its delegated actor cannot be changed. Role, company and resource rules still apply, and read-only tokens cannot modify data or mark project messages read. Acquire another token after expiry; no refresh token is issued.

Endpoint-specific OAuth resource indicators under /api map to the same complete API audience under RFC8707. Protected endpoints' WWW-Authenticate challenges point to path-specific metadata whose resource matches that endpoint. Tokens are never valid at a different origin or at authentication, credential provisioning, connected-agent management, cron or webhook endpoints.

POST /oauth/revoke with the same client Basic authentication, token=<access_token>, and optional token_type_hint=access_token. Revocation is immediate for that token. Revoking the MCP client invalidates every token it issued. Client-key rotation and changes to the delegated account's role, company, password or active state also invalidate tokens.

## Connect an agent with human consent

### 1. Discover the service and choose the registration method

The service_auth profile is supported: register using an email, then obtain human consent. Read https://momayaz.co/.well-known/oauth-protected-resource/api and follow its authorization_servers entry to https://momayaz.co/.well-known/oauth-authorization-server. The agent_auth.identity_endpoint and register_uri identify https://momayaz.co/agent/identity; token_endpoint is https://momayaz.co/oauth/token and revocation_endpoint is https://momayaz.co/oauth/revoke. The protected resource is https://momayaz.co/api.

The requests below are templates for an agent the user has asked to connect. Replace the example email with that user's existing verified account email. Values in angle brackets are response placeholders, not credentials. Do not send registration requests during passive discovery. Keep returned proof handles and tokens in private credential storage.

### 2. Register the agent

Send JSON to the registration endpoint:

```http
POST https://momayaz.co/agent/identity
Content-Type: application/json

{
  "type": "service_auth",
  "login_hint": "your-account@example.com",
  "name": "Your agent name",
  "scopes": ["platform:read"],
  "resource": "https://momayaz.co/api"
}
```

The optional name is unverified display text. scopes defaults to platform:read; request platform:write only when the user intends to authorize changes. A successful registration returns HTTP 201 with this shape:

```json
{
  "registration_id": "<registration ID>",
  "registration_type": "service_auth",
  "claim_url": "https://momayaz.co/agent/identity/claim",
  "claim_token": "<private claim token>",
  "claim_token_expires": "<ISO-8601 expiry>",
  "post_claim_scopes": ["platform:read"],
  "claim": {
    "user_code": "<six-digit code>",
    "verification_uri": "<service-owned verification URL>",
    "expires_in": 600,
    "interval": 5
  }
}
```

Registration grants no account access and returns no access token or identity assertion. The claim ceremony is already started; service_auth does not call the anonymous-only claim initiation endpoint.

### 3. Ask the user to approve, then poll

Show the user the exact returned verification_uri and six-digit user_code. The user signs into their existing verified account, reviews the requested access and explicitly approves or denies on the service-owned page. Only the account matching login_hint can approve. Never ask for, collect or submit the user's password or confirmation code yourself. The ceremony expires in 10 minutes and locks after five incorrect codes.

While waiting, poll the token endpoint. Form-encode each value and substitute the returned claim_token:

```http
POST https://momayaz.co/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aworkos%3Aagent-auth%3Agrant-type%3Aclaim&claim_token=<claim_token>
```

Do not send Basic authentication, cookies, X-Service-Key, X-Act-As-User or delegated_user_id. Wait at least the returned interval before polling (initially 5 seconds). HTTP 400 with error=authorization_pending means continue waiting; slow_down means increase the interval by 5 seconds; expired_token or access_denied means stop. On HTTP 429, respect Retry-After. Do not continue polling after claim_token_expires.

After approval, HTTP 200 returns the first usable credential and the assertion that can obtain subsequent credentials:

```json
{
  "access_token": "<private access token>",
  "token_type": "Bearer",
  "expires_in": 900,
  "scope": "platform:read",
  "identity_assertion": "<private service-signed assertion>",
  "assertion_expires": "<ISO-8601 expiry>"
}
```

Use the actual expires_in from the response; access tokens last at most 900 seconds.

### 4. Use the access token

Send the access_token as an HTTP Bearer credential, for example to read projects visible to the approving account:

```http
GET https://momayaz.co/api/projects?limit=10
Authorization: Bearer <access_token>
Accept: application/json
```

The agent is bound to the approving account, approved scopes and existing resource permissions. Account status, password, role or company changes invalidate the delegation. The agent cannot consent to another agent or manage connected agents using its own token.

### 5. Obtain another short-lived access token

Before the assertion's fixed 24-hour expiry, exchange the returned identity_assertion at the token endpoint. Form-encode the assertion and other values:

```http
POST https://momayaz.co/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&assertion=<identity_assertion>&resource=https%3A%2F%2Fmomayaz.co%2Fapi
```

The response contains access_token, token_type, expires_in and scope. The assertion has its own token type and cannot be used as an API bearer token. An optional scope parameter may narrow the approved scopes but cannot enlarge them. No refresh_token or long-lived service key is returned. After registration expiry, start a new registration and obtain new human approval.

### 6. Revoke access

To revoke the current self-service agent access token, form-encode it and send:

```http
POST https://momayaz.co/oauth/revoke
Content-Type: application/x-www-form-urlencoded

token=<access_token>&token_type_hint=access_token
```

Do not send Basic or Bearer authentication on this revocation request. Successful revocation returns HTTP 200 with no body. Possession permits revoking only that token; it does not revoke the identity assertion. The person can revoke the complete delegation, its assertions and all access tokens at [/settings/agents](/settings/agents). The connected-agents page uses the current browser session and shows only that account's delegations. Operator clients can also be revoked through their existing administrator controls.

NextAuth sign-in remains the human login flow. No third-party identity assertion issuer, anonymous registration, OpenID Connect login, refresh grant or provider event endpoint is advertised.
