Authorization for api.user.m7.org
api.user.m7.org uses access tokens issued by M7 SSO, then applies its own
authorization checks for the current user, organization, or OAuth application.
Some human sessions are additionally bound to a DPoP key, a fingerprint, or
both. Those companion values must accompany every request made with the bound
session.
The API base URL is:
https://api.user.m7.org/api/v2
Supported credentials
| Credential | Public transport | Where it applies | What the API validates |
|---|---|---|---|
| Consumer access token | Authorization: Bearer <token> |
Consumer-owned resources and organization-management operations allowed by the endpoint | Token validity, live SSO session, current user and linked identity, expiry, ownership, and endpoint-specific permissions |
| Organization-member access token | Authorization: Bearer <token> |
Endpoints that explicitly accept an organization member, including /session/me |
Token validity, live member session, organization identity, expiry, and endpoint-specific permissions |
| Organization application access token | Authorization: Bearer <token> |
Organization endpoints that explicitly allow machine applications | Token validity, active application, matching tenant, allowed application type, and the endpoint's current organization-management rules |
| DPoP proof | DPoP: <proof> plus HTU: <absolute-url> |
Required when the human access session was issued with a DPoP binding | ES256 proof signature, public JWK, stored JWK thumbprint, freshness, and the proof's htu value |
| Fingerprint | Fingerprint: <value> |
Required when the human access session was issued with a fingerprint binding | Exact continuity with the fingerprint recorded when the session was issued |
Refresh tokens, ID tokens, authorization codes, client secrets, and grant tokens are not resource credentials. Do not send them to this API in place of an access token.
Obtain an access token
Use an M7 SSO flow appropriate to the caller:
- Interactive applications use the authorization-code flow with PKCE.
- Input-constrained applications can use the device authorization flow.
- Approved confidential applications can use the client-credentials flow for machine access.
See the M7 SSO API documentation
for the authorization, token, device, refresh, and revocation endpoints. The
client secret authenticates a confidential client to the SSO token endpoint; it
never replaces a Bearer access token at api.user.m7.org.
Access tokens are signed JWTs, but clients should treat them as opaque. A decoded claim is not proof that the token is current, accepted by this service, or authorized for a resource.
Send a Bearer request
Send the access token in the Authorization header. For example:
curl --request POST \
'https://api.user.m7.org/api/v2/session/me' \
--header 'Authorization: Bearer ACCESS_TOKEN' \
--header 'Content-Type: application/json' \
--data '{}'
The Bearer scheme is case-insensitive. The public integration contract is the
Authorization header; do not put access tokens in URLs, query strings, or
cookies. Although older clients may use compatibility transports, new clients
must not depend on them.
Never log the complete header or token. Redact it as, for example,
Authorization: Bearer eyJ…<redacted>.
DPoP-bound sessions
When SSO issues a human session with a DPoP binding, the client must retain the corresponding private key and produce a fresh compact proof JWT for every API request. Send both:
Authorization: Bearer ACCESS_TOKEN
DPoP: DPOP_PROOF_JWT
HTU: https://api.user.m7.org/api/v2/session/me
Use an ES256 key. The proof header and payload should contain at least:
{
"typ": "dpop+jwt",
"alg": "ES256",
"jwk": {
"kty": "EC",
"crv": "P-256",
"x": "PUBLIC_X",
"y": "PUBLIC_Y"
}
}
{
"jti": "UNIQUE_PROOF_ID",
"htm": "POST",
"htu": "https://api.user.m7.org/api/v2/session/me",
"iat": 1787191200
}
The private key must not appear in the JWK or leave the client. Use the exact
absolute request URL for both the proof's htu claim and the HTU header, use
the actual uppercase HTTP method for htm, generate a unique jti, and create a
new proof immediately before each request.
Current validation profile
For a DPoP-bound human session, the current resource validator enforces:
- an ES256 signature and
typofdpop+jwt; - a public proof JWK whose thumbprint matches the session's stored binding;
- an
iatwithin five minutes of the server time; and - exact equality between the proof's
htuclaim and the companionHTUheader.
The current resource path does not independently derive the request URL for the
htu comparison, and it does not yet enforce htm, ath, a server nonce, or
jti replay storage. This is therefore M7's current DPoP lineage-key binding,
not a claim of complete RFC 9449 request binding. Clients should nevertheless
populate the standard fields correctly and use one proof per request so they
remain secure and forward-compatible as validation is tightened.
An unbound session does not become DPoP-bound merely because a DPoP header is
present. Conversely, omitting the proof from a bound session causes validation
to fail.
Fingerprint-bound sessions
A fingerprint is an opaque, caller-held continuity value. If it was supplied when the human session was issued, send the exact original value on every API request:
Fingerprint: ORIGINAL_FINGERPRINT_VALUE
Current public issuance helpers use a cryptographically random 64-character hexadecimal value. Generate it locally, do not derive it from easily observed browser attributes, and store it with protection comparable to the access token. The server stores a salted representation and compares the submitted value without exposing the stored binding.
Losing or changing the original fingerprint invalidates use of that bound session. Obtain a new session instead of attempting to reconstruct the value.
Request with both bindings
A session may require both DPoP and a fingerprint:
curl --request POST \
'https://api.user.m7.org/api/v2/session/me' \
--header 'Authorization: Bearer ACCESS_TOKEN' \
--header 'DPoP: DPOP_PROOF_JWT' \
--header 'HTU: https://api.user.m7.org/api/v2/session/me' \
--header 'Fingerprint: ORIGINAL_FINGERPRINT_VALUE' \
--header 'Content-Type: application/json' \
--data '{}'
DPoP and fingerprint companion checks apply to bound human sessions. The organization-machine validation path does not consume these headers; machine access is constrained through the application and tenant checks described below.
Authorization after authentication
A valid token identifies a principal; it does not grant universal access. Authorization is evaluated against current database state on each request.
Consumer users
A consumer token can access the caller's own account resources. Personal OAuth applications must be owned by the current user. Organization operations also require the current user to hold active management access to that organization.
Organization members
An organization-member token is accepted only by endpoints whose authentication
path explicitly supports that principal type. /session/me is one such
endpoint. Do not assume that possession of a member token alone grants access to
organization-management routes; follow each endpoint's documented principal
requirements.
Organization machine applications
Machine access is opt-in per endpoint. For an organization application, the API requires all of the following:
- the token identifies an OAuth client rather than a human user;
- the application is current, active, not archived, and belongs to the same organization named by the request;
- the endpoint explicitly permits organization applications;
- the application has active access through the organization's Management group; and
- the organization retains at least one active human management user.
An organization machine application cannot create a new organization. Machine
tokens are also rejected from human-session endpoints such as /session/me.
Personal owner-proxy machine credentials are a separate restricted profile and
may be used only where an endpoint explicitly documents support.
Roles, audience, and scopes
Organization ownership and Management-group membership are checked from current service data. Current Management-group roles are recorded, but active membership is the authorization boundary used by the existing management checks; clients must not infer additional access from a role label alone.
Request the audience and scopes required by the issuing flow, but do not treat
decoded aud or scope claims as the complete authorization decision. Most
resource operations here additionally rely on current session status,
principal type, resource ownership, tenant equality, and Management-group
membership. An endpoint may impose still narrower checks.
Expiry, refresh, and revocation
The API revalidates a human access session against SSO and current local identity state. A request fails when the session, user, linked identity, ancestor profile, or relevant application is disabled, archived, revoked, expired, or otherwise no longer valid.
- Use the access token's reported lifetime to refresh before expiry.
- Send refresh tokens only to the SSO token endpoint. Never send them to an API resource endpoint.
- A client-credentials access token has no human refresh session; request a new access token by authenticating the confidential client again.
- Revoke tokens through the SSO revocation flow, or through the applicable
api.user.m7.orgcredential-management endpoint when the token was issued and recorded there. - If a DPoP private key or bound fingerprint is lost, leaked, or rotated, revoke the affected session and authorize again with the new binding.
Do not keep retrying a rejected credential. Refresh or reauthorize once, then surface the failure if the replacement is also rejected.
Connection-verification exception
POST /oauth/clients/connections/verify is a verification helper, not a normal
resource endpoint. It intentionally does not authenticate the caller with a
Bearer header. Instead, it accepts the token to inspect and the provider client
identifier in the JSON body:
curl --request POST \
'https://api.user.m7.org/api/v2/oauth/clients/connections/verify' \
--header 'Content-Type: application/json' \
--data '{
"token": "ACCESS_TOKEN_TO_VERIFY",
"provider_client_id": "PROVIDER_CLIENT_ID"
}'
The helper verifies the token cryptographically and evaluates the current provider, consumer, audience, connection, and approved-scope relationship. Its result applies only to that connection check. Do not generalize it into authorization for another endpoint. DPoP and fingerprint companion headers are not part of this verification helper.
Common failures
API responses use the service response envelope; unsuccessful authorization is reported with failure status and a diagnostic comment. Treat comments as diagnostics rather than a stable machine protocol.
| Failure | Typical cause | Client action |
|---|---|---|
| Missing credentials | No accepted access token was supplied | Add the Bearer header; do not substitute a refresh or ID token |
| Failed to validate token / invalid JWT | Bad signature, issuer certificate, token shape, or upstream validation | Discard the token and obtain a new one from SSO |
| Session is expired or revoked | The SSO session is no longer active | Refresh if the flow permits it; otherwise authorize again |
| DPoP required / DPoP invalid | A bound session omitted the proof, used the wrong key, URL, algorithm, or stale time | Generate a fresh proof with the bound key and matching HTU |
| DPoP JWK thumbprint mismatch | The proof key is not the key bound to the session | Use the original private key or establish a new session |
| Fingerprint invalid | The exact session fingerprint was omitted or changed | Send the original value or establish a new session |
| User or linked identity unavailable | The local account mapping is absent, disabled, or expired | Reauthenticate; if persistent, repair the account rather than retrying |
| OAuth client inactive or tenant mismatch | The machine application is disabled, archived, or belongs to another organization | Use the correct active organization application |
| Machine access not allowed | The endpoint does not opt into the machine principal | Use a supported human principal or an endpoint that documents machine access |
| Organization management access denied | Current Management-group or live-human-management requirements are not met | Restore approved management access; do not attempt to bypass the check |
Security checklist
- Keep access tokens, refresh tokens, client secrets, DPoP private keys, and fingerprints out of source control, URLs, analytics, and logs.
- Use TLS and the exact
https://api.user.m7.orghost in production. - Prefer short-lived access tokens and minimum required scopes.
- Validate authorization from API results, not locally decoded token claims.
- Maintain clock synchronization for fresh DPoP proofs.
- Rotate and revoke credentials after suspected disclosure.
- Consult the endpoint documentation for its accepted principal and resource checks before enabling a machine integration.
Related documentation: