Proposal: An HTTP Auth mechanism for OpenID
One thing that OpenID can't do very well right now is authentication between two non-human agents. Though it is possible to make it work, it's difficult to "library-ize" it due to the reliance on HTML forms.
The following describes a simple HTTP Authentication mechanism that could be used in the machine-to-machine case. Not all relying parties would support it, but it could be implemented for any relying party where this functionality is considered useful and used as part of other protocols built apon OpenID.
The protocol is a simplified and adapted version of OpenID 1.1's "dumb mode". The basic jist of the exchange is as follows:
- (optionally) Relying party returns a 401 Unauthorized response to an earlier request with a WWW-Authenticate header indicating that it supports OpenID auth. The client doesn't necessarily have to try an anonymous request first, since there is no challenge to fetch.
- Client talks by some means to its identity provider to get an assoc_handle and a signature. How this is done is outside the scope of this protocol, but in many/most cases the client would be acting as its own identity provider so it would just compute it itself, directly.
- Identity provider computes a signature similar to that of normal OpenID, but it is based on the server's secret, the URL we're requesting and the identity URL. Client sends the following to the relying party:
WWW-Authenticate: OpenID identity="http://example.com/",assoc_handle="...",sig="..."
- The relying party fetches the identity URL given above and discovers the identity provider URL. It then issues a standard OpenID 1.1 check_authentication request to the identity provider, including:
openid.mode=check_authentication openid.assoc_handle=... openid.sig=... openid.signed=request_url,identity openid.request_url=http://relyingparty.com/ openid.identity=http://example.com/Hopefully, the identity provider responds with is_valid=true and the client is authenticated. The relying party can then do whatever authorization checks it wants and produce a response.
I used "dumb mode" here for a couple of reasons:
- It's true to the stateless spirit of HTTP
- It makes for less to-ing and fro-ing in the (assumed) common case where the client is acting as its own identity provider.
- It avoids the need for an initial 401 Unauthorized, making it less of a pain for relying parties that are targetting both humans and bots.
This method of authentication is completely stateless and applies only for one request. The client must repeat the signature generation for each subsequent request, both because the request URL is part of the signature and because the identity provider can then use a different secret for each request to avoid replay attacks.
It is important that the secret keys and assoc_handles issued by the identity provider differ for each request so that replay attacks can be avoided.
URLs which do not do any kind of authentication will likely respond with a 200 OK to an unsolicited OpenID authentication request without resolving the signature. This means that the generated signature and assoc_handle will be "out there" but will never actually be used.
This means that identity providers must expire their signatures after a reasonable amount of time to avoid an accumulation of unresolved signatures which could potentially be used to impersonate the user should the request URL later begin supporting OpenID authentication.
Dual-mode Relying Parties
(NOTE: The practicality of this section is currently disputed, and this ability will likely have to be dropped or implemented some other way.)
For relying parties that service both humans using web browsers and software agents it would be useful to be able to declare the OpenID auth support without issuing a 401 Unauthorized.
Relying parties can be allowed to include the
WWW-Authenticate: OpenID header in a 200 OK response to facilitate this. The response body may contain an HTML form for humans to log in with or it may contain content aimed at unauthenticated users. Suitably-equipped software can detect the presence of the header and try to authenticate where it's supported.
User authentication in non-browser apps
This mechanism could also be of use to user-agents other than browsers which do not have the ability to render an HTML form and supply cookies. In this case, a separate protocol would be defined for authenticating with the identity provider and obtaining the necessary credentials to make a request as detailed above.
Authentication for User-attended RPC
(See also "OpenRPC" for some explanation of what is meant by "user-attended RPC")
User-attended RPC is simplified in the presence of the above protocol because it allows the RPC callers themselves to have an identity which the one-time RPC permission can be attached to. Previous specs for user-attended RPC have required complicated token-passing in order to authenticate the caller, but with the above they can just use standard OpenID authentication.