From 0d9a455ae9d603eb2f6e97570b9c4d1359b09a1d Mon Sep 17 00:00:00 2001 From: slickplaid Date: Tue, 28 Jun 2011 10:12:03 -0500 Subject: [PATCH 1/6] Make .authorizePath() accept either URI or path --- lib/modules/oauth.js | 49 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/lib/modules/oauth.js b/lib/modules/oauth.js index e8f6493a..7db39046 100644 --- a/lib/modules/oauth.js +++ b/lib/modules/oauth.js @@ -1,6 +1,7 @@ var everyModule = require('./everymodule') , OAuth = require('oauth').OAuth , url = require('url') + , querystring = require('querystring') , extractHostname = require('../utils').extractHostname; var oauth = module.exports = @@ -10,7 +11,8 @@ everyModule.submodule('oauth') , oauthHost: 'the host for the OAuth provider' , requestTokenPath: "the path on the OAuth provider's domain where we request the request token, e.g., /oauth/request_token" , accessTokenPath: "the path on the OAuth provider's domain where we request the access token, e.g., /oauth/access_token" - , authorizePath: 'the path on the OAuth provider where you direct a visitor to login, e.g., /oauth/authorize' + , authorizePath: 'the path or full uri on the OAuth provider where you direct a visitor to login, e.g., /oauth/authorize or http://api-user.netflix.com/' + , moreAuthQueryParams: 'Additional querystrings to provide during the authorize step. e.g., { application_name: "testapp" }' , consumerKey: 'the api key provided by the OAuth provider' , consumerSecret: 'the api secret provided by the OAuth provider' , myHostname: 'e.g., http://localhost:3000 . Notice no trailing slash' @@ -81,7 +83,7 @@ everyModule.submodule('oauth') } var p = this.Promise(); - this.oauth.getOAuthRequestToken( function (err, token, tokenSecret, authUrl, params) { + this.oauth.getOAuthRequestToken( function (err, token, tokenSecret, /* authUrl, */ params) { if (err) return p.fail(err); p.fulfill(token, tokenSecret); }); @@ -95,12 +97,51 @@ everyModule.submodule('oauth') _provider.tokenSecret = tokenSecret; }) .redirectToProviderAuth( function (res, token) { + + var url = (/^http/.test(this._authorizePath)) + ? this._authorizePath + : this._oauthHost + this._authorizePath + , params = { + oauth_token: token + , oauth_callback: this._myHostname + this._callbackPath + } + , additionalParams = this._moreAuthQueryParams + , param + , authUri; + + if (additionalParams) for (var k in additionalParams) { + param = additionalParams[k]; + if ('function' === typeof param) { + // e.g., for facebook module, param could be + // function () { + // return this._scope && this.scope(); + // } + additionalParams[k] = // cache the function call + param = param.call(this); + } + //if ('function' === typeof param) { + // // this.scope() itself could be a function + // // to allow for dynamic scope determination - e.g., + // // function (req, res) { + // // return req.session.onboardingPhase; // => "email" + // // } + // param = param.call(this, req, res); + //} + params[k] = param; + } + + authUri = url + '?' + querystring.stringify(params); + res.writeHead(303, {'Location': authUri}); + res.end(); + + // Build URI from host + authorizePath if authorizeURI is absent (default behavior) // Note: Not all oauth modules need oauth_callback as a uri query parameter. As far as I know, only readability's // module needs it as a uri query parameter. However, in cases such as twitter, it allows you to over-ride // the callback url settings at dev.twitter.com from one place, your app code, rather than in two places -- i.e., // your app code + dev.twitter.com app settings. - res.writeHead(303, { 'Location': this._oauthHost + this._authorizePath + '?oauth_token=' + token + '&oauth_callback=' + this._myHostname + this._callbackPath }); - res.end(); + //res.writeHead(303, { 'Location': this._oauthHost + this._authorizePath + '?oauth_token=' + token + '&oauth_callback=' + this._myHostname + this._callbackPath }); + //res.end(); + }) // Steps for GET `callbackPath` From 2af742e57071faed315c979bf002519251f71e43 Mon Sep 17 00:00:00 2001 From: slickplaid Date: Tue, 28 Jun 2011 10:17:04 -0500 Subject: [PATCH 2/6] Removed function execution. --- lib/modules/oauth.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/lib/modules/oauth.js b/lib/modules/oauth.js index 7db39046..7a4095b9 100644 --- a/lib/modules/oauth.js +++ b/lib/modules/oauth.js @@ -111,14 +111,16 @@ everyModule.submodule('oauth') if (additionalParams) for (var k in additionalParams) { param = additionalParams[k]; - if ('function' === typeof param) { - // e.g., for facebook module, param could be - // function () { - // return this._scope && this.scope(); - // } - additionalParams[k] = // cache the function call - param = param.call(this); - } + // Leaving this in in case needed in the future. + // Caused problems because req object wasn't passed to this function. + //if ('function' === typeof param) { + // // e.g., for facebook module, param could be + // // function () { + // // return this._scope && this.scope(); + // // } + // additionalParams[k] = // cache the function call + // param = param.call(this); + //} //if ('function' === typeof param) { // // this.scope() itself could be a function // // to allow for dynamic scope determination - e.g., From 3ea658b667b047676d634719ba41ba07e066abd9 Mon Sep 17 00:00:00 2001 From: slickplaid Date: Tue, 28 Jun 2011 10:17:27 -0500 Subject: [PATCH 3/6] Added netflix module --- lib/modules/netflix.js | 48 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 lib/modules/netflix.js diff --git a/lib/modules/netflix.js b/lib/modules/netflix.js new file mode 100644 index 00000000..8ef8c6a4 --- /dev/null +++ b/lib/modules/netflix.js @@ -0,0 +1,48 @@ +var oauthModule = require('./oauth') + , querystring = require('querystring') + , xml2js = require('xml2js'); + +var netflix = module.exports = +oauthModule.submodule('netflix') + .apiHost('http://api.netflix.com') + .oauthHost('http://api.netflix.com') + + // abnormal authorize URI + .authorizePath('https://api-user.netflix.com/oauth/login') + + .entryPath('/auth/netflix') + .callbackPath('/auth/netflix/callback') +// ?oauth_token=uh5g3j69prfze4f7k9q2mm3e&oauth_verifier= + + .getAccessToken( function (reqToken, reqTokenSecret, verifier) { + var promise = this.Promise() + , extraParams = { + consumer_key: this._consumerKey + , consumer_secret: this._consumerSecret + }; + this.oauth._performSecureRequest(reqToken, reqTokenSecret, "POST", this._apiHost + this._accessTokenPath, extraParams, null, null, function(error,data,res){ + if( error ) promise.fail(error); + else { + var results= querystring.parse( data ); + var oauth_access_token= results["oauth_token"]; + delete results["oauth_token"]; + var oauth_access_token_secret= results["oauth_token_secret"]; + delete results["oauth_token_secret"]; + promise.fulfill(oauth_access_token, oauth_access_token_secret, results) + } + }); + return promise; + }) + + .fetchOAuthUser( function (accessToken, accessTokenSecret, params) { + var promise = this.Promise() + , parser = new xml2js.Parser(); + parser.addListener('end', function(data){ + return promise.fulfill(data); + }); + this.oauth.get(this.apiHost() + '/users/'+params.user_id, accessToken, accessTokenSecret, function (err, data) { + if (err) return promise.fail(err); + return parser.parseString(data); + }); + return promise; + }); From 49249f66a1cd05d1c02026aba46f7b7d770cbc3d Mon Sep 17 00:00:00 2001 From: slickplaid Date: Tue, 28 Jun 2011 10:28:58 -0500 Subject: [PATCH 4/6] Added netflix to README.md --- README.md | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/README.md b/README.md index 6405236d..e442744d 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ So far, `everyauth` enables you to login via: - `dropbox`                                    (Credits [Torgeir](https://github.com/torgeir)) - `justin.tv`                                 (Credits [slickplaid](https://github.com/slickplaid)) - `vimeo`                                 (Credits [slickplaid](https://github.com/slickplaid)) + - `netflix`                                 (Credits [slickplaid](https://github.com/slickplaid)) - OAuth2 - `facebook` - `github` @@ -1018,6 +1019,66 @@ To see all parameters that are configurable, the following will return an object everyauth.justintv.configurable(); ``` +## Setting up Netflix OAuth + +You will first need to sign up for a [developer application](http://developer.netflix.com/) to get the [application name, consumer key and secret](http://developer.netflix.com/apps/mykeys). + +```javascript +var everyauth = require('everyauth') + , connect = require('connect'); + +everyauth.netflix + .consumerKey('YOUR CONSUMER KEY HERE') + .consumerSecret('YOUR CONSUMER SECRET HERE') + .moreAuthQueryParams({ + oauth_consumer_key: 'YOUR CONSUMER KEY HERE' + , application_name: 'APPLICATION NAME HERE' + }) + .findOrCreateUser( function (sess, accessToken, accessSecret, user) { + // find or create user logic goes here + // + // e.g., + // return usersByNetflixId[user.id] || (usersByNetflixId[user.id] = user); + }) + .redirectPath('/'); + +var routes = function (app) { + // Define your routes here +}; + +connect( + connect.bodyParser() + , connect.cookieParser() + , connect.session({secret: 'whodunnit'}) + , everyauth.middleware() + , connect.router(routes); +).listen(3000); +``` + +You can also configure more parameters (most are set to defaults) via +the same chainable API: + +```javascript +everyauth.netflix + .entryPath('/auth/netflix') + .callbackPath('/auth/netflix/callback'); +``` + +If you want to see what the current value of a +configured parameter is, you can do so via: + +```javascript +everyauth.netflix.callbackPath(); // '/auth/netflix/callback' +everyauth.netflix.entryPath(); // '/auth/netflix' +``` + +To see all parameters that are configurable, the following will return an +object whose parameter name keys map to description values: + +```javascript +everyauth.netflix.configurable(); +``` + ## Setting up Vimeo OAuth You will first need to sign up for a [developer application](http://vimeo.com/api/applications) to get the consumer key and secret. From 40c7f76c6ad263399877a1f07e06a1bf4a0449ba Mon Sep 17 00:00:00 2001 From: slickplaid Date: Tue, 28 Jun 2011 11:14:17 -0500 Subject: [PATCH 5/6] Added example for netflix module. --- example/conf.js | 5 +++++ example/server.js | 14 ++++++++++++++ example/views/home.jade | 3 +++ 3 files changed, 22 insertions(+) diff --git a/example/conf.js b/example/conf.js index 8cb54960..77aa6f60 100644 --- a/example/conf.js +++ b/example/conf.js @@ -47,6 +47,11 @@ module.exports = { consumerKey: 'Enter your consumer key here' , consumerSecret: 'Enter your consumer secret here' } + , netflix: { + consumerKey: 'Enter your consumer key here' + , consumerSecret: 'Enter your consumer secret here' + , application_name: 'Enter your application name here' + } , box: { apiKey: '5hl66lbfy0quj8qhhzcn57dflb55y4rg' } diff --git a/example/server.js b/example/server.js index 4823b4ef..63915d21 100644 --- a/example/server.js +++ b/example/server.js @@ -4,6 +4,7 @@ var express = require('express') everyauth.debug = true; +var usersByNetflixId = {}; var usersByVimeoId = {}; var usersByJustintvId = {}; var usersByDropboxId = {}; @@ -224,6 +225,19 @@ everyauth.justintv }) .redirectPath('/') +everyauth.netflix + .consumerKey(conf.netflix.consumerKey) + .consumerSecret(conf.netflix.consumerSecret) + .moreAuthQueryParams({ + oauth_consumer_key: conf.netflix.consumerKey + , application_name: conf.netflix.application_name + }) + .findOrCreateUser( function (sess, accessToken, accessSecret, netflixUser) { + return usersByJustintvId[justintvUser.id] || + (usersByNetflixId[netflixUser.id] = netflixUser); + }) + .redirectPath('/') + everyauth.box .apiKey(conf.box.apiKey) .findOrCreateUser( function (sess, authToken, boxUser) { diff --git a/example/views/home.jade b/example/views/home.jade index 5760e445..a6784a3a 100644 --- a/example/views/home.jade +++ b/example/views/home.jade @@ -45,6 +45,9 @@ #justintv-login a(href='/auth/justintv', style='border: 0px') img(src='http://s.jtvnw.net/jtv_user_pictures/hosted_images/new_logo_148_40_black.png') + #netflix-login + a(href='/auth/netflix', style='border: 0px') + img(src='http://developer.netflix.com/public/Mashery/images/clients/netflix/logo.gif') #box-login a(href='/auth/box', style='border: 0px') img(src='http://sites.box.net/apps/web/simpleshare/img/logo.png') From 52824c68f4c5d9d58c9caaec8e560ffc8cc52871 Mon Sep 17 00:00:00 2001 From: slickplaid Date: Tue, 28 Jun 2011 11:18:27 -0500 Subject: [PATCH 6/6] Removed some rogue debug comments and vanity change to README.md --- README.md | 1 + lib/modules/netflix.js | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e442744d..df116913 100644 --- a/README.md +++ b/README.md @@ -1607,6 +1607,7 @@ Thanks to the following contributors for the following modules: - [slickplaid](https://github.com/slickplaid) - Justin.tv - Vimeo + - Netflix ### MIT License Copyright (c) 2011 by Brian Noguchi diff --git a/lib/modules/netflix.js b/lib/modules/netflix.js index 8ef8c6a4..f0bdb94e 100644 --- a/lib/modules/netflix.js +++ b/lib/modules/netflix.js @@ -12,7 +12,6 @@ oauthModule.submodule('netflix') .entryPath('/auth/netflix') .callbackPath('/auth/netflix/callback') -// ?oauth_token=uh5g3j69prfze4f7k9q2mm3e&oauth_verifier= .getAccessToken( function (reqToken, reqTokenSecret, verifier) { var promise = this.Promise()