From 08b2fd72a42767a30c49d2512e5dc834c32ce72c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Kami=C5=84ski?= Date: Thu, 8 Mar 2012 11:41:33 +0100 Subject: [PATCH 1/6] Implemented auth strategy for use with nkConnect od nk.pl --- examples/app.js | 3 +- examples/example_keys_file.js | 5 +- examples/public/unauthenticated.html | 8 ++- lib/auth.strategies/nkConnect.js | 91 ++++++++++++++++++++++++++++ 4 files changed, 103 insertions(+), 4 deletions(-) create mode 100755 lib/auth.strategies/nkConnect.js diff --git a/examples/app.js b/examples/app.js index 116ca04..d3c0d9a 100644 --- a/examples/app.js +++ b/examples/app.js @@ -95,7 +95,8 @@ app.use(connect.static(__dirname + '/public')) , auth.Getglue({appId : getGlueId, appSecret: getGlueSecret, callback: getGlueCallbackAddress}) , auth.Openid({callback: openIdCallback}) , auth.Yammer({consumerKey: yammerConsumerKey, yammerSecret: yammerConsumerSecret, callback: yammerCallback}) - , auth.Linkedin({consumerKey: linkedinConsumerKey, consumerSecret: linkedinConsumerSecret, callback: linkedinCallback})], + , auth.Linkedin({consumerKey: linkedinConsumerKey, consumerSecret: linkedinConsumerSecret, callback: linkedinCallback}) + , auth.Nkconnect({appId : nkConnectId, appSecret: nkConnectSecret, callback: nkConnectCallbackAddress})], trace: true, logoutHandler: require('../lib/events').redirectOnLogout("/")})) .use(example_auth_middleware()) diff --git a/examples/example_keys_file.js b/examples/example_keys_file.js index 64eda31..bc30ac9 100644 --- a/examples/example_keys_file.js +++ b/examples/example_keys_file.js @@ -33,4 +33,7 @@ exports.linkedinConsumerSecret= ""; exports.linkedinCallback= "http://localhost/auth/linkedin_callback"; exports.yammerConsumerKey= ""; exports.yammerConsumerSecret= ""; -exports.yammerCallback= "http://localhost/auth/yammer_callback"; \ No newline at end of file +exports.yammerCallback= "http://localhost/auth/yammer_callback"; +exports.nkConnectId = ""; +exports.nkConnectSecret = ""; +exports.nkConnectCallbackAddress = "http://localhost/auth/nkConnect_callback"; diff --git a/examples/public/unauthenticated.html b/examples/public/unauthenticated.html index c021437..2475bb4 100644 --- a/examples/public/unauthenticated.html +++ b/examples/public/unauthenticated.html @@ -167,7 +167,11 @@

OAuth 2

- + + nkConnect + Try It! + + Janrain Try It! @@ -191,4 +195,4 @@

OAuth 2

