diff --git a/README.md b/README.md index 4b8617b..ed6099b 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Provides out of the box authentication strategies for: * Yammer (Stephen Belanger) * Linkedin (Stephen Belanger) * Skyrock.com (Nicolas Quiénot) +* NK (Kamil Kamiński & Marek Ziółkowski) Take Care! diff --git a/examples/app.js b/examples/app.js index bf1e3c1..72d0881 100644 --- a/examples/app.js +++ b/examples/app.js @@ -96,7 +96,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.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 16d6a7f..92cfcfd 100644 --- a/examples/example_keys_file.js +++ b/examples/example_keys_file.js @@ -37,3 +37,6 @@ exports.yammerCallback= "http://localhost/auth/yammer_callback"; exports.skyrockConsumerKey= ""; exports.skyrockConsumerSecret= ""; exports.skyrockCallbackAddress= "http://local.host/auth/skyrock_callback"; +exports.nkConnectId = ""; +exports.nkConnectSecret = ""; +exports.nkConnectCallbackAddress = "http://localhost/auth/nk_callback"; diff --git a/examples/public/unauthenticated.html b/examples/public/unauthenticated.html index 9a1d468..6deda91 100644 --- a/examples/public/unauthenticated.html +++ b/examples/public/unauthenticated.html @@ -175,7 +175,11 @@

OAuth 2

- + + nkConnect + Try It! + + Janrain Try It! diff --git a/lib/auth.strategies/nk.js b/lib/auth.strategies/nk.js new file mode 100755 index 0000000..da63ace --- /dev/null +++ b/lib/auth.strategies/nk.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,EMAIL_PROFILE_ROLE"; + my.display =options.display || "page"; + + // Give the strategy a name + that.name = options.name || "nk"; + + // Build the authentication routes required + that.setupRoutes= function(app) { + app.use('/auth/nk_callback', function(req, res){ + req.authenticate([that.name], function(error, authenticated) { +//FIXME: Handle server timeouts or other exceptions + res.writeHead(303, { 'Location': req.session.nk_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._nk_fail= function(callback) { + request.getAuthDetails()['nk_login_attempt_failed'] = true; + this.fail(callback); + }; + + 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()['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._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 ){ + 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,emails&nk_token="+request.session['access_token'], {}, '', 'application/json', function(error, data, response) { + if( error ) { + self._nk_fail(callback); + }else { + self.success(JSON.parse(data).entry, callback); + } + }); + } + }); + } + } + else { + 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); + } + } + }; + return that; +};