| Class | OpenID::OpenIDConsumer |
| In: |
lib/openid/consumer.rb
|
| Parent: | Object |
This class implements the interface for using the OpenID consumer libary.
The only part of the library which has to be used and isn‘t documented in full here is the store required to create an OpenID::OpenIDConsumer instance. More on the abstract store type and concrete implementations of it that are provided in the documentation of OpenID::OpenIDConsumer.new
The OpenID identity verification process most commonly uses the following steps, as visible to the user of this library:
The most important part of the flow to note is the consumer‘s site must handle two separate HTTP requests in order to perform the full identity check.
The library is designed with the above flow in mind. The goal is to make it as easy as possible to perform the above steps securely.
At a high level, there are two important parts in the consumer library. The first important part is this class, which contains the public interface to actually use this library. The second is the OpenID::OpenIDStore class, which describes the interface to use if you need to create a custom method for storing the state this library needs to maintain between requests.
In general, the second part is less important for users of the library to know about, as several implementations are provided which cover a wide variety of situations in which consumers may use the library.
The OpenIDConsumer class contains three public methods corresponding to the actions necessary in each of steps 2, 3, and 4 described in the overview. Use of this library should be as easy as creating an OpenIDConsumer object and calling the methods appropriate for the action the site wants to take.
OpenID is a protocol that works best when the consumer site is able to store some state. This is the normal mode of operation for the protocol, and is sometimes referred to as smart mode. There is also a fallback mode, known as dumb mode, which is available when the consumer site is not able to store state. This mode should be avoided when possible, as it leaves the implementation more vulnerable to replay attacks.
The mode the library works in for normal operation is determined by the store that it is given. The store is an abstraction that handles the data that the consumer needs to manage between http requests in order to operate efficiently and securely.
Several store implementation are provided, and the interface is fully documented so that custom stores can be used as well. The concrete implementations that are provided allow the consumer site to store the necessary data in several different ways: in the filesystem, or in an SQLite database.
There is an additional concrete store provided that puts the system in dumb mode. This is not recommended, as it removes the library‘s ability to stop replay attacks reliably. It still uses time-based checking to make replay attacks only possible within a small window, but they remain possible within that window. This store should only be used if the consumer site has no way to retain data between requests at all.
In the flow described above, the user may need to confirm to the identity server that it‘s ok to authorize his or her identity. The server may draw pages asking for information from the user before it redirects the browser back to the consumer‘s site. This is generally transparent to the consumer site, so it is typically ignored as an implementation detail.
There can be times, however, where the consumer site wants to get a response immediately. When this is the case, the consumer can put the library in immediate mode. In immediate mode, there is an extra response possible from the server, which is essentially the server reporting that it doesn‘t have enough information to answer the question yet. In addition to saying that, the identity server provides a URL to which the user can be sent to provide the needed information and let the server finish handling the original request.
Integrating this library into an application is usually a relatively straightforward process. The process should basically follow this plan:
Add an OpenID login field somewhere on your site. When an OpenID is entered in that field and the form is submitted, it should make a request to the your site which includes that OpenID URL.
When your site receives that request, it should create an OpenID::OpenIDConsumer instance, and call OpenID::OpenIDConsumer.begin_auth>. If begin_auth completes successfully, it will return an OpenID::OpenIDAuthRequest. Otherwise it will provide some useful information for giving the user an error message.
Now that you have the OpenIDAuthRequest object, you need to preserve the value in its OpenIDAuthRequest.token field for lookup on the user‘s next request from your site. There are several approaches for doing this which will work. If your environment has any kind of session-tracking system, storing the token in the session is a good approach. If it doesn‘t you can store the token in either a cookie or in the return_to url provided in the next step.
The next step is to call the OpenID::OpenIDConsumer.construct_redirect>}} method on the OpenIDConsumer object. Pass it the OpenIDAuthRequest object returned by the previous call to begin_auth along with the return_to and trust_root URLs. The return_to URL is the URL that the OpenID server will send the user back to after attempting to verify his or her identity. The trust_root is the URL (or URL pattern) that identifies your web site to the user when he or she is authorizing it.
Next, send the user a redirect to the URL generated by OpenID::OpenIDConsumer.construct_redirect
That‘s the first half of the process. The second half of the process is done after the user‘s ID server sends the user a redirect back to your site to complete their login.
When that happens, the user will contact your site at the URL given as the return_to URL to the OpenID::OpenIDConsumer.construct_redirect call made above. The request will have several query parameters added to the URL by the identity server as the information necessary to finish the request.
When handling this request, the first thing to do is check the openid.return_to parameter. If it doesn‘t match the URL that the request was actually sent to (the URL the request was actually sent to will contain the openid parameters in addition to any in the return_to URL, but they should be identical other than that), that is clearly suspicious, and the request shouldn‘t be allowed to proceed.
Otherwise, the next step is to extract the token value set in the first half of the OpenID login. Create a OpenIDConsumer object, and call its OpenID::OpenIDConsumer.complete_auth method with that token and a dictionary of all the query arguments. This call will return a status code and some additional information describing the the server‘s response. See the documentation for OpenID::OpenIDConsumer.complete_auth for a full explanation of the possible responses.
At this point, you have an identity URL that you know belongs to the user who made that request. Some sites will use that URL directly as the user name. Other sites will want to map that URL to a username in the site‘s traditional namespace. At this point, you can take whichever action makes the most sense.
This class provides the interface to the OpenID consumer logic. Instances maintain no per-request state, so they can be reused (or even used by multiple threads concurrently) as needed.
Creates a new OpenIDConsumer instance.
begin_auth is called to start the OpenID login process.
Returns an array with two elements. The first element is a status code, and the second element contains additional information about the status and is dependant on the first.
If there was a problem fetching the identity page the user gave, the status code is set to OpenID::HTTP_FAILURE, and the additional information value is either set to nil if the HTTP transaction failed or the HTTP return code, which will be in the 400-500 range. This additional information value may change in a future release.
If the identity page fetched successfully, but didn‘t include the correct link tags, the status code is set to OpenID::PARSE_ERROR, and the additional information value is currently set to nil. The additional information value may change in a future release.
Otherwise, the status code is set to OpenID::SUCCESS, and the additional information is an instance of OpenIDAuthRequest. The OpenIDAuthRequest.token attribute contains the token to be preserved for the next HTTP request. The OpenIDAuthRequest.server_url might also be of interest, if you wish to blacklist or whitelist OpenID servers. The other contents of the object are information needed in the construct_redirect call.
First, the user‘s claimed identity page is fetched, to determine their identity server. If the page cannot be fetched or if the page does not have the necessary link tags in it, this method returns one of OpenID::HTTP_FAILURE or OpenID::PARSE_ERROR, depending on where the process failed.
Second, unless the store provided is a dumb store, it checks to see if it has an association with that identity server, and creates and stores one if not.
Third, it generates a signed token for this authentication transaction, which contains a timestamp, a nonce, and the information needed in step 4 in the module overview. The token is used by the library to make handling the various pieces of information needed in step 4 easy and secure.
The token generated must be preserved until step 4, which is after the redirect to the OpenID server takes place. This means that the token must be preserved across http requests. There are three basic approaches that might be used for storing the token. First, the token could be put in the return_to URL passed into the OpenIDConsumer.construct_redirect method. Second, the token could be stored in a cookie. Third, in an environment that supports user sessions, the session is a good spot to store the token.
This method does not handle any exceptions raised by the store or fetcher it is using. It raises no exceptions itself.
Called to interpret the server‘s response to an OpenID request. It is called in step 4 of the flow described in the overview.
The return value is an array of two elements, consisting of a status and additional information. The status values are strings, but should be referred to by their symbolic values: OpenID::SUCCESS, OpenID::FAILURE, and OpenID::SETUP_NEEDED.
When OpenID::SUCCESS is returned, the additional information returned is either nil or a string. If it is nil, it means the user cancelled the login, and no further information can be determined. If the additional information is a string, it is the identity that has been verified as belonging to the user making this request.
When OpenID::FAILURE is returned, the additional information is either nil or a string. In either case, this code means that the identity verification failed. If it can be determined, the identity that failed to verify is returned. Otherwise nil is returned.
When OpenID::SETUP_NEEDED is returned, the additional information is the user setup URL. This is a URL returned only as a response to requests made with openid.mode=immediate, which indicates that the login was unable to proceed, and the user should be sent to that URL if they wish to proceed with the login.
This method does not handle any exceptions raised by the fetcher or store. It raises no exceptions itself.
Called to construct the redirect URL sent to the browser to ask the server to verify its identity. This is called in step 3 of the flow described in the overview. The generated redirect should be sent to the browser which initiated the authorization request.
Return a string which is the URL to which you should redirect the user.
This method does not handle exceptions thrown by the store it is using.