Last active
January 11, 2016 13:51
-
-
Save kgaughan/95bea100f9c451a90e47 to your computer and use it in GitHub Desktop.
Single sign-on - this is only a thought experiment, and it likely full of holes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Nomenclature: | |
The REQUESTING SYSTEM is the system requesting that some entity be | |
authenticated. | |
The AUTHENTICATING SYSTEM is the system the performs the authentication of an | |
entity for the requesting system. | |
The IDENTITY TOKEN is a token used by both systems to identify a user. An email | |
address would be the best candidate. The requesting system should tie this | |
token to an account on its end. | |
Assumptions: | |
The requesting and authenticating systems can both generate unique URLs in a | |
cryptographically secure fashion for 'notify', 'return', and 'form'. | |
Flow: | |
1. User visits the requesting system and selects/enters an identity token. | |
2. System takes takes the domain part out of the token and does an NAPTR | |
lookup for the auth service, and applies the returned regex to the token. | |
This gives an authentication endpoint URL. | |
3. The requesting system POSTs over HTTPS the following JSON document to | |
the aforementioned endpoint: | |
{ | |
// A unique endpoint to redirect to after authentication has succeeded. | |
'return': 'https://...', | |
// A URL to POST to internally by the authenticator once authentication | |
// has succeeded. This is where the authenticator can send information | |
// about the user such as permissions, &c. This should also be unique | |
// and shouldn't contain any *critical* information in the 'return' | |
// URL. If there is shared information between the two, it must be safe | |
// to pass in the open. | |
'notify': 'https://...', | |
// Used for rough time synchronisation. Timeout is in seconds. | |
'now': '2016-01-11T12:00:00Z', | |
'timeout': 300, | |
// Optional lists of information that is requested to be send back to | |
// the 'notify' URL upon successful authentication. If missing, it's | |
// the same as sending an empty list. These should probably be URIs. | |
// The array should contain no duplicate items. 'need' lists required | |
// information and 'want' lists optional information. | |
'need': [ | |
'name', | |
'email', | |
'foo', | |
], | |
'want': [ | |
'fred', | |
'barney', | |
'tag:example.net,2012:bar' | |
], | |
} | |
The endpont returns the following: | |
{ | |
// Form to redirect to where the auth will take place. | |
'form': 'https://...', | |
// Used for rough time synchronisation. Timeout is in seconds. | |
'now': '2016-01-11T12:00:00Z', | |
'timeout': 600 | |
} | |
4. The user is redirected to the form listed in 'form'. The URL should be | |
unique for all interactions. It doesn't necessarily have to use a form: the | |
authentication mechanism could really be anything. | |
5. The user enters their credentials. If successful, the system POSTs to the | |
'notify' URL, and redirects to the 'return' URL. | |
The 'notify' document should look something like the following: | |
{ | |
// Used for rough time synchronisation. Timeout is in seconds. | |
'now': '2016-01-11T12:00:00Z', | |
'timeout': 300, | |
// Either this, which indicates that the authenticating system has to | |
// with the user whether to pass on the given information, or... | |
'defer': true, | |
// The information requested in 'need' and 'want': | |
'requested': { | |
'name': 'Jane Doe', | |
'email': '[email protected]', | |
'fred': 'wilma', | |
'barney': 'betty', | |
'foo': {'bar': 'baz'}, | |
'tag:example.net,2012:bar': { | |
'foo': ['bar'], | |
} | |
} | |
} | |
[Aside: need to work out the HTTP response codes for the sad paths.] | |
The authenticating system is given a chance to ask the user if they are OK | |
with data being passed on to the requesting system. The user may deny | |
access to information listed under 'want', but information under 'need' is | |
always sent if the user confirms the request. It can defer the confirmation | |
of this by sending 'defer' rather than the requested information to the | |
requesting system. If the requesting system is happy with this, it responds | |
with a 202 (Accepted) status code, and if it isn't, it responds with 403 | |
(Forbidden). If passing the requested data has not been deferred, the | |
requesting system responds with 200 (OK). If the authorising system doesn't | |
pass all the information listed in 'need', the requesting system responds | |
with 400 (Bad Request). | |
The use case for a deferred request is to allow authentication to succeed | |
quickly before any data needs to be passed to the request to prevent a | |
timeout. | |
In the case of a deferred response, the 'notify' URL is POSTed to again as | |
soon as the request is confirmed. | |
The authenticating system can cancel an authentication session by performing | |
a DELETE on the 'notify' URL. | |
Open questions: | |
* This is chatty if you're requesting information about the authenticated | |
entity. There ought to be a way to avoid unnecessary requests for | |
information. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment