Delegation Proposal Amendment

Drummond Reed drummond.reed at
Fri Oct 6 14:22:04 PDT 2006


This is very cool. Adding openid.rp_user_id would give us an unambigous way
to represent what I called the RPI in my earlier message:

IPI = IdP-Persistent-Identifier = openid.identity

RPI = RP-Persistent-Identifier = openid.rp_user_id

It doesn't address the third identifier, which I called UPI
(User-Presented-Identifier -- the one the user typed in at the RP), but
let's leave that aside for now.

So as I understand it, the rules would be:

***** ON THE RP SIDE *****

The RP ALWAYS does discovery on UPI. Then it applies these tests:

1) If UPI maps to a directed identity server
(<Type></Type>), then:
	openid.rp_user_id = [empty]
	openid.identity = ""

2) If UPI is an XRI that maps to a CanonicalID AND there is no
openid:delegate element in the XRD, then:
	openid.rp_user_id = CanonicalID
	openid.identity = CanonicalID

3) If UPI is an XRI that maps to a CanonicalID AND to an IPI (via the
openid:delegate element in the XRD), then:
	openid.rp_user_id = CanonicalID
	openid.identity = IPI

4) If UPI is a URL that maps to an IPI (via the openid:delegate element in
the XRD), then:
	openid.rp_user_id = UPI
	openid.identity = IPI

5) Else:
	openid.rp_user_id = UPI
	openid.identity = UPI

***** ON THE IDP SIDE *****

6) IdP ALWAYS keys on the value of openid.identity.

7) IdP ALWAYS returns the same value of openid.identity that the RP sent (so
the RP can always key off this value in the response).

8) IdP ALWAYS returns the value of openid.rp_user_id UNLESS it was empty, in
which case see rule 9a below.

9) IdP MAY or MAY NOT do discovery. The rules are:

	a) If openid.identity = "",
then IdP prompts User for UPI (or detects cookie, etc.). If UPI != IPI, then
IdP does discovery on UPI to get mapping to IPI. IdP authenticates against
IPI, but at that point allows user to select the RPI (or generates for the
user). IdP returns:
	openid.rp_user_id = user-selected or IdP-generated RPI
	openid.identity = ""

	b) If openid.identity = UPI that IdP does not recognize, then IdP
does discovery on UPI to get mapping to IPI. After authentication against
IPI, IdP returns:
	openid.rp_user_id = UPI
	openid.identity = UPI

	c) If openid.identity = IPI, IdP does not need to do discovery, but
authenticates against IPI and returns:
	openid.rp_user_id = [value sent by RP]
	openid.identity = IPI


This all works wonderfully and covers all the use cases -- congratulations!

Now, let me make a case for also making the third identifier -- the UPI --
explicit in the protocol. This addresses a specific usability issue that
arises due to the fact that XRIs support i-name/CanonicalID separation,
which URLs don't. However I believe it can also improve usability for URLs.

The motivation is that in cases 2 and 3 above, the openid.rp_user_id that
the RP passes to the IdP is going to be an CanonicalID, which is an
i-number. This is a very ugly string like:

	=!F83.62B1.44F.2813	(that's my actual i-number)

However the IdP only has the choice of openid.rp_user_id or openid.identity
from which to greet me to ask for my authentication credentials. Since these
will both be a CanonicalID, this leads to a greeting like:

	Hello =!F83.62B1.44F.2813. Please confirm that you want to login
	to YourFavoriteRP. [Allow Once] [Allow Always] [Cancel]

All it takes to solve this problem is for the RP to pass the UPI in the
authentication request. Then the IdP can say:

	Hello =drummond.reed. Please confirm that you want to login
	to YourFavoriteRP. [Allow Once] [Allow Always] [Cancel]

Better still, this functionality is not limited to XRIs. RPs can apply it to
any User just by prompting the user for a preferred Display Name along with
their OpenID identifier. Then the RP can send the Display Name as the UPI
string so the IdP can call the user by the same name. For example:

	Hello Drummond. Please confirm that you want to login
	to YourFavoriteRP. [Allow Once] [Allow Always] [Cancel]

So this boils down to a simple proposed amendment to your amendment:

PROPOSED AMENDMENT: Add a third optional parameter, openid.display, the
value of which is the UPI. The rules governing its use:

1) If the RP DOES NOT send openid.display, it defaults to openid.rp_user_id.
(And by your amendment, if RP does not send openid.rp_user_id, then it
defaults to openid.identity).

2) If the RP prompts the User for a Display Name for an OpenID identifier,
the RP SHOULD set the value of openid.display to the UTF-8 encoded value of
the display name string.

3) If the RP does not prompt the User for a Display Name (or if the User
does not supply one), but if UPI is an i-name, the RP SHOULD send the i-name
as the openid.display value.


-----Original Message-----
From: specs-bounces at [mailto:specs-bounces at] On Behalf
Of Josh Hoyt
Sent: Friday, October 06, 2006 11:41 AM
To: specs at
Subject: Delegation Proposal Amendment

I'd like to amend my proposal for changing the delegation mechanism:

Revised Proposal

As it stands, "openid.identity" is the identifier by which the IdP
knows the user. There is no parameter by which the RP knows the user.

I propose to add a field called "openid.rp_user_id" in "checkid_*" and
"id_res" that defaults to "openid.identity" if it is missing. This
field is the identifier by which the relying party knows the user.
This is the identifier on which discovery was performed by the relying

The name "openid.rp_user_id" is not the best, but it *is* very
specific. Other suggestions welcome.


This proposal retains the current behaviour in terms of who is
responsible for discovery and verification. It makes the messages
between the RP and IdP more explicit. It is completely
backwards-compatible. IdP-driven identifier selection can now return a
delegated identifier (if the user wishes to do so).


The IdP now has knowledge of the identifier that the user entered at
the relying party.


I think there is general agreement that the protocol messages on the
wire can lead to confusing results. I also think that it's easy to get
the relying party implementation wrong because it has to keep track of
state to ensure that the user gets the right identifier. I don't think
that most relying parties will have a problem keeping state, but I
think it's not a good idea to make proper behavior (using the right
identifier) *depend* on the relying party's implementation of state

This proposal is similar in spirit to Martin's proposal, in that it
acknowledges that delegation is not really a special case. The main
difference is that (a) it is obvious from the protocol messages what
is going on and (b) discovery is entirely unchanged.

Related threads

Original proposal:

Brad's explanation of openid.delegate:

Regarding the purpose of delegation:

Martin's similar proposal:

specs mailing list
specs at

More information about the specs mailing list