<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE rfc [
<!ENTITY nbsp "&#160;">
<!ENTITY zwsp "&#8203;">
<!ENTITY nbhy "&#8209;">
<!ENTITY wj "&#8288;">
]>
<rfc xmlns:xi="http://www.w3.org/2001/XInclude" 
     category="info" 
     docName="draft-bouaram-oidc-email-linking-extension-00" 
     ipr="trust200902" 
     xml:lang="en" 
     version="3"
  >

  <front>
    <title abbrev="OIDC Email Linking">OpenID Connect Email Account Linking Extension</title>
    <seriesInfo name="Internet-Draft" value="draft-bouaram-oidc-email-linking-extension-00"/>
    <author fullname="Salim BOU ARAM" initials="S." role="editor" surname="Bou Aram">
      <address>
        <postal>
          <city>Beirut</city>
          <region>LB</region>
          <country>Lebanon</country>
        </postal>
        <email>salimbouaram12@gmail.com</email>
      </address>
    </author>
    <date year="2025" month="8"/>
    
    
<abstract>
  <t>This document extends OpenID Connect's standard email functionality to support secure linking between multiple email accounts. 
  It enables users to associate secondary email addresses with their primary account while maintaining backward compatibility with existing implementations. 
  The extension provides methods for establishing, managing, and utilizing these relationships within the OpenID Connect email scope.</t>
