# Website integration

<!-- m7-identity-discovery:begin -->
## Connect to M7 Identity

Issuer: <https://sso.user.m7.org>

Discovery JSON: <https://sso.user.m7.org/.well-known/openid-configuration>

- [Discovery and signing keys](https://m7.org/docs/api/sso.user.m7.org/discovery-and-keys.md)
- [Integration quickstart](https://m7.org/docs/api/sso.user.m7.org/quickstart.md)
- [Provider profile](https://m7.org/docs/api/sso.user.m7.org/provider-profile.md)
- [M7 Identity SDK and current downloads](https://m7.org/docs/sdk/m7-identity/)

Live discovery supplies endpoint locations and advertised capabilities. Use the
provider profile for the integration contract and current testing status.
<!-- m7-identity-discovery:end -->

For optional encrypted ID tokens, JARM and UserInfo, see
[PHP response encryption](https://m7.org/docs/sdk/m7-identity/response-encryption.md). It requires the documented
Web/PHP 0.1.4 or Token/PHP 0.1.4 and the optional native runtime.
Ordinary supported flows remain usable without the native extension.
For the separate C library and PHP extension, use the
[native component guides](https://m7.org/docs/sdk/m7-identity/README.md#optional-native-runtime), which link
installation, compatibility and release status for each component.

M7 Identity SDK currently supports two PHP website integration roles. Choose
the smallest package that matches the application's responsibility.

| Package | Use it for | Current version |
| --- | --- | --- |
| `web-php` | Browser authorization-code login, same-origin session and profile access, refresh, token acknowledgement, and logout through a PHP backend-for-frontend. | 0.1.4 stable release |
| `token-php` | Local validation of M7 access tokens received by a PHP application or API, plus optional online introspection and UserInfo calls. | 0.1.4 stable release |

An application may use both packages when it owns browser login and separately
protects backend routes. Installing `web-php` does not automatically authorize
the host application's own API routes; the host remains responsible for its
route and resource policy.

For a shared Login/Switch account control, see
[full-page, popup and iframe sign-in](https://m7.org/docs/sdk/m7-identity/website/sign-in.md). The prepared Web/PHP 0.1.5
and Active Tags 0.1.1 pair adds a modal, background session completion,
configurable reload/close behavior and a standalone Node asset build. These
are separate from the published 0.1.4 baseline above; see
[prepared release status](https://m7.org/docs/sdk/m7-identity/README.md#prepared-web-and-active-tags-updates).

For a tenant application that will call browser-direct endpoints from its own
JavaScript, see the [browser-direct JavaScript release and examples](https://m7.org/docs/sdk/m7-identity/website/browser-direct.md).
This is a versioned JavaScript ZIP release with independent components;
it is separate from the PHP packages and Active Tags sign-in package above.

For an organization application using M7's hosted tenant login form, follow
[hosted tenant login setup](https://m7.org/docs/sdk/m7-identity/website/hosted-tenant-login.md). It uses the same Web/PHP
package with a copyable Apache configuration, tenant SSO endpoints, and
application login-group policy.

For a website's confidential backend to call another connected service on a
user's behalf, see [Token Exchange](https://m7.org/docs/sdk/m7-identity/cli/token-exchange.md). It requires
Token/PHP 0.1.4 and explicit application storage; the browser session
bridge does not automatically exchange or replace the user's login bundle.

## Current-source native verification and browser limits

Token/PHP 0.1.4 includes optional `m7crypto` verification for the full
15-profile asymmetric set; the earlier 0.1.2 ZIP does not. It still requires
an explicit algorithm allowlist and compatible public
keys/backend. Ed25519 browser sign-in and refresh have operator-confirmed
acceptance after deploying that source.

The current Web SDK stores complete JWTs in single cookies. ML-DSA-65/87 exceed
the browser cookie limit with signatures alone; ML-DSA-44 is payload-dependent.
Do not enable ML-DSA for this session path until token storage is redesigned
and browser-tested. Device/native crypto support does not remove this limit.
See [native verification and post-quantum use](https://m7.org/docs/sdk/m7-identity/README.md#additional-signing-profiles).

## HMAC tokens

Token/PHP 0.1.4 supports HS256/384/512 local verification with an
explicit secret and m7crypto. Browser login, profile and refresh separately
use the Web SDK's existing authenticated SSO introspection path without that
extension. This integration uses a confidential PHP backend; keep client
secrets on that server. A public browser client using `none` must select an
asymmetric algorithm. The User.M7/SSO guard passed scoped production acceptance
on September 20; persisted legacy-record repair was not tested. See [HMAC setup and
acceptance](../README.md#hmac-verification) for exact runtime and acceptance scope.

## `web-php` capabilities

The website package installs at the stable `/m7_sso_session` path and provides:

* authorization-code login and signup with PKCE;
* pushed authorization requests when configured by the M7 authority;
* server-side code exchange and HttpOnly session cookies;
* browser DPoP integration and request-bound `ath` support;
* encrypted custody and acknowledgement of pending token packages;
* same-origin session and profile operations;
* registered refresh-mode handling; and
* local session clearing plus the configured M7 logout flow.

The host website owns its pages, client registration, deployment secrets,
backend authorization, and the decision to request the current session or
profile.

### Web/PHP 0.1.4 response modes and logout

These capabilities are included in Web/PHP 0.1.4. Earlier archives retain
their original behavior.

`M7_RESPONSE_MODE` selects `query` (the default), `form_post`, `fragment`,
`query.jwt`, `form_post.jwt`, `fragment.jwt`, `jwt`, `web_message.opener`,
`web_message.parent`, or `web_message`. Enable the same mode in the client
registration. Popup and iframe receivers check the exact sender window and
origin, issuer, state and saved transaction before submitting to the
same-origin callback; the generic Web Message mode offers both presentations.
Signed JARM verifies the inner RS256/RS512 signature and claims. Optional
encryption follows the [recipient guide](https://m7.org/docs/sdk/m7-identity/response-encryption.md).

ID-token and logout-token verification supports RS256/RS512 through PHP
OpenSSL and Ed25519 through the optional native extension. With
`M7_ID_TOKEN_SIGNED_RESPONSE_ALG` unset, the incoming supported algorithm is
verified without a default pin. Set it explicitly only to require a specific
supported algorithm. This does not expand JARM or signed UserInfo algorithms.

The default installation adds these notification routes; substitute the
installed base path when registering a nested integration:

| Registration field | Receiver URL | Implemented effect |
| --- | --- | --- |
| `frontchannel_logout_uri` | `https://YOUR_APPLICATION_ORIGIN/m7_sso_session/frontchannel-logout` | A valid GET notification clears active and pending SDK cookies in the current browser. |
| `backchannel_logout_uri` | `https://YOUR_APPLICATION_ORIGIN/m7_sso_session/backchannel-logout` | Validates a POSTed logout token and acknowledges receipt only. |

Keep both session-required registration flags false: these receivers do not
match a stored OIDC session identifier. Front-channel embedding requires the
configured issuer origin to be allowed by the web server's framing policy;
cross-site iframe cookie restrictions can prevent cleanup. Host application
sessions and browser storage require their own cleanup.

**Back-channel receipt does not invalidate SDK or host application sessions.**
Its HTTP 200 response is useful for delivery and validation testing, and must
not be treated as completed back-channel logout. Registering the receiver does
not add session enforcement. The existing logout button and post-logout return
remain separate from these notification routes.

## `token-php` capabilities

The token package can protect PHP application and API code with:

* compact JWT parsing;
* RSA signature and claims validation;
* exact issuer and audience policy;
* scope matching;
* optional request-bound DPoP proof validation;
* trusted certificate resolution and consumer-owned caching;
* separate OAuth token introspection; and
* separate OpenID Connect UserInfo retrieval.

Token/PHP 0.1.4 exposes M7-specific `introspectAcl()` for
[inbound machine access](https://m7.org/docs/sdk/m7-identity/website/inbound-machine-access.md). The published ZIP includes
its options, report and transport dependencies.

## UserInfo response verification

UserInfo has separate ordinary JSON and signed-JWT response paths. The JSON
path requires HTTP 200 with `application/json`, a JSON object, and a nonempty
`sub`; an optional `expected_sub` must match exactly. It does not treat an
ordinary JSON response as a signed identity assertion.

Signed UserInfo is included in the immutable `token-php` 0.1.3 artifact. The
signed path accepts
only `application/jwt` and keeps JWT verification in a dedicated verifier,
segregated from ordinary JSON parsing and response handling.

JWT claims are not returned until all of these checks pass:

1. the success response media type is exactly `application/jwt`;
2. the compact JWT parses canonically and declares `RS256` or `RS512` with a
   usable key ID;
3. the configured issuer's OpenID discovery document reports that exact issuer
   and supplies a safe HTTPS `jwks_uri`;
4. the discovered JWKS contains exactly one applicable RSA signing key for the
   key ID, algorithm, use, and key operations, and the signature verifies;
5. issuer, client-ID audience, and time claims pass with the configured leeway;
6. `sub` is a nonempty string; and
7. any configured `expected_sub` binding matches exactly.

The verifier may refresh the discovered JWKS once for signing-key rotation.
Any media-type, discovery, key, algorithm, signature, claims, subject, or
expected-sub failure returns a failed report without exposing decoded JWT
claims.

Local validation, introspection, and UserInfo are distinct operations. An
introspection or UserInfo response does not silently change a local validation
result.

## Requirements

The current website packages require PHP 8.1 or newer and OpenSSL. `web-php`
also requires PHP cURL, HTTPS, normal PHP session support, and web-server routing
for the stable package path. Use an M7 client registration whose redirect URI,
authentication method, fingerprints, scopes, and lifecycle match the
deployment.

The compiled M7 PHP Crypto extension and its separate C library are optional.
The current native wrapper targets PHP 8.4+; encrypted responses additionally
require matching 0.3+ native components and AES-GCM. Base installation keeps
the requirements above. See [optional native runtime](https://m7.org/docs/sdk/m7-identity/README.md#optional-native-runtime).

Stable `web-php` 0.1.4 accepts each 32-byte fingerprint in
the PHP environment as either 64 hexadecimal or 43 canonical unpadded
base64url characters. This is input normalization only: the SDK continues to
send the server's existing lowercase 64-character hexadecimal fingerprint
format. The local-only pending-envelope key accepts the same two environment
encodings, is decoded to raw key bytes, and is never sent to SSO. Separate
random-generation commands produce different values; convert or print both
encodings from the same bytes when an existing registration must be preserved.

## Install

Follow the [website installation guide](https://m7.org/docs/sdk/m7-identity/website/installation.md) to verify a release,
install either package, and perform the first safe checks.

## OIDC-Connect PHP example

Use the [OIDC-Connect PHP purpose and integration guide](https://m7.org/docs/sdk/m7-identity/website/oidc-connect-php.md)
when an independent website wants to add **Sign in with M7** beside provider
buttons it manages itself. The guide explains the website/M7 ownership
boundary, the deliberate nested callback layout, release
status, and links to the sanitized client-registration card and Apache
deployment template.

## Basic browser integration

After `web-php` is installed and configured, begin login through the local
same-origin route:

```js
window.location.assign("/m7_sso_session/");
```

Resolve the current session from host JavaScript with credentials included:

```js
const response = await fetch("/m7_sso_session/me", {
  method: "POST",
  credentials: "include",
  headers: { "Content-Type": "application/json" },
  body: "{}",
});

const session = await response.json();
if (!response.ok || session.ok !== true) {
  throw new Error(session.error?.message || "M7 session request failed");
}
```

Treat any access token returned by `/me` as sensitive and keep it in memory
only. The `/profile` operation uses the HttpOnly session cookie and does not
return the token.

## Web SSO setup diagnostics

`M7_WEB_SDK_DEBUG` is a Web SDK-only diagnostics switch included in the
immutable `web-php` 0.1.4 artifact. It does not enable debug behavior in
`token-php`.

The setting defaults to `off`. It accepts `1`, `true`, `yes`, or `on` and `0`,
`false`, `no`, or `off`, ignoring case and surrounding whitespace. Any other
value is a configuration error rather than a silent fallback. During a
controlled initial setup, make the setting visible to the web PHP process,
enable PHP `log_errors`, confirm that the worker can write its configured error
log, and reload Apache or PHP-FPM after changing the environment:

```text
M7_WEB_SDK_DEBUG=on
```

Web SDK configuration, session, upstream OAuth, endpoint-response, and fatal
failures are written as structured `[m7-identity-web-php]` error-log records
whether debug mode is on or off. With debug off, package-owned browser
responses keep their normal production-safe shape. With debug on, failed JSON
responses may add an opaque `trace_id` and a `debug` object containing a safe
setup hint; package-owned text failures provide comparable safe guidance. Use
the trace ID to locate the matching PHP error-log entry. It is a diagnostic
reference only and must not drive authorization or application behavior.

Debug detail is sanitized. Logs and responses must not disclose client
secrets, authorization headers, access or refresh tokens, cookies,
authorization codes, PKCE or DPoP material, fingerprints, pending activation
data, or raw upstream bodies. Do not enable PHP `display_errors` as a substitute
for this facility. After login, callback, `/me`, `/profile`, refresh/ACK, and
logout work through the deployed HTTPS path, set `M7_WEB_SDK_DEBUG=off` and
reload the worker. Failures continue to reach the PHP error log with reduced
production-safe context.

## Security boundaries

Keep the installed `m7_sso_session` directory package-owned. Store OAuth client
secrets and pending-envelope keys in the deployment secret manager, not in the
public directory or application source. Never call the package's internal
callback finalizer directly; the validated callback page owns that transition.

Use non-production registration values for the first deployment. Verify the
complete login, callback, acknowledgement, session, profile, refresh, and logout
sequence through the actual HTTPS proxy and PHP worker before production use.

## Current-source organization and email acquisition

- [Consumer organizations, live membership facts and service authorization](https://m7.org/docs/sdk/m7-identity/website/organization-access.md)
- [API User account email list and exact subject validation](https://m7.org/docs/sdk/m7-identity/website/account-emails.md)

These Token/PHP operations are included in the verified 0.1.4 ZIP. Install the
complete package with all org/email classes and facade
wiring. Existing released capabilities and download integrity guidance remain
separate. No org/email executable commands or automatic session ownership are
implied by these library operations.
