{D}
Description: | %%des%% |
HTTP method: | %%method%% |
Flow: | %%flow%% |
param | value | default | notes |
---|
Response format: %%format%%
param | value | notes |
---|
To use some URL as your identity with OpenID, that URL has to declare which OpenID server is authorative over it. The host serving a particular URL doesn't need to support OpenID --- the identity URL and OpenID server can be on two totally different services.
Let's imagine your identity URL (your personal website/blog/profile page) is, say, http://bob.com/. Bob.com's <head> should contain, say:
Important notes:
It's possible to use somebody else's OpenID server without that server knowing about your website if you also have control of a URL which that other OpenID server will assert for you.
For example, you may want to use your website, http://bob.com/, as your identity, but you don't have the means (or desire) to run an OpenID server. However, you have a LiveJournal account (say, user "bob"), and you know that LiveJournal provides an OpenID server and that it'll assert that you control http://bob.livejournal.com/.
So, to use bob.com as your identity, but have consumers actually verify http://bob.livejournal.com/, you'd say (on bob.com):
Now, when a consumer sees that, it'll talk to openid/server.bml and ask if you're bob.livejournal.com, never mentioning bob.com anywhere on the wire.
The main advantage of this is that you can keep an OpenID identity over many years, even as services come and go. You just keep changing who you use for your OpenID server, or maybe even run your own.
Important notes:
An end user visits a consumer site which says it supports OpenID. The consumer site says, "Hey, we support OpenID. You can leave an authenticated comment if you use OpenID." So the user then types in "bob.com":
Note that the user can leave off "http://" and the trailing "/". A consumer must canonicalize the URL, following redirects and noting the final URL. The final, canonicalized URL is the user's identity URL.
It's also recommend that the form field be named openid_url so browsers auto-complete user's URLs between different sites, in the same way the ecommerce world tends to use conventions like "address1" and "address2".
Also note that this is called a "claimed" identity at this point, until it's been verified.
Now the consumer site must fetch the document (perhaps from cache) that the user entered. Make note that the user could be malicious and try to make you connect to your internal network, or tarpit you, etc. You'll probably want to use a paranoid HTTP library like LWPx::ParanoidAgent that protects you from attackers.
The consumer then parses the head section and finds the "openid.server" and the optional "openid.delegate" declarations. (Note: consumers MUST support openid.delegate)
The protocol supports both a "smart mode" and "dumb mode" to accomodate consumers of differing capabilities. A smart consumer does a little more work at the beginning to save itself work later, but requires local caching of state information. A dumb consumer is completely stateless, but requires extra HTTP requests.
It's recommended that a consumer, if possible, first submit an openid.mode=associate POST request to the identity server and get a shared secret. This shared secret will be used as the HMAC-SHA1 key in future identity check requests. If a consumer already has a shared secret with that server that hasn't expired, it should keep on using that.
The shared secret can be exchanged either in plain-text or encrypted with a Diffie-Hellman-negotiated secret. Not that if Diffie-Hellman is used, it's only used in the associate mode. The identity check modes assume you already have some shared secret, regardless of how you got it.
Now the consumer constructs a URL to the identity server's openid.mode=checkid_immediate (or checkid_setup) URLs and sends the User-Agent there. By sending the User-Agent there, the user's cookies and whatever other login credentials are sent back to their trusted identity server. The server does its work, appends its response onto your supplied return_to URL, and sends the user-agent back at you.
Details of each OpenID request type.
associate method=>POST flow=>consumer server consumer des=>Establish a shared secret between consumer and server. format=> in<= openid.mode value=> default=> notes=> ip?> openid.assoc_type value=>Preferred association type. default=> notes=>Optional. Currently only one value. Defaults to HMAC-SHA1. ip?> openid.session_type value=>Preferred way to encrypt the shared secret. Either blank or default=>None. (cleartext) notes=>Without specifying DH-SHA1, secrets are sent in the clear. As this is usually between consumer and server, which are usually on good net connections (not, say, WiFi), it's not as risky as you might think to send it in the clear. However, it's still recommended that you use the DH-SHA1 mode to encrypt the shared secret. ip?> openid.dh_modulus value=>base64((p)) default<=checkid_immediate mode is commonly used for "AJAX"-style setups, doing fancy JavaScript stuff. The more classic mode to check an identity is checkid_setup.
in<= openid.mode value=> default=> notes=> ip?> openid.identity value=>identity URL being checked default=> notes=>The identity URL the end user is asking the ID server to verify. The exact question is: "Does the user logged in to your site own this URL, and do they allow the trust_root (and therefore the return_to URL) to know that?" (Note that the question isn't "Who's logged in?") Note: An identity server should only assert to URLs that it manages/produces directly. If a user wants to assert other URLs outside of that server realm, they should use openid.delegate. ip?> openid.assoc_handle value=>The assoc_handle from the associate mode. default=> notes=>Optional. Consumer must use dumb mode (check_authentication mode) if an assoc_handle isn't provided. Also, if you use an assoc_handle the server doesn't know about, it'll pick its own and you'll have to use dumb mode as well. ip?> openid.return_to value=>URL to return back to default=> notes=>This is where the server is being asked to return the User-Agent back to, with the response in the GET paramaters. Note that the URL you provide may contain an existing query string, and the server must preserve it when appending the response parameters. ip?> openid.trust_root value=>URL for user to trust default=> notes=>(Optional, but recommended) -- The URL which the user will actually see to approve. The return_to URL must descend from the trust_root, or the identity server will return an error, not a redirect. Namely, the URL scheme and port must match. The path, if present, but be equal or below the trust_root, and the domains on both must match, or, the trust_root contain a wildcard like http://*.livejournal.com (but the wildcard may only be at the beginning) You can try to pass things like http://*.com/ or http://*.co.uk/, but any respectable identity server will protect their users from that. Defaults to return_to URL if absent. ip?> <=in out<= openid.mode value=> notes=> op?> openid.user_setup_url value=>URL to send user to complete process notes<= If the identity assertion fails, the server provides this URL for where the user can do whatever's necessary to fulfill the assertion, be it login, setup permissions, etc. The server should return a URL which doesn't imply anything about what's needed, so the consumer is left in the dark about why the assertion failed.Servers are required to implement this mode for error recovery and dumb consumers (which can't keep state locally), but it's recommended that you use it as little as possible, as it shouldn't be necessary most the time. It's good for debugging, though, as you develop your consumer library.
mode?>