OAuth.io

Simplified multi-providers
authorization

OAuth


OAUTH 2 protocol

1 - Create the application

OAUTH 2 PROTOCOL

1 - Create the application

OAuth 2 Protocol

2 - Redirection

www.facebook.com/dialog/oauth/authorize
client_id=...
response_type=code
scope=email,read_friendlists...
redirect_uri=http://mysite.com
state=...


3 - Authorize callback



http://mysite.com/?code=...&state=...


4 - Receive the token

POST graph.facebook.com/oauth/access_token

code=...
client_id=...
client_secret=...
grant_type=authorization_code


OAuth 2 Protocol

2 - Redirection

client_id -> app_id=...
response_type=code
scope -> perms=email,read_friendlists...
redirect_uri=http://mysite.com
state=... [non documenté]


3 - Authorize callback



http://mysite.com/?code=...&state=...


4 - Receive the token


code=...
client_id ->  app_id=...
client_secret -> secret=...
grant_type=authorization_code


OAUTH 2 FLAWS



api.provider.com/path/action?access_token=TOKEN

api.provider.com/path/action?oauth_token=TOKEN

api.provider.com/path/action?token=TOKEN

Authorization: Bearer TOKEN

Authorization: OAuth TOKEN

OAUTH 2 flaws


scope=email%20publish
scope=email,publish
scope=email;publish
scope=email:publish
scope=email|publish

scope=read_only   or   scope=read_write

oauth 2 flaws

In the results of /access_token:

extra data (facultatif)
"user": {
                 id: "..."
                          name: "..."
           // ...
}                

extra data (requis)
"instance_url": "https://eu2.salesforce.com"

oauth 2 flaws


MailChimp

One added step:  /oauth2/metadata

{
    "dc":"us1",
    "login_url":"https://login.mailchimp.com",
    "api_endpoint":"https://us1.api.mailchimp.com"
}

oauth 2 flaws


Custom signature

mail.ru, odnoklassniki.ru, renren... 

sig = md5(uid + params + private_key)

oauth 2 flaws


Custom constant

Tencent weibo:

oauth_version=2.a

OAUTH 2 FLAWS


The "state" param

  • inexistent (dailymotion, eventbrite...)
  • undocumented (wordpress, deezer...)
  • impossible (angellist)

Multi providers oauth



Oauth.io



OAUTH.IO


 OAuth.popup('facebook', function(err, res) {
    if (err) {
        // do something with error
    }    // the access token is res.access_token !})


OAUTH.io


 OAuth.popup('facebook', function(err, res) {
    if (err) {
        // do something with error
    }    res.get('/me')
.done(function(data) { alert('Hello ' + data.name) }) })


OAUTH.IO


 OAuth.popup('twitter', function(err, res) {
    if (err) {
        // do something with error
    }    res.get('/1.1/account/verify_credentials.json')
       .done(function(data) {
        alert('Hello ' + data.name)
    })
})


OAUTH.IO


Android, iOS, Flex et Phonegap


Examples


Client-side twitter timeline


TEMPLATE

<html ng-app="demoApp">   <head>     <!-- title, js/css (jquery/bootstrap/angular) -->     <script src="/oauth.js"></script>
     <script src="/app.js"></script>
     <link rel="stylesheet" type="text/css" href="/basic.css" />
   </head>

   <body>
        <div class="container">
            <h1>Twitter ~ client-side timeline</h1>
            <div class="well">
                <div class="basic-content" ng-view></div>
            </div>
        </div>
   </body>
</html>

Angularjs app


var demoApp = angular.module('demoApp', ['ngRoute']);

demoApp.config(function($routeProvider) {
	$routeProvider.when('/timeline', {
	    templateUrl: '/partials/timeline.html',
	    controller: 'timelineCtrl'
	}).when('/connect', {
	    templateUrl: '/partials/connect.html',
	    controller: 'connectCtrl'
	}).otherwise({
            redirectTo: '/connect'
	});
});

CONNECT Controller


Connect Controller

<h3>Connect with twitter to see your home timeline</h3><button ng-click='connect()' class="btn btn-primary">    <img src="https://oauth.io/api/providers/twitter/logo" />    connect with twitter</button>
demoApp.controller('connectCtrl', function ($scope,                                $rootScope, $location) {	OAuth.initialize("hMOd7zAuUxDSM...");
	$scope.connect = function() {
             OAuth.popup("twitter", function(err, res) {
                if (err) return alert(err);
                $rootScope.twitter = res;
                $location.path('/timeline');
                $scope.$apply();
	    });
	}
});

TIMELINE CONTROLLER


TIMELINE CONTROLLER

<ul id="timeline" ng-repeat="entry in tw_timeline">
<li> <img class="thumb" src="{{entry.user.profile_image_url}}" /> <span class="content"> <span class="author">{{entry.user.name}}</span> <span class="text">{{entry.text}}</span> </span> </li> </ul>
demoApp.controller('timelineCtrl', function ($scope,                                         $rootScope) {
$rootScope.twitter.get('/1.1/statuses/home_timeline.json') .done(function(data) { $scope.tw_timeline = data; $scope.$apply(); }); });


EXAMPLES


Synchro google drive

Connect ControlLER


... et redirige vers /editor

CONNECT CONTROLLER


$scope.connect = function() {
    OAuth.popup("google_drive", function(err, res) {
        if (err) return alert(err);
        $rootScope.drive = res;
        getDriveFile("realtime_test", function (file) {
            $rootScope.drive_file = file;
            $location.path('/editor');
            $scope.$apply();
        });
    });
}

CONNECT CONTROLLER


getDriveFile

function getDriveFile(title, callback) {
$rootScope.drive.get({ url: "/drive/v2/files", data: {q: "title = '" + title + "'"} }).done(function(files) { if (files.items.length) return callback(files.items[0]); // create file if it does not exists createDriveFile(title, callback); }); }

connect controller


createDriveFile

function createDriveFile(title, callback) {
$rootScope.drive.post({ url: "/drive/v2/files", data: JSON.stringify({ title: title, mimeType:'application/vnd.google-apps.document'}), contentType: 'application/json' }).done(function(item) { callback(item); }); }

EDITOR Controller


EDITOR CONTROLLER

<textarea id="editor" ng-model="file_content"></textarea>
demoApp.controller('editorCtrl', function($scope,                                       $rootScope) {    $rootScope.drive.get(        $rootScope.drive_file.exportLinks['text/plain'])    .done(function(data) {
	$scope.file_content = data;
		$scope.$apply();

	$scope.$watch("file_content", function() {
	    $scope.must_save = true;
	    updateFile();        });    });
    function updateFile() {
        // ...
    }
}

editor controller

updateFile
function updateFile() {    if ( ! $scope.must_save) return;
    if ($scope.saving) return setTimeout(updateFile, 50);

    $scope.saving = true;
    $scope.must_save = false;
    $rootScope.drive.put({
        url: "/upload/drive/v2/files/"
            + $rootScope.drive_file.id +
            + "?uploadType=media",
        data: $scope.file_content
    }).always(function() {
        $scope.saving = false;
        updateFile();
    });
}


Thanks !


https://slid.es/arnaudrichard/angular-oauth-io

https://github.com/bumpmann/demo-oauthio-twitter
https://github.com/bumpmann/demo-oauthio-drive