- \ No newline at end of file + diff --git a/lib/auth.strategies/nkConnect.js b/lib/auth.strategies/nkConnect.js new file mode 100755 index 0000000..3131132 --- /dev/null +++ b/lib/auth.strategies/nkConnect.js @@ -0,0 +1,91 @@ +/*! + * Copyright(c) 2010 Ciaran Jessup + * Copyright(c) 2012 Kamil Kaminski + * MIT Licensed + */ +var OAuth2= require("oauth").OAuth2, + OAuth1= require("oauth").OAuth, + url = require("url"), + http = require('http'), + + querystring = require('querystring'); + +module.exports= function(options, server) { + options= options || {}; + var that= {}; + var my= {}; + + // Construct the internal OAuth client + my._oAuth= new OAuth2(options.appId, options.appSecret, "https://nk.pl", "/oauth2/login", "/oauth2/token"); + my._oAuth.setAccessTokenName('nk_token'); + my._rest_oAuth= new OAuth1('http://opensocial.nk-net.pl/v09/rest/', 'http://opensocial.nk-net.pl/v09/token/get/', options.appId, options.appSecret, '1.0', null, 'HMAC-SHA1', null, {"Accept" : "*/*", + "Connection" : "close", + "User-Agent" : "Node authentication", + "Content-Type" : "application/json"}); + my._redirectUri= options.callback; + my.scope= options.scope || "BASIC_PROFILE_ROLE"; + my.display =options.display || "page"; + + // Give the strategy a name + that.name = options.name || "nkConnect"; + + // Build the authentication routes required + that.setupRoutes= function(app) { + app.use('/auth/nkConnect_callback', function(req, res){ + req.authenticate([that.name], function(error, authenticated) { + res.writeHead(303, { 'Location': req.session.nkConnect_redirect_url }); + res.end(''); + }); + }); + }; + + // Declare the method that actually does the authentication + that.authenticate= function(request, response, callback) { + //todo: makw the call timeout .... + var parsedUrl= url.parse(request.originalUrl, true); + var self= this; + this._nkConnect_fail= function(callback) { + request.getAuthDetails()['nkConnect_login_attempt_failed'] = true; + this.fail(callback); + }; + + if( request.getAuthDetails()['nkConnect_login_attempt_failed'] === true ) { + // Because we bounce through authentication calls across multiple requests + // we use this to keep track of the fact we *Really* have failed to authenticate + // so that we don't keep re-trying to authenticate forever. + delete request.getAuthDetails()['nkConnect_login_attempt_failed']; + self.fail( callback ); + } + else { + if( parsedUrl.query && ( parsedUrl.query.code || parsedUrl.query.error_reason === 'user_denied' ) ) { + if( parsedUrl.query.error_reason == 'user_denied' ) { + self._nkConnect_fail(callback); + } else { + my._oAuth.getOAuthAccessToken(parsedUrl.query && parsedUrl.query.code , + {redirect_uri: my._redirectUri,grant_type: 'authorization_code'}, function( error, access_token, refresh_token ){ + if( error ) callback(error); + else { + request.session["access_token"]= access_token; + if( refresh_token ) request.session["refresh_token"]= refresh_token; + + my._rest_oAuth._performSecureRequest(null, '', 'GET', "http://opensocial.nk-net.pl/v09/social/rest/people/@me?fields=id,displayName,thumbnailUrl&nk_token="+request.session['access_token'], {}, '', 'application/json', function(error, data, response) { + if( error ) { + self._nkConnect_fail(callback); + }else { + console.dir(JSON.parse(data).entry); + self.success(JSON.parse(data).entry, callback); + } + }); + } + }); + } + } + else { + request.session['nkConnect_redirect_url']= request.originalUrl; + var redirectUrl= my._oAuth.getAuthorizeUrl({redirect_uri : my._redirectUri, scope: my.scope, display:my.display, response_type: 'code'}); + self.redirect(response, redirectUrl, callback); + } + } + }; + return that; +}; From da408d18ac94a557ba34f403aa6aae5acdb2df46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Kami=C5=84ski?= Date: Thu, 8 Mar 2012 11:50:24 +0100 Subject: [PATCH 2/6] Removed console.dir from sourcecode -.- --- lib/auth.strategies/nkConnect.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/auth.strategies/nkConnect.js b/lib/auth.strategies/nkConnect.js index 3131132..64cec8a 100755 --- a/lib/auth.strategies/nkConnect.js +++ b/lib/auth.strategies/nkConnect.js @@ -72,7 +72,6 @@ module.exports= function(options, server) { if( error ) { self._nkConnect_fail(callback); }else { - console.dir(JSON.parse(data).entry); self.success(JSON.parse(data).entry, callback); } }); From 59dd207c0f24b58ff07390291ed80304c1bcc74d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Kami=C5=84ski?= Date: Thu, 8 Mar 2012 16:15:29 +0100 Subject: [PATCH 3/6] Renamed nkConnect to nk; Added email addresses to basic profile information retrieved during authentication. --- examples/app.js | 2 +- examples/example_keys_file.js | 2 +- examples/public/unauthenticated.html | 2 +- lib/auth.strategies/{nkConnect.js => nk.js} | 28 +++++++++++---------- 4 files changed, 18 insertions(+), 16 deletions(-) rename lib/auth.strategies/{nkConnect.js => nk.js} (78%) diff --git a/examples/app.js b/examples/app.js index d3c0d9a..d35a5a4 100644 --- a/examples/app.js +++ b/examples/app.js @@ -96,7 +96,7 @@ app.use(connect.static(__dirname + '/public')) , auth.Openid({callback: openIdCallback}) , auth.Yammer({consumerKey: yammerConsumerKey, yammerSecret: yammerConsumerSecret, callback: yammerCallback}) , auth.Linkedin({consumerKey: linkedinConsumerKey, consumerSecret: linkedinConsumerSecret, callback: linkedinCallback}) - , auth.Nkconnect({appId : nkConnectId, appSecret: nkConnectSecret, callback: nkConnectCallbackAddress})], + , auth.Nk({appId : nkConnectId, appSecret: nkConnectSecret, callback: nkConnectCallbackAddress})], trace: true, logoutHandler: require('../lib/events').redirectOnLogout("/")})) .use(example_auth_middleware()) diff --git a/examples/example_keys_file.js b/examples/example_keys_file.js index bc30ac9..49bbc53 100644 --- a/examples/example_keys_file.js +++ b/examples/example_keys_file.js @@ -36,4 +36,4 @@ exports.yammerConsumerSecret= ""; exports.yammerCallback= "http://localhost/auth/yammer_callback"; exports.nkConnectId = ""; exports.nkConnectSecret = ""; -exports.nkConnectCallbackAddress = "http://localhost/auth/nkConnect_callback"; +exports.nkConnectCallbackAddress = "http://localhost/auth/nk_callback"; diff --git a/examples/public/unauthenticated.html b/examples/public/unauthenticated.html index 2475bb4..7e4ea8b 100644 --- a/examples/public/unauthenticated.html +++ b/examples/public/unauthenticated.html @@ -169,7 +169,7 @@

OAuth 2

nkConnect - Try It! + Try It! Janrain diff --git a/lib/auth.strategies/nkConnect.js b/lib/auth.strategies/nk.js similarity index 78% rename from lib/auth.strategies/nkConnect.js rename to lib/auth.strategies/nk.js index 64cec8a..04444af 100755 --- a/lib/auth.strategies/nkConnect.js +++ b/lib/auth.strategies/nk.js @@ -21,19 +21,21 @@ module.exports= function(options, server) { my._rest_oAuth= new OAuth1('http://opensocial.nk-net.pl/v09/rest/', 'http://opensocial.nk-net.pl/v09/token/get/', options.appId, options.appSecret, '1.0', null, 'HMAC-SHA1', null, {"Accept" : "*/*", "Connection" : "close", "User-Agent" : "Node authentication", - "Content-Type" : "application/json"}); + "Content-Type" : "application/json"}); my._redirectUri= options.callback; - my.scope= options.scope || "BASIC_PROFILE_ROLE"; + my.scope= options.scope || "BASIC_PROFILE_ROLE,EMAIL_PROFILE_ROLE"; my.display =options.display || "page"; // Give the strategy a name - that.name = options.name || "nkConnect"; + that.name = options.name || "nk"; // Build the authentication routes required that.setupRoutes= function(app) { - app.use('/auth/nkConnect_callback', function(req, res){ + app.use('/auth/nk_callback', function(req, res){ req.authenticate([that.name], function(error, authenticated) { - res.writeHead(303, { 'Location': req.session.nkConnect_redirect_url }); + console.dir(authenticated); + console.dir(error); + res.writeHead(303, { 'Location': req.session.nk_redirect_url }); res.end(''); }); }); @@ -44,22 +46,22 @@ module.exports= function(options, server) { //todo: makw the call timeout .... var parsedUrl= url.parse(request.originalUrl, true); var self= this; - this._nkConnect_fail= function(callback) { - request.getAuthDetails()['nkConnect_login_attempt_failed'] = true; + this._nk_fail= function(callback) { + request.getAuthDetails()['nk_login_attempt_failed'] = true; this.fail(callback); }; - if( request.getAuthDetails()['nkConnect_login_attempt_failed'] === true ) { + if( request.getAuthDetails()['nk_login_attempt_failed'] === true ) { // Because we bounce through authentication calls across multiple requests // we use this to keep track of the fact we *Really* have failed to authenticate // so that we don't keep re-trying to authenticate forever. - delete request.getAuthDetails()['nkConnect_login_attempt_failed']; + delete request.getAuthDetails()['nk_login_attempt_failed']; self.fail( callback ); } else { if( parsedUrl.query && ( parsedUrl.query.code || parsedUrl.query.error_reason === 'user_denied' ) ) { if( parsedUrl.query.error_reason == 'user_denied' ) { - self._nkConnect_fail(callback); + self._nk_fail(callback); } else { my._oAuth.getOAuthAccessToken(parsedUrl.query && parsedUrl.query.code , {redirect_uri: my._redirectUri,grant_type: 'authorization_code'}, function( error, access_token, refresh_token ){ @@ -68,9 +70,9 @@ module.exports= function(options, server) { request.session["access_token"]= access_token; if( refresh_token ) request.session["refresh_token"]= refresh_token; - my._rest_oAuth._performSecureRequest(null, '', 'GET', "http://opensocial.nk-net.pl/v09/social/rest/people/@me?fields=id,displayName,thumbnailUrl&nk_token="+request.session['access_token'], {}, '', 'application/json', function(error, data, response) { + my._rest_oAuth._performSecureRequest(null, '', 'GET', "http://opensocial.nk-net.pl/v09/social/rest/people/@me?fields=id,displayName,thumbnailUrl,emails&nk_token="+request.session['access_token'], {}, '', 'application/json', function(error, data, response) { if( error ) { - self._nkConnect_fail(callback); + self._nk_fail(callback); }else { self.success(JSON.parse(data).entry, callback); } @@ -80,7 +82,7 @@ module.exports= function(options, server) { } } else { - request.session['nkConnect_redirect_url']= request.originalUrl; + request.session['nk_redirect_url']= request.originalUrl; var redirectUrl= my._oAuth.getAuthorizeUrl({redirect_uri : my._redirectUri, scope: my.scope, display:my.display, response_type: 'code'}); self.redirect(response, redirectUrl, callback); } From 66eb95cd14f0d176077a89a0f22a38ed84e3b130 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Kami=C5=84ski?= Date: Thu, 8 Mar 2012 16:17:58 +0100 Subject: [PATCH 4/6] Removed another bunch of console.dir's --- lib/auth.strategies/nk.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/auth.strategies/nk.js b/lib/auth.strategies/nk.js index 04444af..da63ace 100755 --- a/lib/auth.strategies/nk.js +++ b/lib/auth.strategies/nk.js @@ -33,8 +33,7 @@ module.exports= function(options, server) { that.setupRoutes= function(app) { app.use('/auth/nk_callback', function(req, res){ req.authenticate([that.name], function(error, authenticated) { - console.dir(authenticated); - console.dir(error); +//FIXME: Handle server timeouts or other exceptions res.writeHead(303, { 'Location': req.session.nk_redirect_url }); res.end(''); }); From 4cc8ccf9cad70dad8f3bc5b96bfe7d303a4569e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Zi=C3=B3=C5=82kowski?= Date: Thu, 8 Mar 2012 16:37:12 +0100 Subject: [PATCH 5/6] Added information about new provider - NK (nk.pl). --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8e367b5..18a1a44 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ Provides out of the box authentication strategies for: * Google (Oauth 1 & OAuth 2 clients) * Yammer (Stephen Belanger) * Linkedin (Stephen Belanger) +* NK (OAuth 1/2) Take Care! From a704cbaa55407cb3ea16db3b8518dea3bc07550e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20Kami=C5=84ski?= Date: Fri, 9 Mar 2012 08:47:32 +0100 Subject: [PATCH 6/6] Fix whitespace :) --- examples/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/app.js b/examples/app.js index d35a5a4..ba00278 100644 --- a/examples/app.js +++ b/examples/app.js @@ -96,7 +96,7 @@ app.use(connect.static(__dirname + '/public')) , auth.Openid({callback: openIdCallback}) , auth.Yammer({consumerKey: yammerConsumerKey, yammerSecret: yammerConsumerSecret, callback: yammerCallback}) , auth.Linkedin({consumerKey: linkedinConsumerKey, consumerSecret: linkedinConsumerSecret, callback: linkedinCallback}) - , auth.Nk({appId : nkConnectId, appSecret: nkConnectSecret, callback: nkConnectCallbackAddress})], + , auth.Nk({appId : nkConnectId, appSecret: nkConnectSecret, callback: nkConnectCallbackAddress})], trace: true, logoutHandler: require('../lib/events').redirectOnLogout("/")})) .use(example_auth_middleware())