T. Lodderstedt | |
Deutsche Telekom AG | |
August 04, 2016 |
OpenID Connect Account Migration 1.0
draft-account-migration-02
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.
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:
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.
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:
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.
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.
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.
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].
The account migration object is a JWT with additional structured claims. On the top level, it contains the following claims:
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:
The "to" claim contains the following sub claims:
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 }
Account migration data MUST be signed by the old OP using asymmetric algorithms and MUST NOT be encrypted since it is supposed to be processed by at least two parties, the new OP and the respective RP.
Migration data JWTs are signed by the old OP using JSON Web Signature [RFC7515]. The value of the header parameter "typ" is set to "migration_data". This allows the recipient to distinguish migration data from ID tokens or other JWTs (already while processing the signed object).
The following shows the example migration data JWT from above after signing:
eyJhbGciOiJSUzI1NiIsInR5cCI6Im1pZ3JhdGlvbl9kYXRhIn0.eyJmcm9tIjp 7ImlzcyI6Imh0dHBzOi8vb3AubW5vMS5jb20iLCJzdWIiOiI0NTQ0NTQ1NCIsIn N1Yl90eXBlIjoicGFpcndpc2UiLCJhdWQiOiJodHRwczovL2NyZWRpdGFnZW5je S5leGFtcGxlLmNvbS9vaWRjIn0sInRvIjp7ImlzcyI6Imh0dHBzOi8vb3AubW5v Mi5jb20ifSwiZXhwIjoxNTY4OTI1NzYyOTg2LCJpYXQiOjE0Njg5MjU3NjI5ODZ 9.bMxk--Hmqvs8DRRWvR8RLg4XxSb3wULUrL-8YoLXWSKhKA6bPXsxxoIoUb6Rg qbZhp1j2W030RVvKqImT6XjT_83VFEb4TELrxVa_gCEWTwW7u09YFXstpZ9aOeb 8opDs78ejHyYDFSh3F01qcbdms6AMmqyIGllyOomhVBZpZc
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):
OPEN: Do we want/need to also transfer claims and scope values for user info endpoint, the user consented to?
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).
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 ["eyJhbGciOiJSUzI1NiIsInR5cCI6Im1pZ3JhdGlvbl9kYXRhIn0. eyJmcm9tIjp7ImlzcyI6Imh0dHBzOi8vb3AubW5vMS5jb20iLCJzd WIiOiI0NTQ0NTQ1NCIsInN1Yl90eXBlIjoicGFpcndpc2UiLCJhdW QiOiJodHRwczovL2NyZWRpdGFnZW5jeS5leGFtcGxlLmNvbS9vaWR jIn0sInRvIjp7ImlzcyI6Imh0dHBzOi8vb3AubW5vMi5jb20ifSwi ZXhwIjoxNTY4OTI1NzYyOTg2LCJpYXQiOjE0Njg5MjU3NjI5ODZ9. bMxk--Hmqvs8DRRWvR8RLg4XxSb3wULUrL-8YoLXWSKhKA6bPXsxx oIoUb6RgqbZhp1j2W030RVvKqImT6XjT_83VFEb4TELrxVa_gCEWT wW7u09YFXstpZ9aOeb8opDs78ejHyYDFSh3F01qcbdms6AMmqyIGl lyOomhVBZpZc", "eyJhbGciOiJSUzI1NiIsInR5cCI6Im1pZ3JhdGlvbl9kYXRhIn0. eyJmcm9tIjp7ImlzcyI6Imh0dHBzOi8vb3AubW5vMS5jb20iLCJzd WIiOiI1NjU2NTU2NTUiLCJzdWJfdHlwZSI6InBhaXJ3aXNlIiwiYX VkIjoiaHR0cHM6Ly9teWJhbmsuZXhhbXBsZS5jb20vb2lkYyJ9LCJ 0byI6eyJpc3MiOiJodHRwczovL29wLm1ubzIuY29tIn0sImV4cCI6 MTU2ODkyNTc3Mjk4NiwiaWF0IjoxNDY4OTI1NzcyOTg2fQ.sdCJ0N elcpo8qDpPV6Dvs2DThDrvOeWEngyL3SPa0yr-1ooiGKpJA_8EmCW 3B58eX14Cny0-stB1V9d1Vv4KRjEsulcicC_NV4Qds3Lr6HiUo6oM Ph9yHGb209L_g1lHFggb-lltcRTssuM4GWhhJYZDTXoOhMWyTdMDr nfzsPc"]
The new OP is supposed to process the response as follows:
TBD errors: unauthorized, account does not exists, already migrated, migrated to different OP, ...
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:
The migration data is added to the ID token in the new claim migration_data.
The following is an example response (line breaks are for display purposes only):
{ "iss": "https://op.mno2.com", "sub": "676887676767", "aud": "client_xyz", "migration_data":"eyJhbGciOiJSUzI1NiIsInR5cCI6Im1pZ3Jhd Glvbl9kYXRhIn0.eyJmcm9tIjp7ImlzcyI6Imh0dHBzOi8vb3AubW5v MS5jb20iLCJzdWIiOiI0NTQ0NTQ1NCIsInN1Yl90eXBlIjoicGFpcnd pc2UiLCJhdWQiOiJodHRwczovL2NyZWRpdGFnZW5jeS5leGFtcGxlLm NvbS9vaWRjIn0sInRvIjp7ImlzcyI6Imh0dHBzOi8vb3AubW5vMi5jb 20ifSwiZXhwIjoxNTY4OTI1NzYyOTg2LCJpYXQiOjE0Njg5MjU3NjI5 ODZ9.bMxk--Hmqvs8DRRWvR8RLg4XxSb3wULUrL-8YoLXWSKhKA6bPX sxxoIoUb6RgqbZhp1j2W030RVvKqImT6XjT_83VFEb4TELrxVa_gCEW TwW7u09YFXstpZ9aOeb8opDs78ejHyYDFSh3F01qcbdms6AMmqyIGll yOomhVBZpZc", "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 an 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 MUST validate 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 obtain the location of the old OP's JSON Web Key Set [RFC7517]) (containing the respective public keys of the OP).
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)?
TBD
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).
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.
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.
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.
Attacker could try to trick victim into (unintentionally) migration her OP account to a OP under the attacker's control
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.
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.
TBD
TBD
[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. |
The following have contributed to the development of this specification.
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.
[[ To be removed from the final specification ]]
-02
-01
-00