Authorization requests and PAR
The authorization endpoint is the browser entry point for authorization code flow:
GET https://sso.user.m7.org/authorize
Use the discovery document for the live endpoint URL. Authorization requests must use a top-level browser navigation; M7 presents sign-in and related user interaction itself.
Request parameters
| Parameter | Required | Description |
|---|---|---|
client_id |
Yes | Public identifier of the registered OAuth client. |
redirect_uri |
Yes | Exact registered HTTPS callback URI. |
response_type |
Yes | Must be code. |
state |
Yes | Opaque, high-entropy CSRF correlation value. Returned unchanged on success. |
code_challenge |
Yes | PKCE challenge derived from your code verifier. |
code_challenge_method |
Yes | Use S256. Discovery currently lists plain, but /token verifies only the S256 transformation; do not use plain. |
scope |
No | Space-delimited requested scopes. openid, profile, email, groups, and offline_access are the standard M7 scopes. Client policy determines which scopes are granted. |
nonce |
Recommended with openid |
Returned in the ID token, allowing the relying party to bind the token to this browser transaction. |
prompt |
No | none, login, or create. |
max_age |
No | Non-negative maximum authentication age in seconds. |
login_hint |
No | An email address or username hint used to prefill the sign-in experience. |
request_uri |
No | A value returned by PAR. |
M7 accepts only query response mode. It supports only response_type=code.
redirect_uri must be a valid HTTPS URL and match one of the client's
registered redirect URIs exactly, including path, query, and trailing slash.
/authorize currently defers a missing PKCE challenge to the token exchange,
where it fails; therefore code_challenge is required for every working flow.
Prompt values
| Value | Behavior |
|---|---|
none |
Requests a non-interactive result. If M7 cannot continue without interaction, the authorization attempt fails rather than showing a sign-in page. |
login |
Requests fresh sign-in. |
create |
Starts the account-creation path for eligible clients. |
Do not combine unsupported prompt values. M7 currently rejects values such as
consent and select_account.
Success and errors
After successful user interaction, M7 redirects to the registered callback:
https://app.example.com/callback?code=AUTHORIZATION_CODE&state=STATE
The authorization code is confidential, short-lived, and single-use. Exchange
it only from your application. Validate state before using the code, then
send the code and the original PKCE verifier to /token.
When M7 can safely return an error to the callback, it uses a top-level browser
GET with the OAuth error, M7 error_reason, optional safe
error_description, optional opaque trace_id, and original state in the
query. Validate state before acting on either a success or an error. A malformed
request that has no trusted redirect URI receives an error at M7 instead of
being redirected.
See Authorization callback outcomes for the complete error and cancellation matrix, field-dependency rules, retryability, PAR re-entry behavior, and required client actions.
Pushed Authorization Requests (PAR)
PAR lets a client send authorization parameters directly to M7 before the browser redirect. It is useful when request parameters are lengthy or should not appear in the front-channel URL.
POST https://sso.user.m7.org/par
Content-Type: application/x-www-form-urlencoded
Authenticate the client using its registered token-endpoint authentication
method. The PAR request carries the same authorization parameters as
/authorize: client_id, redirect_uri, response_type=code, state, PKCE
parameters, and any optional authorization parameters.
For client_secret_jwt or private_key_jwt, the client assertion audience is
the exact PAR endpoint URL, https://sso.user.m7.org/par.
Example with client_secret_basic:
curl --fail-with-body --silent --show-error \
--request POST 'https://sso.user.m7.org/par' \
--user 'CLIENT_ID:CLIENT_SECRET' \
--data-urlencode 'client_id=CLIENT_ID' \
--data-urlencode 'redirect_uri=https://app.example.com/oauth/callback' \
--data-urlencode 'response_type=code' \
--data-urlencode 'scope=openid profile email' \
--data-urlencode 'state=STATE' \
--data-urlencode 'nonce=NONCE' \
--data-urlencode 'code_challenge=CODE_CHALLENGE' \
--data-urlencode 'code_challenge_method=S256'
The response contains an opaque URI and expiry:
{
"request_uri": "urn:ietf:params:oauth:request_uri:OPAQUE_VALUE",
"expires_in": 600
}
Immediately redirect the browser to /authorize with the returned
request_uri and, optionally, the matching client_id:
https://sso.user.m7.org/authorize?client_id=YOUR_CLIENT_ID&request_uri=REQUEST_URI
Do not add or override request fields in this browser request. M7 hydrates the
stored request; a supplied client_id must match it. Start a new PAR request
if it expires.
Security requirements
- Always use
state, validate it on return, and expire it after one use. - Always use PKCE
S256; a code exchange without a stored challenge fails. - Do not use an unregistered redirect URI or construct a redirect URI from user input.
- Do not send client secrets in the browser or in an
/authorizeURL. - Do not place authorization codes in logs, analytics, screenshots, or issue reports.