Skip to content

Instantly share code, notes, and snippets.

@kgaughan
Last active January 11, 2016 13:51
Show Gist options
  • Save kgaughan/95bea100f9c451a90e47 to your computer and use it in GitHub Desktop.
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.
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