Fix changed names of imports
[pgweb/local.git] / docs / authentication.rst
blob8c43294b67ed90807626e38ae5033507850273ac
1 Community authentication 2.0
2 ============================
3 While the old community authentication system was simply having the
4 clients call a PostgreSQL function on the main website server, version
5 2.0 of the system uses browser redirects to perform this. This allows
6 for a number of advantages:
8 * The users password never hits the "community sites", only the main
9   website. This has some obvious security advantages.
10 * There is no need to allow external access from these sites to the
11   PostgreSQL database on the main website.
12 * It is possible for the user to get single sign-on between all the
13   community sites, not just same-password.
15 Each community site is still registered in the central system, to hold
16 encryption keys and similar details. This is now held in the main
17 database, accessible through the django administration system, instead
18 of being held in pg_hba.conf and managed through SQL.
20 The flow of an authentication in the 2.0 system is fairly simple:
22 #. The user tries to access a protected resource on the community
23    site.
24 #. At this point, the user is redirected to an URL on the main
25    website, specifically https://www.postgresql.org/account/auth/<id>/.
26    The <id> number in this URL is unique for each site, and is the
27    identifier that accesses all encryption keys and redirection
28    information.
29    In this call, the client can optionally include a parameter
30    *d*, which will be passed through back on the login confirmation.
31    This should be a base64 encoded parameter (other than the base64
32    character, the *$* character is also allowed and can be used to
33    split fields).
34    The client should encrypt or sign this parameter as necessary, and
35    without encryption/signature it should *not* be trusted, since it
36    can be injected into the authentication process without verification.
37 #. The main website will check if the user holds a valid, logged in,
38    session on the main website. If it does not, the user will be
39    sent through the standard login path on the main website, and once
40    that is done will be sent to the next step in this process.
41 #. The main website puts together a dictionary of information about
42    the logged in user, that contains the following fields:
44    u
45     The username of the user logged in
46    f
47      The first name of the user logged in
48    l
49      The last name of the user logged in
50    e
51      The email address of the user logged in
52    d
53      base64 encoded data block to be passed along in confirmation (optional)
54    su
55      *DEPRECATED* The suburl to redirect to (optional)
56    t
57      The timestamp of the authentication, in seconds-since-epoch. This
58      should be validated against the current time, and authentication
59      tokens older than e.g. 10 seconds should be refused.
61 #. This dictionary of information is then URL-encoded.
62 #. The resulting URL-encoded string is padded with spaces to an even
63    16 bytes, and is then AES encrypted with a shared key. This key
64    is stored in the main website system and indexed by the site id,
65    and it is stored in the settings of the community website somewhere.
66    Since this key is what protects the authentication, it should be
67    treated as very valuable.
68 #. The resulting encrypted string and the IV used for the encryption are
69    base64-encoded (in URL mode, meaning it uses - and _ instead of + and /.
70 #. The main website looks up the redirection URL registered for this site
71    (again indexed by the site id), and constructs an URL of the format
72    <redirection_url>?i=<iv>&d=<encrypted data>
73 #. The user browser is redirected to this URL.
74 #. The community website detects that this is a redirected authentication
75    response, and stars processing it specifically.
76 #. Using the shared key, the data is decrypted (while first being base64
77    decoded, of course)
78 #. The resulting string is urldecoded - and if any errors occur in the
79    decoding, the authentication will fail. This step is guaranteed to fail
80    if the encryption key is mismatching between the community site and
81    the main website, since it is going to end up with something that is
82    definitely not an url-decodeable string.
83 #. The community site will look up an existing user record under this
84    username, or create a new one if one does not exist already (assuming
85    the site keeps local track of users at all - if it just deals with
86    session users, it can just store this information in the session).
87    It is recommended that the community site verifies if the first name,
88    last name or email field has changed, and updates the local record if
89    this is the case.
90 #. The community site logs the user in using whatever method it's framework
91    uses.
92 #. If the *d* key is present in the data structure handed over, the
93    community site implements a site-specific action based on this data,
94    such as redirecting the user to the original location.
95 #. *DEPRECATED* If the *su* key is present in the data structure handed over, the
96    community site redirects to this location. If it's not present, then
97    the community site will redirect so some default location on the
98    site.
100 Logging out
101 -----------
102 If the community site implements functionality to log the user out, it
103 should also send a redirect to the main website to cause a logout from
104 this site as well. If this is not done, it will appear to the user as if
105 the logout didn't work, since upon next login the user is redirected and
106 automatically logged in again.
108 The flow for a logout request is trivial:
110 #. The community website logs the user out of the local instance, however
111    that works.
112 #. The community website redirects the user to
113    https://www.postgresql.org/account/auth/<id>/logout/ (where the id
114    number is the same id as during login)
115 #. The main website will log the user out of the community site
116 #. The main website redirects the user back to the community website,
117    at the URL <redirection_url>?s=logout (where redirection_url is the
118    same URL as when logging in)
120 Searching
121 ---------
122 The community authentication system also supports an API for searching for
123 users. The idea here is to give the ability to add a user to downstream
124 systems even if that user has not yet logged in (normally the user is added
125 on first login).
127 In order to not leak sensitive information about users, all search results
128 are returned encrypted with the same key as the authentication scheme.
130 The flow for search is:
132 #. Make an API call to
133    https://www.postgresql.org/account/auth/<id>/search/?<params>
134    where the id is the same id as during login, and params can be one of
135    the following:
137    s
138     Case insensitive substring search of name and email
139    n
140     Case insensitive substring search of name
141    e
142     Case insensitive substring search of email
143    u
144     Exact search of username
146 #. The returned data will be an array of JSON objects, with the following keys:
148    u
149     Username
150    e
151     Email
152    f
153     First name
154    l
155     Last name