> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.id.me/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.id.me/_mcp/server.

# iframe Implementations

> Launch an IDMe OAuth 2.0 verification flow inside an iframe.

Use an iframe implementation when you want users to start and complete an IDMe OAuth 2.0 verification flow without leaving your site. The OAuth parameters, redirect URI, token exchange, and attribute retrieval are the same as a standard OAuth 2.0 Authorization Code integration; the main difference is that the IDMe authorization and verification pages render inside an iframe that you host.

> **Warning**
>
> Your iframe parent URL must be approved by IDMe before the embedded flow will load. Send IDMe each exact origin that will host the iframe, including the scheme and host, such as `https://www.example.com`. Include non-standard ports for test environments, such as `https://staging.example.com:8443`.

## Requirements

Before building your iframe implementation, make sure you have:

* An existing IDMe OAuth 2.0 application with a configured `client_id`, `redirect_uri`, and scope.
* An HTTPS page that will host the iframe. Production iframe implementations must be served over HTTPS.
* Each iframe parent origin added to the IDMe iframe-whitelist.
* A stable `state` value for CSRF protection and request correlation.
* PKCE if your application type or security model requires it.

If your site uses a Content Security Policy, allow IDMe pages to load in frames:

**`CSP example`**

```http CSP example
Content-Security-Policy: frame-src https://api.id.me https://verify.id.me;
```

For test environments, use the IDMe test hosts provided by your IDMe contact.

## iframe permissions

Verification flows may require camera and microphone access for document capture, selfie capture, or liveness checks. Delegate those browser permissions to the iframe:

**`iframe permissions`**

```html iframe permissions
<iframe
  title="ID.me verification"
  src="https://api.id.me/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback&response_type=code&scope=YOUR_SCOPE&state=YOUR_STATE&eid=YOUR_EXTERNAL_IDENTIFIER&appID=YOUR_EXTERNAL_APP_ID"
  allow="camera; microphone; fullscreen"
  referrerpolicy="strict-origin-when-cross-origin">
</iframe>
```

If your application sends a `Permissions-Policy` header, allow camera and microphone for the IDMe origins used by your integration:

**`Permissions-Policy example`**

```http Permissions-Policy example
Permissions-Policy: camera=(self "https://api.id.me" "https://verify.id.me"), microphone=(self "https://api.id.me" "https://verify.id.me")
```

Avoid adding a restrictive `sandbox` attribute unless you have tested every verification step. If your application requires sandboxing, the iframe must still allow scripts, forms, same-origin behavior, popups, and the camera or microphone capabilities required by your verification flow.

## Build the iframe page

Start with a normal OAuth 2.0 authorization URL. Replace the placeholder values with your application values:

**`Authorization URL`**

```text Authorization URL
https://api.id.me/oauth/authorize
  ?client_id=YOUR_CLIENT_ID
  &redirect_uri=https%3A%2F%2Fexample.com%2Fcallback
  &response_type=code
  &scope=YOUR_SCOPE
  &state=YOUR_STATE
  &eid=YOUR_EXTERNAL_IDENTIFIER
  &appID=YOUR_EXTERNAL_APP_ID
```

Then render the authorization URL inside an iframe. The example below renders a "Sign in with IDMe" launcher button inside the iframe first. When the user clicks the button, the iframe navigates to the IDMe authorization URL.

**`Sample iframe launcher`**

```html Sample iframe launcher
<iframe
  id="idme-verification-iframe"
  title="ID.me verification"
  allow="camera; microphone; fullscreen"
  referrerpolicy="strict-origin-when-cross-origin">
</iframe>

<script>
  const authorizeUrl = 'https://api.id.me/oauth/authorize?client_id=YOUR_CLIENT_ID&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback&response_type=code&scope=YOUR_SCOPE&state=YOUR_STATE&eid=YOUR_EXTERNAL_IDENTIFIER&appID=YOUR_EXTERNAL_APP_ID';

  const launcherHtml = `<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <base target="_self">
  </head>
  <body>
    <a href="${authorizeUrl.replaceAll('&', '&amp;')}">Sign in with ID.me</a>
  </body>
</html>`;

  document.getElementById('idme-verification-iframe').srcdoc = launcherHtml;
</script>
```

Download sample HTML

## Handle redirects

The user still returns to your registered `redirect_uri` after the IDMe flow completes. Your callback handler should:

* Validate the `state` parameter.
* Exchange the authorization `code` for tokens using your existing backend OAuth flow.
* Retrieve user attributes from the IDMe APIs.
* Render a completion page that works both inside and outside an iframe.

If the callback page is expected to render inside the iframe, make sure your own application does not block that page with `X-Frame-Options` or a `Content-Security-Policy` `frame-ancestors` directive.

## Testing checklist

Use this checklist after IDMe confirms your parent origin is on the iframe-whitelist:

* Open the page from the exact whitelisted origin. `https://www.example.com` and `https://example.com` are different origins.
* Confirm the iframe loads the IDMe authorization page after the user clicks the button.
* Complete the verification flow in a browser with third-party cookies enabled for the test.
* Confirm camera and microphone prompts appear when your policy requires document capture, selfie capture, or liveness.
* Confirm the final redirect reaches your registered `redirect_uri` and your application validates `state`.
* Test on the desktop and mobile browsers you support.

> **Best practice**
>
> Keep a standard redirect implementation available as a fallback. Browser privacy settings, embedded browser restrictions, or customer-specific security headers can prevent any third-party iframe flow from completing even when the iframe-whitelist is configured correctly.