# auth.md

UTick (utick.ir) authentication and agent registration.

## Audience

AI agents and automated clients that need to call the UTick API on behalf of
a customer (order and subscription status, product catalog, service health).

## Discovery documents

| Document | URL |
| --- | --- |
| OAuth 2.0 authorization server metadata (RFC 8414) | https://utick.ir/.well-known/oauth-authorization-server |
| OpenID Connect discovery | https://utick.ir/.well-known/openid-configuration |
| Protected resource metadata (RFC 9728) | https://utick.ir/.well-known/oauth-protected-resource |
| JWKS | https://utick.ir/.well-known/jwks.json |
| API catalog (RFC 9727) | https://utick.ir/.well-known/api-catalog |
| OpenAPI description | https://utick.ir/openapi.json |

Issuer: `https://utick.ir` (both the authorization server and the resource).

## Registration

Registration uses a one-time password (OTP) sent by SMS to the customer's
phone number. There is no open self-service registration for machine
identities: a human phone number is required.

```http
POST https://utick.ir/api/v1/auth/send-otp
Content-Type: application/json

{"phoneNumber": "09xxxxxxxxx"}
```

## Obtaining a credential (OTP grant)

Grant type: `urn:ietf:params:oauth:grant-type:otp`

```http
POST https://utick.ir/api/v1/auth/verify-otp
Content-Type: application/json

{"phoneNumber": "09xxxxxxxxx", "otp": "123456"}
```

The credential is delivered as an HTTP-only cookie, never in the JSON body:

```http
HTTP/1.1 200 OK
X-Token-Expires-In: 604800
Set-Cookie: accessToken=<jwt>; HttpOnly; Secure; Domain=.utick.ir; Path=/; Max-Age=604800
```

An automated client reads `accessToken` from `Set-Cookie` and sends it
back as a bearer credential (the cookie and the bearer value are the same
JWT).

## Using the credential

```http
GET https://utick.ir/api/v1/auth/me
Authorization: Bearer <accessToken>
```

- Credential type: `bearer-token` (JWT, HS256), valid for **7 days**.
- There is no refresh grant: once the token expires, run the OTP flow again.
- Anonymous identity type: no account-level identity beyond the verified
  phone number is asserted; claims are documented in
  `https://utick.ir/.well-known/openid-configuration`.
- Claims: `sub`, `phoneNumber`, `name`, `role`.
- Claim reference: `https://utick.ir/auth.md` (this document).
- Revocation: `POST https://utick.ir/api/v1/auth/logout` (revocation event:
  `credential.revoked`); `POST https://utick.ir/api/v1/auth/logout-all`
  revokes every session of the user.

## Unauthenticated endpoints

These endpoints are public and need no credential:

- `GET https://api.utick.ir/api/v1/health`
- `GET https://utick.ir/api/v1/products` — catalog (`search`, `page`, `limit`)
- `GET https://utick.ir/api/v1/blog` — blog posts (`page`, `limit`)
- `GET https://utick.ir/openapi.json`
- every `/.well-known/*` document and `GET https://utick.ir/mcp` (MCP tools
  only read the public endpoints above)

## Rate limits and abuse

Authenticated and public endpoints are rate limited (for example the OTP
verification allows 5 attempts per minute); a burst that exceeds the limit
returns `429`. Never attempt to enumerate customer orders or accounts —
those require the customer's own credential. Support: https://utick.ir/contact
