# Full-page, popup and iframe sign-in

Use the Web/PHP SDK for OAuth and session handling. Add the separate Active
Tags package to open sign-in from any page and finish in a modal on that same
page. One link selects the presentation; its ordinary `href` remains the
full-page fallback.

This guide describes **Web/PHP 0.1.5** with **Active Tags 0.1.1**, which requires
Web/PHP **>=0.1.5 <0.2.0**. These artifacts have been built, verified locally
and staged for download publication. Public download and matching release-tag
verification remain pending. See [package and release status](https://m7.org/docs/sdk/m7-identity/README.md#package-and-release-status)
before choosing an archive. The older Web/PHP 0.1.4 archive does not include
the new background-completion APIs.

## Choose a presentation

| Method | What the visitor sees | SSO response mode |
| --- | --- | --- |
| `full-page` | The current window visits SSO and returns through the registered callback. | `query` with the normal default configuration |
| `popup` | A popup handles SSO sign-in, closes, and the original page shows completion in its modal. | `web_message.opener` |
| `iframe` | The modal contains the SSO page and then shows session completion. | `web_message.parent` |

The client registration must permit the selected response mode and contain the
exact HTTPS callback URI. For iframe sign-in, SSO's framing policy must allow
the exact embedding origin. Keep `M7_RESPONSE_MODE=query` for the normal
full-page route; the enhanced flow selects its response mode per transaction.

The consumer supplies Active Tags, its `ui.dialog` and `ui.tabs` services,
and general dialog, tab, backdrop and typography styles. The package includes
the sign-in-specific HTML, CSS and JavaScript. It uses the existing
`data-dialog-trigger` mechanism and hidden tab controls, rather than bundling
another dialog system. Include one modal per document; multiple sign-in links
can open it.

## Install the assets and adapter

First [install and configure Web/PHP](https://m7.org/docs/sdk/m7-identity/website/installation.md#install-web-php), using
the compatible 0.1.5 package for this integration. Configure the PHP worker's
HTTPS origin, client credentials, registered callback and other SDK settings
as usual. The default callback is `/m7_sso_session/callback`.

Obtain each compatible ZIP together with its `.zip.sha256` and
`.zip.manifest.json` sidecars. Verify before extracting outside the public
document root:

```sh
shasum -a 256 -c m7-identity-web-php-0.1.5.zip.sha256
shasum -a 256 -c m7-identity-active-tags-0.1.1.zip.sha256
unzip m7-identity-web-php-0.1.5.zip -d ./staging
unzip m7-identity-active-tags-0.1.1.zip -d ./staging
```

On systems providing `sha256sum`, use `sha256sum -c` instead. Check the
manifest's package and version against the pair above. The Active Tags ZIP
already includes deployable assets; Node is needed only when rebuilding them.

Use this layout with the default paths:

| Content from the extracted packages | Install location |
| --- | --- |
| Web/PHP `m7_sso_session/` | `public_html/m7_sso_session/` |
| Active Tags `dist/nomap/m7-identity/` | `public_html/vendor/m7-identity/` |
| Active Tags `dist/nomap/examples/flow.php` | `public_html/embedded-sign-in/flow.php` |
| Active Tags `dist/nomap/examples/include.php` | Include once from the application's page shell, alongside its Active Tags setup. |

Keep source, Node tooling, package manifests and release sidecars outside the
public asset directory. For debugging, use `dist/map/` and its matching
examples instead of `dist/nomap/`.

**`flow.php` starts and cancels authorization transactions; it does not include
the modal HTML.** It is a small application-owned POST adapter to
`m7_start_authorization()` and `m7_cancel_authorization()` in the base Web SDK.
The supplied adapter checks the request origin before opening or changing
pending state and returns the SDK's browser configuration. Cancellation is
bound to the matching state. Token exchange and cookie installation stay in
the SDK's validated callback pipeline.

With these default paths, the supplied built examples need no endpoint edits.
Include the generated `include.php` from wherever the application stores its
PHP view fragments. Its wrapper has this configuration:

```php
<div data-m7-identity-config
  data-identity-flow-url="/embedded-sign-in/flow.php"
  data-identity-sdk-module="/m7_sso_session/tpl/popup.js?v=20260923-1"
  data-identity-login-url="/m7_sso_session/?fast_switch=1"
  data-identity-success-action="reload"
  data-identity-success-auto="true">
  <?php require $_SERVER['DOCUMENT_ROOT'] . '/vendor/m7-identity/modal.html'; ?>
</div>
```

If the paths change, update the wrapper, asset URLs in the HTML and adapter's
SDK filesystem imports together. The SDK module must come from the matching
Web/PHP installation. Define the wrapper before Active Tags initializes it.
Never put OAuth client secrets or pending-envelope keys in these attributes.

## Open sign-in from one link

The generated include also supplies a link. This is the unmodified 0.1.1
build's example:

```html
<a href="/m7_sso_session/?fast_switch=1"
  data-activetag at-name="identity-sign-in"
  at-at="import:/vendor/m7-identity/js/sign-in-trigger.js?v=0.1.1-ca23932bdf86"
  data-identity-method="iframe"
  aria-haspopup="dialog" aria-controls="embedded-sign-in">Login</a>
```

Set `data-identity-method` to `iframe`, `popup` or `full-page`. Use the label
“Switch account” when the application already has a session. The handler reads
the method on activation, so the attribute can also be changed on an existing
link. An Active Tags `activate` pipeline can invoke it; popup activation must
run synchronously from a user gesture.

Keep the normal full-page route in `href`. A click before initialization, a
missing modal dependency, or an omitted or unknown method follows that link.
Modified clicks, non-primary clicks and explicit targets retain ordinary link
behavior. Do not attach `data-button-proxy` or `data-dialog-trigger` to this
link; the modal already contains its own hidden dialog opener.

After customizing and rebuilding, copy the new link from the emitted
`examples/include.php`: its revision changes with the built content. Deploy
the complete asset directory and matching examples together so all entry
points share the same modal controller module.

## Complete login on the current page

For iframe sign-in, the modal moves from preparation to the SSO frame, then
to “Logging in…”. For popup sign-in, the original page opens that completion
panel after receiving a validated response and closing the popup.

The base SDK checks the SSO response's origin, sender window, issuer, state
and pending transaction. With `output_mode=iframe`, it submits the response
through a hidden **same-origin callback iframe**, performs token pickup,
installs cookies and completes activation. It signals the parent instead of
forwarding to the configured post-login page. Only validated completion
advances the modal to success; an iframe `load` event alone is insufficient.

`response_mode` controls delivery from SSO. `output_mode` controls how the
consumer callback finishes. They are separate: popup sign-in can use
`web_message.opener` with `output_mode=iframe`. Both presentations use the
same base SDK and callback route. The ordinary full-page flow keeps its
normal post-login navigation.

Choose the success behavior on the configuration wrapper:

| `data-identity-success-action` | `data-identity-success-auto` | Result after the session is installed |
| --- | --- | --- |
| `reload` | `false` | Show Success; clicking reloads the current page. |
| `reload` | `true` | Reload the current page automatically. |
| `close` | `false` | Show Success; clicking closes the modal. |
| `close` | `true` | Close the modal automatically. |

The action defaults to `reload`; an unknown action also uses `reload`.
Automatic completion requires the exact value `true`; omission waits for a
click. The generated include chooses automatic reload for both iframe and
popup completion.

The cookie is installed **before** any success action. Reload refreshes the
host's avatar and other session-dependent content. With `close`, the host
owns those UI updates; this package does not add automatic profile hydration
or a public completion-event API.

## Rebuild after customization

From the extracted Active Tags package, use Node.js 20 or newer:

```sh
npm ci
npm run build
```

Edit `m7-identity/modal.html`, `m7-identity/modal.css`, or the modules in
`m7-identity/js/`, then repeat `npm run build`. This standalone Node build uses
the locked esbuild dependency and needs neither Python nor the SDK repository.

| Command | Output |
| --- | --- |
| `npm run build` | Both variants below. |
| `npm run build:nomap` | Minified assets and matching examples in `dist/nomap/`. |
| `npm run build:map` | Minified assets, source maps and matching examples in `dist/map/`. |

The direct entry point is `node scripts/build.mjs`; add `--with-map` for the
debug variant. Copy the entire output's `m7-identity/` directory into the
vendor location and use that variant's generated examples. The shared
content-derived revision updates local module and stylesheet URLs together.
It does not change your SDK URL or endpoint configuration.

The build keeps shared ES modules and does not bundle Active Tags or another
OAuth implementation. The package's npm project is for local builds; no npm
registry installation is advertised. Source maps contain source code, so
choose the deployment variant accordingly.

## Browser fallback and SSO policy

The popup is reserved during the click, before lazy imports or network work.
When opening returns no usable window, returns the current window, or fails
to navigate, the component cancels its pending transaction and starts the
full-page route. It also falls back if the original `about:blank` document is
still present 15 seconds after navigation was attempted.

This is a startup check, not a detector for Safari's tab count. A changed
document or cross-origin navigation counts as progress; a manually closed
popup is cancellation. The code cannot recover the opener if the browser
unloads it. The full-page fallback remains available for other failures.

Cross-site iframe cookies and storage depend on browser policy. Framing
permission and cookie attributes do not override browser blocking. Use the
popup or full-page presentation when the browser cannot maintain SSO state
inside the iframe.

For M7 consumer accounts, the SSO preference `sso.require_dpop` is enabled
only by boolean `true`; missing or false means off. When off, SSO does not
bind or check its root browser session using DPoP, and retains its other
session checks. When on, SSO requires that proof and asks iframe sign-in to
continue through the full-page route. Tenant credentials retain their
separate SSO policy. **This preference applies to the SSO root session only;
each customer application sets its own token/session DPoP policy.**

The SDK validates an SSO `m7-identity:full-page-required` message against the
active iframe, exact origin, issuer and state, with reason
`sso_dpop_required`. The modal cancels the matching pending flow and follows
its configured same-origin HTTPS `data-identity-login-url`. This control
message is not login success and cannot supply an arbitrary redirect URL.

## Check the integration

Verify the ordinary link before Active Tags initializes. Then test each
enabled method, cancellation, retry, manual success and the chosen automatic
action using a non-production registration. Confirm the current page URL is
preserved on reload and the host sees the installed session.

If the modal does not open, check the Active Tags import and dialog/tab
services. If preparation fails, check the POST adapter path and
[Web SDK diagnostics](https://m7.org/docs/sdk/m7-identity/website/README.md#web-sso-setup-diagnostics). If an iframe is
blank or cannot remember accounts, check framing policy and browser storage
restrictions, then test full-page sign-in. Popup startup failure should follow
the link's full-page URL.

The package checks cover source and built modal/trigger behavior, validated
completion, cancellation and fallback using synthetic browser fixtures.
Clean extraction and rebuild checks do not establish behavior on every mobile
browser; exercise the deployed HTTPS flow in the browsers your site supports.
