T. Lodderstedt
Deutsche Telekom AG
JULY 19, 2016

OpenID Connect Account Migration 1.0


This document specifies a protocol for migrating user accounts among OpenID Connect OPs. The goal is to allow users to migrate between OpenID Connect OPs while retaining access to their existing services (RPs). Although the need for such a function was first raised in the context of the Mobile Connect initiative ([MobileConnect]), the intend is to design a protocol applicable on a general basis.

Table of Contents

1. Introduction

Mobile Connect uses the mobile phone number to identify a certain user identity. So from a user's perspective, the mobile phone number is becoming her digital identity and is used to login to a variety of services.

When the respective subscriber changes among mobile network operators, the mobile phone number is typically migrated and can be used with the new Mobile Network Operator (mobile phone number portability). And in the same way the user can be reached afterwards via the same mobile phone number as before, users may also expect to retain access to all the services they had logged into with this mobile phone number before.

But even if the subscriber does not migrate her mobile phone number, she may want to retain access to all services they had logged into using the old Mobile Phone Operator's services before. This use case is not bound to Mobile Connect but can be solved for OpenID Connect in general, opening the opportunity to migrate between all kinds of OpenID OPs, which greatly contributes to the concept of user centricity since users are not locked into a certain OP.

From a user's perspective if she logs in to an particular RP with the new OP, she must get access to the same account with this RP as before. The technical challenge can be expressed as follows: OpenID Connect assumes full autonomy of every OP regarding the way its user identifier ("sub" claim of an ID token) are created and managed. The OpenID Connect specification does intentionally not define the structure of a user identifier or the mechanisms used to create them. This way every OP can implement user id management the way it suites its needs the best. It also allows to wrap existing user databases with OpenID Connect without the need to migrate user data (on both OP and RP ends). RPs shall treat a subject as opaque string. Global uniqueness is achieved by scoping every user id with the respective OP's identifier ("iss" claim of an ID token). User ids (i.e. iss + sub) can therefore not simply be transferred among OPs.

This extension to the OpenID Connect protocol is based on the concepts of the OpenID 2.0 migration protocol extension ([OpenID20.Migration]). In the OpenID 2.0 migration protocol, the same OP that previously offered OpenID 2.0 now provides identity data to RPs via OpenID Connect. Since the data structures changed between both versions of OpenID, the respective user identifiers at the RPs need to be migrated. This is supported by providing the RP with both sets of data, the old and the new user id referring to the same user account with the OP. These data is jointly provided in the OpenID Connect authentication response. Based on this data, the RP can identify the user account in its database (using the OpenID 2.0 identifier) and augment it with the iss and sub claim obtained from the respective id token.

This specification applies the same principle to the migration of user accounts among OPs. If the user has moved its user account to a new OP, this new OP will not only provide its iss and sub for a particular account but also the old iss and sub used by the old OP. This additional data is provided in an extension to the OpenID Connect authentication response and allows the RP to identify the respective user account in its database (using the old values for iss and sub) and update the respective user account record to be identified by the new iss and sub. After this update, the RP user account is directly identified (and authenticated) by the sub and iss provided by the new OP in subsequent login processes.

Care must be taken to ensure this protocol is not used for user account take over. An RP is therefore supposed to perform an user account migration only if the old OP has asserted the transfer of responsibility regarding the user account under consideration to the actual OP. This specification proposes the necessary mechanisms. It also specifies a new API used to transfer user account data among OPs. Clearly, this specification ensures the user is in full control of the whole migration process, especially her consent is needed in order to reveal user data to the new OP.

The following topics or requirements are out of scope of this specification:

User Authentication
Users need to be authenticated in the course of the migration as well as in the ordinary login process. The means used to authenticate users are at the discretion of the OP and out of scope for this specification. The OP could use credentials especially issued for migration, but it could also use other mechanisms available even if the user lost some mechanisms because of the migration (e.g. SIM-based authentication).
Chained migration
One could image that users change OPs multiple times over a span of several years. Migrating user account data especially for seldomly used RPs will then be a challenge. It would require the currently responsible OP to establish a prove chain up to the OP the user used the last time to login. For the time being, this specification will not cover user account migration over more then two OPs.
OP Account Lifecycle
This specification does not assume a certain lifecycle of the user account object at the old OP. It could be deleted after a certain time (grace period), one could also imagine the OP allows the user to continue to use the respective user account. It is assumed the old OP invalidates the subject values migrated to the new OP for login processes to RPs.

