1
Copyright 2010 Canonical Ltd. This software is licensed under the
2
GNU Affero General Public License version 3 (see the file LICENSE).
4
= Launchpad Single-Signon Workflow: Authorize =
6
If a user has logged into Launchpad and then wants to log in to a
7
Launchpad-SSO web site, they are not prompted for a password.
9
First we will set up the helper view that lets us test the final
10
portion of the authentication process:
12
>>> from openid.consumer.consumer import Consumer
13
>>> from openid.fetchers import setDefaultFetcher
14
>>> from openid.store.memstore import MemoryStore
15
>>> from canonical.signon.testing.openidhelpers import (
16
... complete_from_browser, make_identifier_select_endpoint,
18
>>> setDefaultFetcher(PublisherFetcher())
20
The authentication process is started by the relying party issuing a
21
checkid_setup request, sending the user to Launchpad. We will
22
authenticate before starting the login procedure:
24
>>> browser.open('http://openid.launchpad.dev/+login')
25
>>> browser.getControl(name='email').value = 'mark@example.com'
26
>>> browser.getControl(name='password').value = 'test'
27
>>> browser.getControl(name='continue').click()
29
>>> openid_store = MemoryStore()
30
>>> consumer = Consumer(session={}, store=openid_store)
31
>>> request = consumer.beginWithoutDiscovery(
32
... make_identifier_select_endpoint(PROTOCOL_URI))
34
# Use localhost instead of launchpad.dev because Launchpad is not
35
# recorded as an OpenIDRPSummary.
36
>>> browser.open(request.redirectURL(
37
... 'http://localhost/', 'http://localhost/+openid-consumer'))
39
Each OpenID authentication is recorded as an OpenIDRPSummary. This user
40
has not ever used Launchpad to authenticate with a relying party.
42
>>> from identityprovider.models import OpenIDRPSummary
44
>>> summaries = OpenIDRPSummary.objects.filter(
45
... openid_identifier='http://openid.launchpad.dev/+id/mark_oid')
49
At this point, the user is presented with a form asking if they want
50
to authenticate to the relying party
52
>>> print browser.title
53
Authenticate to http://localhost/
55
By clicking the "Sign In" button, the user is returned to the relying
56
party with their identity URL:
58
>>> browser.getControl(name='yes', index=0).click()
60
http://localhost/+openid-consumer?...
61
>>> info = complete_from_browser(
62
... consumer, browser, 'http://openid.launchpad.dev/+id/mark_oid')
65
>>> print info.endpoint.claimed_id
66
http://openid.launchpad.dev/+id/mark_oid
68
The authentication was recorded. There is a summary showing that the
69
user has used the replying part once.
71
>>> summaries = OpenIDRPSummary.objects.filter(
72
... openid_identifier='http://openid.launchpad.dev/+id/mark_oid')
73
>>> for summary in summaries:
74
... summary.openid_identifier
75
... summary.trust_root
76
... summary.total_logins
77
u'http://openid.launchpad.dev/+id/mark_oid'
82
== Declining to Authenticate ==
84
Alternatively, the user could have declined to authenticate. This
85
time, we will cancel the authentication request:
87
>>> request = consumer.beginWithoutDiscovery(
88
... make_identifier_select_endpoint(PROTOCOL_URI))
89
>>> browser.open(request.redirectURL(
90
... 'http://launchpad.dev/', 'http://launchpad.dev/+openid-consumer'))
92
>>> print browser.title
93
Authenticate to http://launchpad.dev/
94
>>> browser.getLink(url="+cancel").click()
96
http://launchpad.dev/+openid-consumer?...
97
>>> info = complete_from_browser(
98
... consumer, browser, 'http://openid.launchpad.dev/+id/mark_oid')
105
>>> setDefaultFetcher(None)
106
>>> summaries = OpenIDRPSummary.objects.filter(
107
... openid_identifier='http://openid.launchpad.dev/+id/mark_oid')
108
>>> summaries.delete()