# auth.md

You are an agent. This service exposes an HTTP API secured with OAuth 2.0 / OpenID Connect. Authenticate with the Authorization Code flow with PKCE (S256): discover → pick a method → register → use the credential → handle errors → revoke. Follow the steps in order.

This document lives at https://back2ono.com/auth.md.

## Step 1 — Discover

Fetch this origin's Protected Resource Metadata (RFC 9728) directly at the conventional well-known path below. (A protected endpoint that receives an invalid token, or a token lacking a required scope, also returns a `WWW-Authenticate` header pointing here — but an unauthenticated request is served as anonymous, so do not rely on provoking a challenge.)

- Protected Resource Metadata: [/.well-known/oauth-protected-resource](https://back2ono.com/.well-known/oauth-protected-resource)
- Authorization Server Metadata (RFC 8414): [/.well-known/oauth-authorization-server](https://back2ono.com/.well-known/oauth-authorization-server)
- OpenID Connect Discovery: [/.well-known/openid-configuration](https://back2ono.com/.well-known/openid-configuration)

The authorization-server metadata lists every endpoint, grant type, and scope below. Fetch it first and rely on it as the source of truth.

## Step 2 — Pick a method

This service supports the standard OAuth 2.0 Authorization Code flow with PKCE. Public clients use `code_challenge_method=S256` and the `none` token-endpoint auth method; confidential clients use `client_secret_post`.

> The WorkOS `agent_auth` extension (autonomous `identity_assertion` via ID-JAG, `service_auth`, and the anonymous claim ceremony) is **not yet supported** here. Do not attempt an ID-JAG assertion or call an `identity_endpoint`/`register_uri` for it — use the Authorization Code + PKCE flow below.

## Step 3 — Register

Register a client dynamically (RFC 7591) by POSTing your client metadata to the registration endpoint (advertised as `registration_endpoint` in the authorization-server metadata), `https://back2ono.com/api/oauth/register`. The authorization server may also support Client ID Metadata Documents; check `client_id_metadata_document_supported` in the discovery document before relying on it.

## Step 4 — Claim

Not applicable. The Authorization Code flow obtains user consent interactively at the authorization endpoint, so there is no separate anonymous-registration claim ceremony. (A claim ceremony would only apply to the unsupported `agent_auth` extension noted in Step 2.)

## Step 5 — Use the credential

The OAuth endpoints for this origin:

| Purpose | URL |
| --- | --- |
| Authorization | `https://back2ono.com/oauth/authorize` |
| Token | `https://back2ono.com/api/oauth/token` |
| UserInfo | `https://back2ono.com/api/oauth/userinfo` |
| Revocation | `https://back2ono.com/api/oauth/revoke` |
| Client registration (DCR) | `https://back2ono.com/api/oauth/register` |

1. Generate a PKCE `code_verifier` and its S256 `code_challenge`, then send the user to the authorization endpoint:

```
https://back2ono.com/oauth/authorize?response_type=code&client_id=YOUR_CLIENT_ID&redirect_uri=YOUR_REDIRECT_URI&scope=openid%20profile%20courses:read&code_challenge=CODE_CHALLENGE&code_challenge_method=S256&state=RANDOM
```

2. On approval the user is redirected back with a `code` (and the `iss` parameter, RFC 9207). Exchange it for tokens:

```
curl -X POST https://back2ono.com/api/oauth/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=authorization_code' \
  -d 'code=AUTHORIZATION_CODE' \
  -d 'redirect_uri=YOUR_REDIRECT_URI' \
  -d 'client_id=YOUR_CLIENT_ID' \
  -d 'code_verifier=CODE_VERIFIER'
```

3. Call the API with the returned access token:

```
curl https://back2ono.com/api/oauth/userinfo \
  -H 'Authorization: Bearer ACCESS_TOKEN'
```

Use the `refresh_token` grant at the token endpoint to obtain a new access token without re-prompting the user. Pass a `resource` parameter (RFC 8707) to bind the token to a specific API; it is returned via standard introspection (RFC 7662).

## Step 6 — Errors

Endpoints return standard OAuth 2.0 error responses (RFC 6749 §5.2): a JSON body with an `error` code (e.g. `invalid_request`, `invalid_grant`, `invalid_client`, `invalid_scope`) and a human-readable `error_description`. A protected resource signals an invalid or malformed token with `401 invalid_token`, and a valid token that lacks a required scope with `403 insufficient_scope`; both carry a `WWW-Authenticate` header (see Step 1). A request with no token is served as anonymous rather than challenged.

## Step 7 — Revocation

POST an access or refresh token to the revocation endpoint (`https://back2ono.com/api/oauth/revoke`, RFC 7009) to invalidate it:

```
curl -X POST https://back2ono.com/api/oauth/revoke \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'token=THE_TOKEN' \
  -d 'client_id=YOUR_CLIENT_ID'
```

## Scopes

| Scope | Grants |
| --- | --- |
| `openid` | OpenID Connect authentication |
| `profile` | Basic profile information |
| `email` | Email address |
| `courses:read` | Read access to courses |
| `courses:write` | Write access to courses |
| `students:read` | Read access to students |
| `students:write` | Write access to students |
| `members:read` | Read access to members |
| `members:write` | Write access to members |
| `analytics:read` | Read access to analytics |
| `curriculum:read` | Read access to curriculum |
| `curriculum:write` | Write access to curriculum |
| `orders:read` | Read access to orders |
| `school:read` | Read access to school |
| `school:write` | Write access to school |
| `appearance:read` | Read access to appearance |
| `appearance:write` | Write access to appearance |
| `events:read` | Read access to events |
| `events:write` | Write access to events |
| `membership_plans:read` | Read access to membership plans |
| `membership_plans:write` | Write access to membership plans |
| `coupons:read` | Read access to coupons |
| `coupons:write` | Write access to coupons |
| `posts:read` | Read access to posts |
| `posts:write` | Write access to posts |
| `subscriptions:read` | Read access to subscriptions |
| `subscriptions:write` | Write access to subscriptions |
| `digital_products:read` | Read access to digital products |
| `digital_products:write` | Write access to digital products |
| `comments:read` | Read access to comments |
| `lecturers:read` | Read access to lecturers |
| `lecturers:write` | Write access to lecturers |
| `storage:write` | Write access to storage |
| `forms:read` | Read access to forms |
| `pages:read` | Read access to pages |
| `pages:write` | Write access to pages |
| `account:read` | Read access to account |
| `account:write` | Write access to account |

## Further reading

- OpenAPI specification for this API: [/openapi.json](https://back2ono.com/openapi.json)
- Developer & agent documentation: [https://docs.loopwise.com](https://docs.loopwise.com)
