Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Paypal #467

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
ee475bf
Fix to README docs - missing code section closing characters
Jun 5, 2013
6d7b6ad
Implement SurveyMonkey authorization
Jun 25, 2013
4665e64
Fixes endless callback loop by passing back res in non 200 error fail…
Jun 25, 2013
88d05a0
Add ability in survey monkey to get details about the user now that t…
Aug 9, 2013
44b3ca8
Add first implmentation of desk.com module
Aug 13, 2013
426a8e1
Change oauthHost and apiHost to be customizable.
Aug 18, 2013
2d102a9
Change oAuth initialization to allow for dynamic oauthHost names to b…
Aug 28, 2013
14a88a5
Modify desk module to use new dynamic host names
Aug 28, 2013
c242903
Add Microsoft Live oAuth module
Oct 15, 2013
3155bb9
Desk.com changed their user information route from /accounts to /user…
Nov 15, 2013
5c6e1db
Add ability for accessToken requests to put data in the query string …
Nov 25, 2013
edab96a
Adjust survey monkey everyauth module to allow for new oAuth params. …
Nov 25, 2013
1b45e6d
Small hopeful fix for what seems to be a reserved variable url
Dec 10, 2013
c75622b
Don't follow redirectPath if headers sent.
ibash Dec 30, 2013
0d40e5b
Adding mandrill authentication
ibash Jan 6, 2014
76cfc46
adding additonal parameters to err.extra and fixing issue with addito…
ibash Jan 22, 2014
dd89a37
Add issue that moreAccessTokenQueryParams was not getting cloned corr…
Jan 31, 2014
7f1b5c1
Bumping version of connect because of vulnerability
ibash Apr 9, 2014
4173fc6
start zendesk strategy
Apr 22, 2014
e08a93f
Merge pull request #1 from Datahero/zendesk
Apr 22, 2014
50d8a7f
add setDomain to oauth2
Apr 23, 2014
cb59d46
migrate zendesk to oauth2
Apr 23, 2014
a5c3469
implement fetchOAuthUser
Apr 24, 2014
02bd42a
Merge pull request #2 from Datahero/zendesk
Apr 24, 2014
da44b76
adding paypal module
dougfarre May 27, 2014
35fb39f
unverified first attempt at everyauth paypal module; comments exist d…
dougfarre May 28, 2014
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2425,6 +2425,7 @@ object whose parameter name keys map to description values:

```javascript
everyauth.stripe.configurable();
```

### Salesforce

Expand Down Expand Up @@ -2488,6 +2489,7 @@ object whose parameter name keys map to description values:

```javascript
everyauth.salesforce.configurable();
```

## Configuring a Module

Expand Down
65 changes: 65 additions & 0 deletions lib/modules/desk.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
var oauthModule = require('./oauth'),
url = require('url');

var desk = module.exports =
oauthModule.submodule('desk')
.configurable({
domain: "URL identifying domain for the api"
})
.apiHost('https://something.desk.com/api/v2')
.oauthHost('https://somthing.desk.com')
.requestTokenPath('/oauth/request_token')
.accessTokenPath('/oauth/access_token')
.authorizePath('/oauth/authorize')
.entryPath('/auth/desk')
.callbackPath('/auth/desk/callback')

.authCallbackDidErr( function (req) {
var parsedUrl = url.parse(req.url, true);
return parsedUrl.query && !!parsedUrl.query.not_approved;
})

.handleAuthCallbackError( function (req, res, next) {
var parsedUrl = url.parse(req.url, true),
errorDesc = parsedUrl.query.error + "; " + parsedUrl.query.error_description;
if (res.render) {
res.render(__dirname + '/../views/auth-fail.jade', {
errorDescription: errorDesc
});
} else {
// TODO Replace this with a nice fallback
throw new Error("You must configure handleAuthCallbackError if you are not using express");
}
})

.fetchOAuthUser( function (accessToken, accessTokenSecret, params) {
var p = this.Promise();
this.oauth.get(this.apiHost().call(this) + '/users/current', accessToken, accessTokenSecret, function (err, data) {
if (err) return p.fail(err);
var oauthUser = JSON.parse(data);
oauthUser.id = oauthUser.uid;
p.fulfill(oauthUser);
});
return p;
})

