Can anyone give a good comparison between: https://github.com/ciaranj/connect-auth and https://github.com/bnoguchi/everyauth
Which seem to be the only options for express/connect
I'm the author of everyauth
.
I wrote everyauth
because I found using connect-auth
lacking in terms of:
Easy and powerful configuration
To get particular, one area where it was lacking in terms of configurability was setting facebook's "scope" security settings dynamically.
Good debugging support
I found connect-auth
not-so-straightforward to debug in terms of pinpointing the part of the auth process was failing. This is mostly due to the way that connect-auth sets up its nested callbacks.
With everyauth, I tried to create a system that solved the issues I ran into with connect-auth.
On configuration - every everyauth auth module is defined as a series of steps and configurable parameters. As a result, you have surgery-like precision over what parameters (e.g., hostname, callback url, etc.) or steps (e.g., getAccessToken, addToSession) you want altered. With connect-auth
, if you want to change one thing besides the few built in configurable parameters each auth strategy provides, you have to re-write the entire this.authenticate
function that defines the logic for all of that strategy. In other words, it has less precision of configurability than everyauth
. In other cases, you cannot use connect-auth
, as is -- for example, achieving dynamic facebook "scope" configurability - i.e., asking users for more facebook permissions progressively as they get to portions of your app that require more permissions.
In addition to configurable steps and parameters, you can also take advantage of everyauth
's auth module inheritance. All modules inherit prototypically from the everymodule auth module. All OAuth2-based modules inherit from the oauth2 module. Let's say you want all oauth2 modules to behave differently. All you need to do is modify the oauth2 auth module, and all oauth2-based modules will inherit that new behavior from it.
On debugging - everyauth
, in my opinion, has better debugging visibility because of the very fact that it segments each module explicitly into the steps of which it is composed. By setting
everyauth.debug = true;
you get output of what steps in the authentication process have completed and which ones have failed. You also have granular control over how long each step in each auth strategy has before it times out.
On extensibility - I designed everyauth to maximize code re-use. As mentioned before, all modules inherit prototypically from the everymodule auth module. This means that you can achieve very modular systems while at the same time having fine grained control in terms of over-riding a specific step from an ancestor module. To see how easy it is to extend everyauth with your own auth module, just take a look at any of the specific auth modules in everyauth's source.
On readability - I find everyauth
source easier to read in terms of what is going on. With connect-auth
, I found myself jumping around the several files to understand under what contexts (i.e., during what steps, in everyauth
parlance) each nested callback configured by a strategy was running. With everyauth
, you know exactly what piece of logic is associated with which context (aka step). For instance, here is the code describing what happens when an oauth2 provider redirects back to your service:
.get('callbackPath', 'the callback path that the 3rd party OAuth provider redirects to after an OAuth authorization result - e.g., "/auth/facebook/callback"') .step('getCode') .description('retrieves a verifier code from the url query') .accepts('req res') .promises('code') .canBreakTo('authCallbackErrorSteps') .step('getAccessToken') .accepts('code') .promises('accessToken extra') .step('fetchOAuthUser') .accepts('accessToken') .promises('oauthUser') .step('getSession') .accepts('req') .promises('session') .step('findOrCreateUser') .accepts('session accessToken extra oauthUser') .promises('user') .step('compile') .accepts('accessToken extra oauthUser user') .promises('auth') .step('addToSession') .accepts('session auth') .promises(null) .step('sendResponse') .accepts('res') .promises(null)
Without needing to explain how this works, its pretty straightforward to see what an oauth2 strategy does. Want to know what getCode does? The source again is very straightforward:
.getCode( function (req, res) { var parsedUrl = url.parse(req.url, true); if (this._authCallbackDidErr(req)) { return this.breakTo('authCallbackErrorSteps', req, res); } return parsedUrl.query && parsedUrl.query.code; })
Compare this all to connect-auth
's facebook code, which for me at least, took more time than I thought it should have to figure out what is getting executed when. This is mostly because of the way in which the code is spread across files and because of the use of a single authenticate
method and nested callbacks to define authentication logic (everyauth
uses promises to break down the logic into easily digestible steps):
that.authenticate= function(request, response, callback) { //todo: makw the call timeout .... var parsedUrl= url.parse(request.url, true); var self= this; if( parsedUrl.query && parsedUrl.query.code ) { my._oAuth.getOAuthAccessToken(parsedUrl.query && parsedUrl.query.code , {redirect_uri: my._redirectUri}, 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._oAuth.getProtectedResource("https://graph.facebook.com/me", request.session["access_token"], function (error, data, response) { if( error ) { self.fail(callback); }else { self.success(JSON.parse(data), callback) } }) } }); } else { request.session['facebook_redirect_url']= request.url; var redirectUrl= my._oAuth.getAuthorizeUrl({redirect_uri : my._redirectUri, scope: my.scope }) self.redirect(response, redirectUrl, callback); } }
A few other differences:
everyauth
supports traditional password-based authentication. connect-auth
, as of this writing, does not.everyauth
's foursquare and google modules are based on their implementations of the newer OAuth2 spec.everyauth
.Finally, to comment on Nathan's answer which was unsure about everyauth
support for multiple providers at the same time, everyauth
does support multiple, concurrent providers. The README on everyauth
's github page provides instructions about how to use everyauth
to achieve this.
To conclude, I think choice of libraries depends on the developer. I, and others, find everyauth
more powerful from their point of view. As Nathan's answer illustrates, yet others find connect-auth
more tuned in to their preferences. Whatever your choice, I hope this write-up about why I wrote everyauth
helps you in your decision.
Both libraries are pretty close in feature sets, especially in terms of supported providers. connect-auth
provides support out-of-the-box to make your own oAuth providers, so that could well help you out if you’re going to need that sort of thing.
The main thing I’ve noted between the two is that I find connect-auth
much cleaner with the way it creates and accepts the middleware; you only have to look at the amount of pre-configuration required for the middleware in everyauth
to see that it's going to get messy.
Another thing that isn't clear is whether everyauth
supports multiple providers at the same time; with connect-auth
, it seems possible/more straightforward, though I’ve yet to try this myself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With