diff --git a/.gitignore b/.gitignore index 8a7afec5..1a565d03 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ issues IRC.md playground.js CHANGES +npm-debug.log +.idea \ No newline at end of file diff --git a/README.md b/README.md index e9aeb688..c65c3a19 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,8 @@ So far, `everyauth` enables you to login via: Eduard Baun Smarterer kaizenpack + RunKeeper + Alexis Kinsella Box.net @@ -2116,6 +2118,35 @@ connect( ).listen(3000); ``` +### RunKeeper OAuth (2.0) + +You will first need to [register your application](http://runkeeper.com/partner/applications) to get the appId and appSecret. + +```javascript +everyauth.runkeeper + .appId('YOUR CONSUMER KEY HERE') + .consumerSecret('YOUR CONSUMER SECRET HERE') + .findOrCreateUser( function (sess, accessToken, accessSecret, user) { + // find or create user logic goes here + // + // e.g., + // return usersByRunKeeperId[user.userID] || (usersByRunKeeperId[user.userID] = 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); +``` + ### OpenID protocol OpenID protocol allows you to use an openid auth request. You can read more information about it here http://openid.net/ diff --git a/example/conf.js b/example/conf.js index d02be174..a2c503e7 100644 --- a/example/conf.js +++ b/example/conf.js @@ -119,9 +119,13 @@ module.exports = { , mendeley: { consumerKey: 'Enter your consumer key here' , consumerSecret: 'Enter your consumer secret here' - } - , weibo: { - appId: '3350967939' - , appSecret: 'ef7f0a836d0ef315dca53e8d73816cc0' - } + } + , weibo: { + appId: '3350967939' + , appSecret: 'ef7f0a836d0ef315dca53e8d73816cc0' + } + , runkeeper: { + appId: 'Enter your client/app id here' + , appSecret: 'Enter your client/app secret here' + } }; diff --git a/example/server.js b/example/server.js index 46894037..baf64d10 100644 --- a/example/server.js +++ b/example/server.js @@ -53,6 +53,7 @@ var usersMailruId = {}; var usersByMendeleyId = {}; var usersByDcId = {}; var usersByWeiboId = {}; +var usersByRunKeeperId = {}; var usersByLogin = { 'brian@example.com': addUser({ login: 'brian@example.com', password: 'password'}) }; @@ -389,6 +390,14 @@ everyauth.mendeley }) .redirectPath('/'); +everyauth.runkeeper + .appId(conf.runkeeper.appId) + .appSecret(conf.runkeeper.appSecret) + .findOrCreateUser(function(sess, accessToken, accessSecret, user) { + return usersByRunKeeperId[user.userID] || (usersByRunKeeperId[user.userID] = addUser('runkeeper', user)); + }) + .redirectPath('/'); + everyauth .soundcloud .appId(conf.soundcloud.appId) diff --git a/example/views/home.jade b/example/views/home.jade index ea7f04f8..09e51cc3 100644 --- a/example/views/home.jade +++ b/example/views/home.jade @@ -86,6 +86,9 @@ #mendeley-login a(href='/auth/mendeley', style='border: 0px') img(src='http://d1rktifm8krpj.cloudfront.net/graphics/commonnew/logo-mendeley_1248201417297118.png', title='Login with Mendeley') + #runkeeper-login + a(href='/auth/runkeeper', style='border: 0px') + img(src='http://d2b4ufapzmnxpw.cloudfront.net/build/3572/static/kronos/images/logo.png', title='Login with Runkeeper') #openid-login form#openid(action='/auth/openid') label(for='openid_identifier') OpenID Identifier:   @@ -185,5 +188,8 @@ p= JSON.stringify(everyauth.dailycred.user.email) - if (everyauth['weibo']) p= JSON.stringify(everyauth.weibo.user) + - if (everyauth.runkeeper) + h3 Runkeeper User Data + p= JSON.stringify(everyauth.runkeeper.user) h3 a(href='/logout') Logout diff --git a/lib/modules/runkeeper.js b/lib/modules/runkeeper.js new file mode 100644 index 00000000..895712a1 --- /dev/null +++ b/lib/modules/runkeeper.js @@ -0,0 +1,39 @@ +var oauthModule = require('./oauth2') + , request = require('request'); + +var runkeeper = module.exports = +oauthModule.submodule('runkeeper') + .configurable({ + scope: 'specify types of access: (no scope), non-expiring' + }) + .apiHost('https://api.runkeeper.com') + .oauthHost('https://runkeeper.com') + .authPath('/apps/authorize') + .accessTokenPath('/apps/token') + .entryPath('/auth/runkeeper') + .callbackPath('/auth/runkeeper/callback') + .authQueryParam('response_type', 'code') + .authQueryParam('scope', function () { + return this._scope && this.scope(); + }) + .accessTokenHttpMethod('post') + .postAccessTokenParamsVia('data') + .accessTokenParam('grant_type', 'authorization_code') + .fetchOAuthUser(function (accessToken) { + console.log("Access Token: ", accessToken); + var promise = this.Promise(); + request.get({ + url: this.apiHost() + '/user' + , headers: { + 'Authorization': 'Bearer ' + accessToken + } + }, function (err, res, body) { + if (err) return promise.fail(err); + if (parseInt(res.statusCode / 100, 10) !== 2) { + return promise.fail(body); + } + return promise.fulfill(JSON.parse(body)); + }); + + return promise; + }); diff --git a/media/runkeeper.ico b/media/runkeeper.ico new file mode 100644 index 00000000..f5f98391 Binary files /dev/null and b/media/runkeeper.ico differ