.moduleErrback( function (err, seqValues) {
if (err instanceof Error) {
var next = seqValues.next;
return next(err);
} else if (err.extra) {
var deskResponse = err.extra.res,
serverResponse = seqValues.res;
serverResponse.writeHead(
deskResponse.statusCode,
deskResponse.headers);
serverResponse.end(err.extra.data);
} else if (err.statusCode) {
var serverResponse = seqValues.res;
serverResponse.writeHead(err.statusCode);
serverResponse.end(err.data);
} else {
console.error(err);
throw new Error('Unsupported error type');
}
});
134 changes: 134 additions & 0 deletions lib/modules/mandrill.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
var everyModule = require('./everymodule'),
url = require('url'),
querystring = require('querystring'),
request = require('request'),
extractHostname = require('../utils').extractHostname;


var mandrill = module.exports =
everyModule.submodule('mandrill')
.configurable({
apiHost: 'e.g. https://mandrillapp.com/api/1.0/',
apiAuthUrl: 'e.g. https://mandrillapp.com/api-auth/',
authenticationId: 'The app authentication id generated from mandrill',
authCallbackDidErr: 'Define the condition for the auth module determining if the auth callback url denotes a failure. Returns true/false.',
myHostname: 'e.g., http://local.host:3000 . Notice no trailing slash',
redirectPath: 'the path to redirect once the user is authenticated'
})

// Declares a GET route that is aliased
// as 'entryPath'. The handler for this route
// triggers the series of steps that you see
// indented below it.
.get('entryPath',
'the link a user follows, whereupon you redirect them to authentication url- e.g., "/auth/mandrill"')
.step('redirectToMandrill')
.accepts('req res next')
.promises(null)

// post to callbackPath is aliased below. Mandrill redirects to callbackPath using both methods.
.get('callbackPath',
'the callback path to redirect to after an authorization - e.g., "/auth/mandrill/callback"')
.step('getApiKey')
.description('retrieves a verifier code from the url query')
.accepts('req res next')
.promises('apiKey')
.canBreakTo('authCallbackErrorSteps')
.step('getSession')
.accepts('req')
.promises('session')
.step('fetchUser')
.accepts('apiKey')
.promises('mandrillUser')
.step('findOrCreateUser')
.accepts('session apiKey mandrillUser')
.promises('user')
.step('sendResponse')
.accepts('res')
.promises(null)

.stepseq('authCallbackErrorSteps')
.step('handleAuthCallbackError',
'a request handler that intercepts a failed authorization message sent from mandrill')
.accepts('req res next')
.promises(null)

.apiAuthUrl('http://mandrillapp.com/api-auth/')
.apiHost('https://mandrillapp.com/api/1.0/')
.entryPath('/auth/mandrill')
.callbackPath('/auth/mandrill/callback')

.redirectToMandrill(function(req, res) {
if (!this._myHostname) {
this.myHostname(extractHostname(req));
}

var authUrl,
params;

params = {
id: this.authenticationId(),
redirect_url: this.myHostname() + this.callbackPath()
}
authUrl = this.apiAuthUrl() + '?' + querystring.stringify(params);

this.redirect(res, authUrl);
})

.getApiKey(function (req, res, next) {
var data,
apiKey;

if (this._authCallbackDidErr(req)) {
return this.breakTo('authCallbackErrorSteps', req, res, next);
}

// Note: This assumes that you're using connect.bodyParser
// TODO(ibash) handle both cases where bodyParser is / is not used
apiKey = req.body.key;
return apiKey;
})

.getSession(function(req) {
return req.session;
})

.fetchUser(function(apiKey) {
var promise = this.Promise(),
userUrl = this.apiHost() + '/users/info.json';

request.post({url: userUrl, json:{key: apiKey}}, function(error, res, body) {
if (error) {
error.extra = {res: res, data: body};
return promise.fail(error);
}

if (body && body.status && body.status === 'error') {
// error from mandrill
var errorMsg = body.name + ': ' + body.message;
return promise.fail(new Error(errorMsg));
}

// body is an object representing the user
promise.fulfill(body);
});

return promise;
})

.sendResponse( function (res) {
var redirectTo = this.redirectPath();
if (!redirectTo)
throw new Error('You must configure a redirectPath');
this.redirect(res, redirectTo);
})

.authCallbackDidErr(function(req) {
return req.query && !!req.query.error;
})
.handleAuthCallbackError(function(req, res, next) {
next(new Error("Authorization Error"));
});