</abstract>
  </front>

  <middle>
    <section anchor="concepts">
      <name>Core Concepts</name>
      <t>The extension operates on these fundamental principles:</t>
      <ol>
        <li><t><strong>Primary Account</strong>: The initial identity that controls all linked accounts</t></li>
        <li><t><strong>Secondary Accounts</strong>: Additional email identities linked to the primary</t></li>
        <li><t><strong>Temporal Validity</strong>: Linkages expire after a defined period</t></li>
        <li><t><strong>Account Resolution</strong>: Secondary logins resolve to the primary identity</t></li>
      </ol>
    </section>

    <section anchor="parameters">
      <name>Protocol Parameters</name>
      <table>  
      <name>Parameters</name>
        <thead>
          <tr>
            <th>Parameter</th>
            <th>Location</th>
            <th>Description</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>linking</td>
            <td>Authorization Request</td>
            <td>boolean (true/false), initiates linking flow when true</td>
          </tr>
          <tr>
            <td>linking_period</td>
            <td>Authorization Request</td>
            <td>number (seconds), validity duration (default: 2592000)</td>
          </tr>
        </tbody>
      </table>
    </section>

    <section anchor="flows">
      <name>Protocol Flows</name>

      <section anchor="linking-flow">
        <name>Linking Flow</name>
        <t>Complete sequence for establishing account linkages:</t>
          <artwork><![CDATA[
+----------+       +----------+       +----------+       
|  Client  |       |  IdP/STS  |      |   User   |       
+----------+       +----------+       +----------+       
     | Auth Request      |                  |                  
     | scope=email       |                  |                  
     | linking=true      |                  |                  
     |------------------>|                  |                  
     |                  | Primary Auth      |                  
     |                  |------------------>|                  
     |                  |                   |                  
     |                  | Show Linking      |                  
     |                  | Consent Screen    |                  
     |                  | (where user adds  |                  
     |                  |  or               |                  
     |                  | selects email     |                  
     |                  | accounts)         |                  
     |                  |------------------>|                  
     |                  | (1-N secondary    |                  
     |                  |  accounts based   |                  
     |                  |  on IdP policy    |
     |                  | and allowed N     |
     |                  | Secondaries)      |                  
     |                  |<------------------|                  
     |                  |   Auth Secondary 1|  
     |                  |<----------------- |
     |                  |  Auth Secondary N |
     |                  |<------------------|
     |                  |                   |
     |           IDP/STS stores Linkages    |                  
     |                  |                   |
     | ID Token with    |                   |                  
     | linking claims:  |                   |                  
     | - primary_email  |                   |                  
     | - secondary_emails[N] |              |                  
     | - expires_at     |                   |                  
     |<-----------------|                   |]]></artwork>
        <t>1. Client initiates with parameters:</t>
        <artwork><![CDATA[
GET /authorize?response_type=code
  &client_id=client123
  &scope=openid%20email
  &linking=true
  &linking_period=604800]]></artwork>
        <t>2. IdP authenticates primary account, the account should be primary or normal (not linked) email account</t>
        <t>3. User authenticates 1-N secondary accounts (IdP-defined limit)</t>
        <t>4. IdP stores linkages with desired expiration timestamp</t>
        <t>5. IdP returns ID token containing:</t>
        <artwork><![CDATA[
{
  "email": "main@example.com",
  "primary": true,
  "linking": {
    "secondary_emails": ["alt1@example.com", "alt2@example.org"],
    "expires_at": 1735689600
  }
}]]></artwork>
      </section>

      <section anchor="unlinking-flow">
        <name>Unlinking Flow</name>
        <t>Unlinking occurs through the standard linking interface when initiated by primary accounts:</t>
        
          <artwork><![CDATA[
+----------+       +----------+       +----------+
|  Client  |       |  IdP/STS |       |   User   |
+----------+       +----------+       +----------+
     | Auth Request      |                  |
     | scope=email       |                  |
     | linking=true      |                  |
     |------------------>|                  |
     |                  | Primary Auth      |
     |                  |------------------>|
     |                  |                   |
     |                  | Show Linking      |
     |                  | Consent Screen    |
     |                  | with "Unlink All" |
     |                  | option only       |
     |                  |------------------>|
     |                  | User confirms     |
     |                  | "Unlink All"      |
     |                  |<------------------|
     |                  |                   |
     | ID Token with    |                   |
     | standard claims  |                   |
     |<------------------|                  |]]></artwork>
        
        <t>1. User authenticates with primary account credentials</t>
        <t>2. IdP displays linking consent screen with:</t>
        <ul spacing="normal">
          <li>List of currently linked accounts</li>
          <li>Single "Unlink All" option</li>
          <li>No account selection options</li>
        </ul>
        <t>3. User confirms by clicking "Unlink All"</t>
        <t>4. IdP completely removes all linkages</t>
        <t>5. Standard ID token returned with empty linkage:</t>
        <artwork><![CDATA[
{
  "email": "main@example.com",
  "linking": {}
}]]></artwork>
      </section>

      <section anchor="secondary-flow">
        <name>Secondary Account Authentication</name>
        <t>When authenticating with an email account that is linked to a primary account:</t>
        <t>1. Client initiates standard OIDC authentication:</t>
        <artwork><![CDATA[
GET /authorize?response_type=code
  &client_id=client123
  &scope=openid%20email]]></artwork>
        <t>2. IdP/STS performs normal authentication flow</t>
        <t>3. After successful authentication, system checks for account linkages</t>
        <t>4. For secondary accounts, ID token contains:</t>
        <artwork><![CDATA[
{
  "email": "secondary@example.com",
  "linking": {
    "is_primary": false,
    "primary_email": "main@example.com",
    "expires_at": 1735689600
  }
}]]></artwork>
        <t>Applications must process the token as follows:</t>
        <ul spacing="normal">
          <li>Use <tt>primary_email</tt> as the canonical user identifier</li>
          <li>Verify <tt>expires_at</tt> is in the future</li>
          <li>Treat permissions/access identical to primary account login</li>
          <li>Include secondary email in audit logs only</li>
        </ul>
      </section>
    </section>

    <section anchor="security">
      <name>Security Considerations</name>
      <t>Key security requirements:</t>
      <ol>
        <li><t><strong>Authentication Requirements</strong>:</t>
          <ul spacing="normal">
            <li>All accounts must complete full authentication during linking</li>
            <li>Secondary accounts cannot initiate linking/unlinking</li>
          </ul>
        </li>
        <li><t><strong>Token Validation</strong>:</t>
          <ul spacing="normal">
            <li>Linking expiry must always be validated</li>
          </ul>
        </li>
        <li><t><strong>Account Resolution</strong>:</t>
          <ul spacing="normal">
            <li>Always resolve secondary logins to primary email account</li>
          </ul>
        </li>
        <li><t><strong>Audit Logging</strong>:</t>
          <ul spacing="normal">
            <li>Log all linking/unlinking events</li>
            <li>Record both primary and secondary emails in logs</li>
          </ul>
        </li>
      </ol>
    </section>

    <section anchor="iana">
      <name>IANA Considerations</name>
      <t>This document has no IANA actions.</t>
    </section>
  </middle>

  <back>
  </back>
</rfc>