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 /authorize URL.
  • Do not place authorization codes in logs, analytics, screenshots, or issue reports.