diff --git a/content/services/fxa-oauth-integration.rst b/content/services/fxa-oauth-integration.rst new file mode 100644 index 0000000..e203e95 --- /dev/null +++ b/content/services/fxa-oauth-integration.rst @@ -0,0 +1,119 @@ +How we implemented a Firefox Account OAuth service provider with Cornice +######################################################################## + +:slug: fxa-oauth-integration +:date: 23-12-2014 +:authors: Alexis Métaireau, Rémy Hubscher +:tags: FxA, python +:lang: en + +Daybed is user agnostic. It does not handle users and passwords but +tokens, using Hawk. When you log in, you obtain a Hawk Token derived +into credentials that are used to sign every request made to the API. + +This token can then represent anything: the user, the device or a +group of users that share the same token. + +This lets people use Daybed the way it fits their software. + +But on the other hand, when a user wants to user the same token on all +her devices, she needs a way to share it easily and securely. + +There are several ways to do it, among them: + +- Put the token in the URLs of your applications (like 0bin, doodle, google docs, ...), and share the URLs on your devices using synced bookmarks for example +- Build the token from the authorization header +- Build the token from a user id obtained via OAuth + + +Get a token using Basic-Auth +---------------------------- + +One way to solve this problem, was to let the user give an +Authorization header when asking for a new token. + +And make sure the same token would be generated for the same header. + +This works really well, because you can then use a login:password and +always grab the same Hawk-Credentials for it. + +In a nutshell it looks like this: + +.. code-block:: python + + http POST localhost:8000/v1/tokens --auth admin:password -v + + POST /v1/tokens HTTP/1.1 + Accept: */* + Accept-Encoding: gzip, deflate, compress + Authorization: Basic YWRtaW46cGFzc3dvcmQ= + Content-Length: 0 + Host: localhost:8000 + User-Agent: HTTPie/0.8.0 + + HTTP/1.1 201 Created + Content-Length: 266 + Content-Type: application/json; charset=UTF-8 + Date: Fri, 07 Nov 2014 15:09:01 GMT + Server: waitress + + { + "credentials": { + "algorithm": "sha256", + "id": "371ef18f8a054e5c9fb0961cc5b81006080e9ad22078d30b3727c7c32843579f", + "key": "87e72a8e5dcaf8b4be00b8729462814da3d438ce2fd8b6efee335db722d8369d" + }, + "token": "9f19de0237c9bd59f803de1785f7aea4e3499b6929df3428e1b415fed81f797a" + } + + +Get a token from Firefox Account using OAuth +-------------------------------------------- + +Basic-Auth is good but it means you need to enter your login password +in the client app and trust the usage they will do with it. + +Also for some application you want to trust the email address of the +user. + +One way to do that is to use Firefox Account. The email used has been +validated and the login is made on a trusted Mozilla server. + +The OAuth flow works as defined here: + +1. You access you service ``http://service/oauth/params`` url to get the OAuth configuration in ``conf`` +2. The app redirect the user to:: + + GET conf.oauth_uri + "/authorization?" + + "client_id=" + conf.client_id + + "&state=" + conf.state + + "&scope=profile&action=signin" + +3. The user logs in in the OAuth identity provider +4. After the password has been validated, the OAuth IDP redirect the user to ``http://service//oauth/token?state=&code=`` +5. Then the server ask ``POST conf.oauth_uri + "/token"`` with the ``code``, ``client_id`` and ``client_secret`` to get an ``access_token``. +6. The ``access_token`` can then be used to ask about the user profile: ``GET conf.profile_uri + "/profile"`` with ``Authorization: Bearer `` header. +7. From the profile you can get the ``email``, ``avatar`` and ``uid`` of the user. + +After the OAuth flow, we generate a token for this user, for the same +Firefox Account, the token will always be the same. + +You have got an example of the view implementations here: +https://github.com/spiral-project/daybed-fxa-oauth + + +Other authentication backends +----------------------------- + +We have made this Authentication layer a pluggable layer so that you +can deploy Daybed with any of the one you'd like as well as all of +them. + +You have another example for the BrowserID protocol here: +https://github.com/spiral-project/daybed-browserid + +You can use it with Persona, Firefox Account BrowserId and even +MSISDN-Gateway to let people log using their phone number. + +This plugins can also help you to implement other authentication +backends for Daybed. (SAML, other OAuth)