1.1. Requirements Notation and Conventions

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119].

Throughout this document, values are quoted to indicate that they are to be taken literally. When using these values in protocol messages, the quotes MUST NOT be used as part of the value.

1.2. Terminology

This specification uses the terms "OpenID Provider (OP)" and "Relying Party (RP)" as defined by OpenID Connect Core [OpenID.Core]. This specification also defines the following terms:

OP account
A user's account with the OP. This account is characterized by credentials used to login with the OP and certain user identifiers (public as well as pairwise pseudonymous). The latter are asserted by the OP to RPs in order to authenticate the user to the respective RP.
RP account
A user's account with the respective RP. This account is associated with the user's data with the RP (a service or a collection of services). From an authentication perspective, this account is characterized by a federated user id asserted by a certain OP. This federated user id replaces or supplements local credentials at the RP and is used to authenticate the RP account. In the context of OpenID Connect, the federated user id is build from the iss and sub claims of the id token asserted in the OpenID Connect authentication response.

2. Overview

An user account is migrated in two steps. First, the OP account is moved from the old OP to the new OP. In this process, the user identifiers associated with the respective OP account are obtained by the new OP and stored in relation to the respective new OP account. In the second step, all RP accounts related to the OP account in migration are migrated "on the fly" while the user is logging in to the respective RP. During this stage (which could last for years), the new OP uses the account data obtained in the first phase to provide the RP with the required "old" OP account data as part of the OpenID Connect authentication response. Both processes are explained in more detail in the following sub sections.

2.1. OP account migration

The following figure shows the abstract message flow during the OP account migration process. Note: the new OP takes the role of an OAuth client trying to get access to the old OP's account migration endpoint. So the flow is based on the OAuth [RFC6749] abstract protocol flow.

     +---------+                               +-------------+
     |         |<-(A)-- Start Migration -------|             |
     |         |--(B)- Authorization Request ->|    User     |
     |         |<-(C)-- Authorization Grant ---|             |
     |         |                               +-------------+
     |         |                               +---------------------+   
     |         |                               |   Old OP            |
     |         |                               +------------------+  |
     | New OP  |--(D)-- Authorization Grant -->| Tokens Endpoint  |  |
     |         |<-(E)-- Access Token ----------|                  |  |
     |         |                               +------------------+  |
     |         |                               +------------------+  |          
     |         |--(F)-- Request Account Data ->| AccountMigration |  |
     |         |<-(G)--- Account Data ---------|   Endpoint       |  |
     |         |                               +------------------+  |
     |         |                               |                     |                                 
     +---------+                               +---------------------+

Figure 1 OP account migration (Abstract Protocol Flow)

The new OP stores the newly obtained account data with its respective OP account for latter use during the RP account migration.

Note: The new OP may access the AccountMigration endpoint as long as the authorization grant is valid. This could be used to obtain fresh assertions if the originally obtained assertions expired.

2.2. RP account migration

The RP account migration is performed as part of the login process to a particular RP.

This concludes the migration of the RP from one OP to another OP. The RP will directly login the user with the RP account corresponding to the new OP's account in subsequent login processes.

3. AccountMigration Endpoint

The AccountMigration Endpoint is exposed by an OpenID Connect OP supporting account migration and is used to transfer user account data from one OP to another OP.

The AccountMigration endpoint provides the new OP with all subject values (public as well as pairwise) of the user account under migration. For every subject value, the old OP issues a signed JWT containing all relevant data, which in turn can be used to prove to a RP that ownership of the account had been migrated to the new OP.

Communication with the AccountMigration Endpoint MUST utilize TLS ([RFC5246]).

The AccountMigration Endpoint MUST support the use of the HTTP POST methods defined in [RFC2616].

This endpoint is OAuth protected, so the new OP needs to acquire a suitable access token before it invokes the endpoint. The proposed scope value to acquire authorization to this endpoint is "account_migration". The AccountMigration Endpoint MUST accept Access Tokens as OAuth 2.0 Bearer Token Usage [RFC6750].

3.1. Account Migration Data

The account migration JSON object is a JWT with additional structured claims. On the top level, it contains the following claims:

Data about the user account at the old OP.
Data about the OP this account is being migrated to.
Expiration time (see [RFC7519])
Issued at (see [RFC7519])