// alias post callbackPath to get callbackPath
mandrill._stepSequences['post:callbackPath'] = mandrill._stepSequences['get:callbackPath'];
141 changes: 141 additions & 0 deletions lib/modules/microsoft.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
var oauthModule = require('./oauth2')
, url = require('url')
, request = require('request');

var microsoft = module.exports =
oauthModule.submodule('microsoft')
.configurable({
scope: "URL identifying the Microsoft service to be accessed. See the documentation for the API you'd like to use for what scope to specify. To specify more than one scope, list each one separated with a space.",
display: "The display type used for the authentication page. Valid values are: 'popup', 'touch', 'page', 'none'",
locale: "Optional - A market string that determines how the consent UI is localized. Defaults to autodetect"
})

.oauthHost('https://login.live.com')
.apiHost('https://apis.live.net')

.authPath('/oauth20_authorize.srf')
.authQueryParam('response_type', 'code')

.accessTokenPath('/oauth20_token.srf')
.accessTokenParam('grant_type', 'authorization_code')
.accessTokenHttpMethod('post')
.postAccessTokenParamsVia('data')

.entryPath('/auth/microsoft')
.callbackPath('/auth/microsoft/callback')

.authQueryParam({
display: function() {
return this._display && this.display();
},
locale: function () {
return this._locale && this.locale();
},
scope: function () {
return this._scope && this.scope();
}
})

.addToSession( function (sess, auth) {
this._super(sess, auth);
if (auth.refresh_token) {
sess.auth[this.name].refreshToken = auth.refresh_token;
sess.auth[this.name].expiresInSeconds = parseInt(auth.expires_in, 10);
}
})

.authCallbackDidErr( function (req) {
var parsedUrl = url.parse(req.url, true);
return parsedUrl.query && !!parsedUrl.query.error;
})

.handleAuthCallbackError( function (req, res) {
var parsedUrl = url.parse(req.url, true)
, errorDesc = parsedUrl.query.error + "; " + parsedUrl.query.error_description;
if (res.render) {
res.render(__dirname + '/../views/auth-fail.jade', {
errorDescription: errorDesc
});
} else {
// TODO Replace this with a nice fallback
throw new Error("You must configure handleAuthCallbackError if you are not using express");
}
})
.moduleErrback( function (err, seqValues) {
if (err instanceof Error) {
var next = seqValues.next;
return next(err);
} else if (err.extra) {
var microsoftResponse = err.extra.res
, serverResponse = seqValues.res;
serverResponse.writeHead(
microsoftResponse.statusCode
, microsoftResponse.headers);
serverResponse.end(err.extra.data);
} else if (err.statusCode) {
var serverResponse = seqValues.res;
serverResponse.writeHead(err.statusCode);
serverResponse.end(err.data);
} else {
console.error(err);
throw new Error('Unsupported error type');
}
})

.fetchOAuthUser( function (accessToken, authResponse) {
var p = this.Promise();

request.get({
url: this.apiHost() + '/v5.0/me',
qs: {access_token: accessToken}
}, function(err, res, body) {
if(err){
return p.fail(err);
} else {
if(parseInt(res.statusCode/100,10) !== 2) {
return p.fail({extra:{data:body, res: res}});
}
var oAuthUser = JSON.parse(body);
p.fulfill(oAuthUser);
}
});
return p;
});

/**
* @param {Object} params in an object that includes the keys:
* - refreshToken: The refresh token returned from the authorization code
* exchange
* - clientId: The client_id obtained during application registration
* - clientSecret: The client secret obtained during the application registration
* @param {Function} cb
*/
microsoft.refreshToken = function (params, cb) {
request.post('https://login.live.com/oauth20_token.srf', {
form: {
refresh_token: params.refreshToken
, client_id: params.clientId
, client_secret: params.clientSecret
, grant_type: 'refresh_token'
}
}, function (err, res, body) {
// `body` should look like:
// {
// "access_token":"1/fFBGRNJru1FQd44AzqT3Zg",
// "expires_in":3920,
// "token_type":"Bearer",
// }
if (err) return cb(err);
if (parseInt(res.statusCode / 100, 10) !== 2) {
cb(null, {}, res);
} else {
body = JSON.parse(body);
cb(null, {
accessToken: body.access_token
, expiresIn: body.expires_in
, idToken: body.id_token
}, res);
}
});
return this;
};
Loading