OPEN: do we need nbf and/or jti?

Note: this specification intentionally does not use the ID token format to prevent abuse of the migration data as ID token.

The "from" claim contains the following sub claims:

Issuer URL of the OP, which asserted the JWT, so this is the same semantics as for "iss" in a JWT (see [RFC7519]).
subject identifier of the respective user account for the RP identified by the claim "aud", so this is the same semantics as "sub" in a JWT (see [RFC7519]).
subject type, may be "pairwise" or "public".
In case of an pairwise subject, this claim contains the audience of the particular pairwise subject identifier. The value may be a redirect_uri or a sector_identifier of the client or the set of clients the old OP asserted the respective subject identifier to.

The "to" claim contains the following sub claims:

Issuer URL of the OP, which is supposed to take over responsibility for the particular account. The value is subject to the same rules applicable to iss claims in JWTs and ID Tokens.

The following shows an example of a migration data JWT:

  "from": {
    "iss": "https://op.mno1.com",
    "sub": "45445454",
    "sub_type": "pairwise",
	"aud": "https://creditagency.example.com/oidc"
  "to": {
    "iss": "https://op.mno2.com"
  "exp": 1568925762986,
  "iat": 1468925762986

Note: Account migration data may only be signed by the old OP using asymmetric algorithms and never encrypted since it is supposed to be processed by at least two parties, the new OP and the respective RP.

OPEN: There are several potential ways to identify the client or set of clients a certain ppid is bound to. They all have their pros and cons. Since there is a certain (privacy) risk to expose a ppid to clients, which are not eligible to get to know it, we need to carefully select the right option(s):

Limited to single client. Works well for HTTP(S)-URLs, rather weak for custom schemes (natives apps) - can be impersonated.
Host component of the registered redirect_uri - bit more flexible - works for HTTP(S) URLs only.
Points to a JSON file containing all redirect URIs for a certain set of sites and apps under common administrative control. Basically same limitation as redirect URI.
software id
Claim of the software statement used in MODRNA registration to identify a certain package (within the scope of the issuer of the software statement). In my opinion, this is the only cross-OP way to identify clients.

OPEN: Do we want/need to also transfer claims and scope values for user info endpoint, the user consented to?

3.2. AccountMigration Request

The account migration request has no parameters (except the BEARER authorization header carrying the access token). The respective user account and the identity of the client are obtained based on the access token.

The following is an non-normative example request.

POST /connect/migrate HTTP/1.1
Host: op.mno1.com
Content-Type: application/x-www-form-urlencoded
Authorization: Bearer mF_9.B5f-4.1JqM

OPEN: Is POST the right verb?I think so since user account state is change at the old OP (subject values are invalidated).

3.3. AccountMigration Response

The response is a JSON array, which is composed of signed migration data JWTs, each of them asserting a particular subject value of the respective OP account. The response MAY contain a single public subject. It MAY contain several pairwise pseudonymous subject values, each of them augmented with the respective redirect URI or sector identifier URI utilized to identify eligible clients in the next migration stage. There MUST be at most one entry per client identifier.

The following is an example response (line breaks are for display purposes only):

HTTP/1.1 200 OK
Content-Type: application/json


The new OP is supposed to process the response as follows:

3.4. Account Data Error Response

TBD errors: unauthorized, account does not exists, already migrated, migrated to different OP, ...

4. Authentication response extension

The actual migration of a RP user account is performed per RP during the respective login process.

When generating the authentication response for a particular RP, the new OP verifies, whether it is in possession of an old subject value relevant for the particular RP. There are two different cases:

Pairwise pseudonymous identifier
The OP is in possession of a pairwise pseudonymous identifier for the respective RP. Equivalence of RPs is determined by matching the RP's redirect_uris with the the redirect_uri or the sector identifier in the account migration JWTs of the OP user account under consideration.
Public identifier
If there is no matching ppid but the data set contains a public identifier, this identifier is sent back to the RP.

The migration data is added to the ID token in the new claim migration_data.

This claim contains a single account migration JWT as obtained from the old OP. It shall demonstrate to the RP that the OP took over responsibility regarding the RP user account from the old OP and it contains the old values of iss and sub.

The following is an example response (line breaks are for display purposes only):

  "iss": "https://op.mno2.com",
  "sub": "676887676767",
  "aud": "client_xyz",
  "exp": 1311281970,
  "iat": 1311280970,
  "auth_time": 1311280969,
  "acr": "urn:mace:incommon:iap:silver"

The RP is supposed to act as follows:

If the RP does not find a user account within its database using the combination of the iss and sub claim, it checks whether there exists a porting_data claim in the id token. If that's the case the OP inspects the porting data and attempts to migrate the user account identified by the porting data JWT within its database to the values asserted by the id token.

In the example case, the id token carries a account data claim, which contains the following JWT:

  "from": {
    "iss": "https://op.mno1.com",
    "sub": "45445454",
    "sub_type": "pairwise",
	"aud": "https://creditagency.example.com/oidc"
  "to": {
    "iss": "https://op.mno2.com"
  "exp": 1568925762986,
  "iat": 1468925762986

The RP first validates the digital signature of the migration data JWT. It therefore looks up the old OP's openid configuration as defined in [OpenID.Discovery] using the "iss" sub claim of the claim "from" and uses it to obtains the location of the old OP's JSON Web Key Set [RFC7517]) (containing the respective public keys of the OP).

For example, given the issuer URL https://op.mno1.com, the new OP would obtain the following OpenID configuration of the old OP from https://op.mno1.com/.well-known/openid-configuration (line breaks are for display purposes only):

HTTP/1.1 200 OK
Content-Type: application/json
  "issuer": "https://op.mno1.com",
  "jwks_uri": "https://op.mno1.com/jwks.json",

It then loads the public keys material, which could for example look like this (line breaks for are for display purposes only):

 "keys": [
   "kty": "RSA",
   "alg": "RS256",
   "use": "sig",
   "kid": "b040ea9e48fec8dfd6a8859b07553dee18f19636",
   "n": "zewQFS4tqHaofLLOTfliLO3gb1WnmjMYrPlVHPNdJc7WTVO5iuSVV1j5bYH0IvuoikdnBUzV0hjZiEg
   "e": "AQAB"
   "kty": "RSA",
   "alg": "RS256",
   "use": "sig",
   "kid": "fc33f33a95ce227b9956398788a49ca83bea7bf5",
   "n": "qMW-G5XetV6bfJ4i6yWLLukttyLAoT3Fw3qz6sqqwRnvuS_StqAnVs7A5fWavcR3_AZimy1fJf9Gz9w
   "e": "AQAB"

Note: the appropriate key required for a particular migration data JWT is identified by the key identifier (kid).

If the signature has been validated successfully, the RP checks whether the iss of the ID token of the actual authentication response an the claim "to/iss" contain the same value, i.e. the respective OP account had been transferred to the new OP.

If this check was successful, the RP checks, whether it can find an existing user account in its database using the combination of "from/iss" and "from/sub" obtained from the porting data JWT. In the case of the example above, this would be the the issuer "https://op.mno1.com" and the sub "45445454".

If there is a match, the RP changes the corresponding database values to the values of the claims iss and sub of the actual id token. In the example, the respective values would be "https://op.mno2.com" and "676887676767".

After this step, the account of the actual user has effectively been migrated to the new OP. If the same user logs into the same RP again, the RP would not consider the porting data again because it would successfully lookup the local user account using the iss and sub provided by the new OP.

OPEN: the migration data JWT needs a long-term signature since RP migration might happen years after the migration between OPs happened. Instead of using a digital signature, we could also introduce a validation endpoint at the old OP to verify the migration data during RP account migration (proposal by James Manger).

There was also a further review comment, whether the RP a third party or the old OP should verify the signature.

OPEN: unsolicited response or shall the RP ask for migration data (like in OpenID 2.0 migration)?

5. Mandatory to Implement Requirements


6. Security Considerations

Attackers goal: get access to the victims RP accounts either by taking over the respective OP or RP account. This section analysis the protocol flow along the lines of the migration process for threat vectors. Note: this list is a starting point and not meant to be comprehensive (yet).

6.1. Impersonation of legitimate user's old OP account

If the attacker can get hold of the authorization grant issued by the old OP for access to the account migration API, the attacker can impersonate the legitimate user in the migration process at the new OP.

6.2. Trick user into login with attacker's account

The attacker could try to cause the legitimate user to login with her new OP with the attacker's account with this new OP. That would cause the new OP to associate the migration data with the attackers account, which in turn allows the attacker to migrate all RP accounts of the legitimate user to his account with the new OP.

6.3. Impersonate old OP/replay migration data

If the attacker gets hold of valid migration data of an account at OP1 and "migrates" the account data to his account with OP1. Scenario: The attacker logs into the new OP with her OP account and sends the new OP to the OP under her control. This OP returns migration data obtained from a legitimate OP in a previous step.

6.4. Bad OP

Attacker could try to trick victim into (unintentionally) migration her OP account to a OP under the attacker's control

6.5. Inject migration data during RP account migration

Attacker gets hold of valid migration data and injects it into the login response. This would only work for implicit grant, not for grant type code.

6.6. Further Considerations

Note: the new OP could also accidentally assign the account migration data to the wrong user account in its database. Care must be taken that the respective functions are thoroughly tested with every change.

7. Privacy Considerations


8. IANA Considerations


9. References

9.1. Normative References

[OpenID.Core] Sakimura, N., Bradley, J., Jones, M., de Medeiros, B., Mortimore, C. and E. Jay, "OpenID Connect Core 1.0", December 2013.
[OpenID.Discovery] Sakimura, N., Bradley, J., Jones, M. and E. Jay, "OpenID Connect Discovery 1.0", August 2015.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, March 1997.
[RFC2616] Fielding, R., Gettys, J., Mogul, J., Frystyk, H., Masinter, L., Leach, P. and T. Berners-Lee, "Hypertext Transfer Protocol -- HTTP/1.1", RFC 2616, DOI 10.17487/RFC2616, June 1999.
[RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security (TLS) Protocol Version 1.2", RFC 5246, DOI 10.17487/RFC5246, August 2008.
[RFC6749] Hardt, D., "The OAuth 2.0 Authorization Framework", RFC 6749, DOI 10.17487/RFC6749, October 2012.
[RFC6750] Jones, M. and D. Hardt, "The OAuth 2.0 Authorization Framework: Bearer Token Usage", RFC 6750, DOI 10.17487/RFC6750, October 2012.
[RFC7517] Jones, M., "JSON Web Key (JWK)", RFC 7517, DOI 10.17487/RFC7517, May 2015.
[RFC7519] Jones, M., Bradley, J. and N. Sakimura, "JSON Web Token (JWT)", RFC 7519, DOI 10.17487/RFC7519, May 2015.

9.2. Informative References

[MobileConnect] GSMA, "Mobile Connect", 2016.
[OpenID20.Migration] Sakimura, N., Bradley, J., Agarwal, N. and E. Jay, "OpenID 2.0 to OpenID Connect Migration 1.0", April 2015.

Appendix A. Acknowledgements

The following have contributed to the development of this specification.

Appendix B. Notices

Copyright (c) 2016 The OpenID Foundation.

The OpenID Foundation (OIDF) grants to any Contributor, developer, implementer, or other interested party a non-exclusive, royalty free, worldwide copyright license to reproduce, prepare derivative works from, distribute, perform and display, this Implementers Draft or Final Specification solely for the purposes of (i) developing specifications, and (ii) implementing Implementers Drafts and Final Specifications based on such documents, provided that attribution be made to the OIDF as the source of the material, but that such attribution does not indicate an endorsement by the OIDF.

The technology described in this specification was made available from contributions from various sources, including members of the OpenID Foundation and others. Although the OpenID Foundation has taken steps to help ensure that the technology is available for distribution, it takes no position regarding the validity or scope of any intellectual property or other rights that might be claimed to pertain to the implementation or use of the technology described in this specification or the extent to which any license under such rights might or might not be available; neither does it represent that it has made any independent effort to identify any such rights. The OpenID Foundation and the contributors to this specification make no (and hereby expressly disclaim any) warranties (express, implied, or otherwise), including implied warranties of merchantability, non-infringement, fitness for a particular purpose, or title, related to this specification, and the entire risk as to implementing this specification is assumed by the implementer. The OpenID Intellectual Property Rights policy requires contributors to offer a patent promise not to assert certain patent claims against other contributors and against implementers. The OpenID Foundation invites any interested party to bring to its attention any copyrights, patents, patent applications, or other proprietary rights that may cover technology that may be required to practice this specification.

Appendix C. Document History

[[ To be removed from the final specification ]]



Author's Address

Torsten Lodderstedt Deutsche Telekom AG EMail: t.lodderstedt@telekom.de