Browse files

initial commit

  • Loading branch information...
0 parents commit 9e5af26ccd759fb20eb3d7ed9cf909eb26ced601 @jeremybenaim committed Aug 21, 2012
2 .gitignore
@@ -0,0 +1,2 @@
+.DS_Store
+node_modules
4 .npmignore
@@ -0,0 +1,4 @@
+*.md
+.DS_Store
+.git*
+examples/
20 LICENSE
@@ -0,0 +1,20 @@
+(The MIT License)
+
+Copyright (c) 2012 Jared Hanson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
91 README.md
@@ -0,0 +1,91 @@
+# Passport-500px
+
+[Passport](http://passportjs.org/) strategy for authenticating with [500px](http://www.500px.com/)
+using the OAuth 1.0a API.
+
+This module lets you authenticate using 500px in your Node.js applications.
+By plugging into Passport, 500px authentication can be easily and
+unobtrusively integrated into any application or framework that supports
+[Connect](http://www.senchalabs.org/connect/)-style middleware, including
+[Express](http://expressjs.com/).
+
+## Installation
+
+ $ npm install passport-500px
+
+## Usage
+
+#### Configure Strategy
+
+The 500px authentication strategy authenticates users using a 500px account
+and OAuth tokens. The strategy requires a `verify` callback, which accepts
+these credentials and calls `done` providing a user, as well as `options`
+specifying a consumer key, consumer secret, and callback URL.
+
+ passport.use(new _500pxStrategy({
+ consumerKey: _500px_OAUTH_KEY,
+ consumerSecret: _500px_OAUTH_SECRET,
+ callbackURL: "http://127.0.0.1:3000/auth/500px/callback"
+ },
+ function(token, tokenSecret, profile, done) {
+ User.findOrCreate({ '500pxId': profile.id }, function (err, user) {
+ return done(err, user);
+ });
+ }
+ ));
+
+#### Authenticate Requests
+
+Use `passport.authenticate()`, specifying the `'500px'` strategy, to
+authenticate requests.
+
+For example, as route middleware in an [Express](http://expressjs.com/)
+application:
+
+ app.get('/auth/500px',
+ passport.authenticate('500px'),
+ function(req, res){
+ // The request will be redirected to 500px for authentication, so this
+ // function will not be called.
+ });
+
+ app.get('/auth/500px/callback',
+ passport.authenticate('500px', { failureRedirect: '/login' }),
+ function(req, res) {
+ // Successful authentication, redirect home.
+ res.redirect('/');
+ });
+
+## Examples
+
+For a complete, working example, refer to the [login example](https://github.com/jeremybenaim/passport-500px/tree/master/examples/login).
+
+[![Build Status](https://secure.travis-ci.org/jaredhanson/passport-500px.png)](http://travis-ci.org/jeremybenaim/passport-500px)
+
+## Credits
+
+ - [Jeremy Benaim](http://github.com/jeremybenaim)
+ - based on [Jared Hanson](http://github.com/jaredhanson) previous work
+
+## License
+
+(The MIT License)
+
+Copyright (c) 2012 Jared Hanson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
121 examples/login/app.js
@@ -0,0 +1,121 @@
+var express = require('express')
+ , passport = require('passport')
+ , util = require('util')
+ , _500pxStrategy = require('passport-500px').Strategy;
+
+var _5OOpx_APP_ID = "--insert-500px-key-here--"
+ , _5OOpx_APP_SECRET = "--insert-500px-key-here--";
+
+// Passport session setup.
+// To support persistent login sessions, Passport needs to be able to
+// serialize users into and deserialize users out of the session. Typically,
+// this will be as simple as storing the user ID when serializing, and finding
+// the user by ID when deserializing. However, since this example does not
+// have a database of user records, the complete 500px profile is
+// serialized and deserialized.
+passport.serializeUser(function(user, done) {
+ done(null, user);
+});
+
+passport.deserializeUser(function(obj, done) {
+ done(null, obj);
+});
+
+
+// Use the _500pxStrategy within Passport.
+// Strategies in passport require a `verify` function, which accept
+// credentials (in this case, a token, tokenSecret, and 500px profile), and
+// invoke a callback with a user object.
+passport.use(new _500pxStrategy({
+ consumerKey: _5OOpx_APP_ID,
+ consumerSecret: _5OOpx_APP_SECRET,
+ callbackURL: "http://127.0.0.1:3000/auth/500px/callback"
+ },
+ function(token, tokenSecret, profile, done) {
+ // asynchronous verification, for effect...
+ process.nextTick(function () {
+
+ // To keep the example simple, the user's 500px profile is returned to
+ // represent the logged-in user. In a typical application, you would want
+ // to associate the 500px account with a user record in your database,
+ // and return that user instead.
+ return done(null, profile);
+ });
+ }
+));
+
+
+
+
+var app = express.createServer();
+
+// configure Express
+app.configure(function() {
+ app.set('views', __dirname + '/views');
+ app.set('view engine', 'ejs');
+ app.use(express.logger());
+ app.use(express.cookieParser());
+ app.use(express.bodyParser());
+ app.use(express.methodOverride());
+ app.use(express.session({ secret: 'keyboard cat' }));
+ // Initialize Passport! Also use passport.session() middleware, to support
+ // persistent login sessions (recommended).
+ app.use(passport.initialize());
+ app.use(passport.session());
+ app.use(app.router);
+ app.use(express.static(__dirname + '/public'));
+});
+
+
+app.get('/', function(req, res){
+ res.render('index', { user: req.user });
+});
+
+app.get('/account', ensureAuthenticated, function(req, res){
+ res.render('account', { user: req.user });
+});
+
+app.get('/login', function(req, res){
+ res.render('login', { user: req.user });
+});
+
+// GET /auth/500px
+// Use passport.authenticate() as route middleware to authenticate the
+// request. The first step in 500px authentication will involve redirecting
+// the user to 500px.com. After authorization, 500px will redirect the user
+// back to this application at /auth/500px/callback
+app.get('/auth/500px',
+ passport.authenticate('500px'),
+ function(req, res){
+ // The request will be redirected to 500px for authentication, so this
+ // function will not be called.
+ });
+
+// GET /auth/500px/callback
+// Use passport.authenticate() as route middleware to authenticate the
+// request. If authentication fails, the user will be redirected back to the
+// login page. Otherwise, the primary route function function will be called,
+// which, in this example, will redirect the user to the home page.
+app.get('/auth/500px/callback',
+ passport.authenticate('500px', { failureRedirect: '/login' }),
+ function(req, res) {
+ res.redirect('/');
+ });
+
+app.get('/logout', function(req, res){
+ req.logout();
+ res.redirect('/');
+});
+
+app.listen(3000);
+
+
+// Simple route middleware to ensure user is authenticated.
+// Use this route middleware on any resource that needs to be protected. If
+// the request is authenticated (typically via a persistent login session),
+// the request will proceed. Otherwise, the user will be redirected to the
+// login page.
+function ensureAuthenticated(req, res, next) {
+ if (req.isAuthenticated()) { return next(); }
+ res.redirect('/login')
+}
10 examples/login/package.json
@@ -0,0 +1,10 @@
+{
+ "name": "passport-500px-examples-login",
+ "version": "0.0.0",
+ "dependencies": {
+ "express": ">= 0.0.0",
+ "ejs": ">= 0.0.0",
+ "passport": ">= 0.0.0",
+ "passport-500px": ">= 0.0.0"
+ }
+}
2 examples/login/views/account.ejs
@@ -0,0 +1,2 @@
+<p>ID: <%= user.id %></p>
+<p>Name: <%= user.displayName %></p>
5 examples/login/views/index.ejs
@@ -0,0 +1,5 @@
+<% if (!user) { %>
+ <h2>Welcome! Please log in.</h2>
+<% } else { %>
+ <h2>Hello, <%= user.displayName %>.</h2>
+<% } %>
21 examples/login/views/layout.ejs
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Passport-500px Example</title>
+ </head>
+ <body>
+ <% if (!user) { %>
+ <p>
+ <a href="/">Home</a> |
+ <a href="/login">Log In</a>
+ </p>
+ <% } else { %>
+ <p>
+ <a href="/">Home</a> |
+ <a href="/account">Account</a> |
+ <a href="/logout">Log Out</a>
+ </p>
+ <% } %>
+ <%- body %>
+ </body>
+</html>
1 examples/login/views/login.ejs
@@ -0,0 +1 @@
+<a href="/auth/500px">Login with 500px</a>
15 lib/passport-500px/index.js
@@ -0,0 +1,15 @@
+/**
+ * Module dependencies.
+ */
+var Strategy = require('./strategy');
+
+
+/**
+ * Framework version.
+ */
+require('pkginfo')(module, 'version');
+
+/**
+ * Expose constructors.
+ */
+exports.Strategy = Strategy;
107 lib/passport-500px/strategy.js
@@ -0,0 +1,107 @@
+/**
+ * Module dependencies.
+ */
+var util = require('util')
+ , OAuthStrategy = require('passport-oauth').OAuthStrategy
+ , InternalOAuthError = require('passport-oauth').InternalOAuthError;
+
+
+/**
+ * `Strategy` constructor.
+ *
+ * The 500px authentication strategy authenticates requests by delegating to
+ * 500px using the OAuth protocol.
+ *
+ * Applications must supply a `verify` callback which accepts a `token`,
+ * `tokenSecret` and service-specific `profile`, and then calls the `done`
+ * callback supplying a `user`, which should be set to `false` if the
+ * credentials are not valid. If an exception occured, `err` should be set.
+ *
+ * Options:
+ * - `consumerKey` identifies client to 500px
+ * - `consumerSecret` secret used to establish ownership of the consumer key
+ * - `callbackURL` URL to which 500px will redirect the user after obtaining authorization
+ *
+ * Examples:
+ *
+ * passport.use(new _500pxStrategy({
+ * consumerKey: '123-456-789',
+ * consumerSecret: 'shhh-its-a-secret'
+ * callbackURL: 'https://www.example.net/auth/500px/callback'
+ * },
+ * function(token, tokenSecret, profile, done) {
+ * User.findOrCreate(..., function (err, user) {
+ * done(err, user);
+ * });
+ * }
+ * ));
+ *
+ * @param {Object} options
+ * @param {Function} verify
+ * @api public
+ */
+function Strategy(options, verify) {
+ options = options || {};
+ options.requestTokenURL = options.requestTokenURL || 'https://api.500px.com/v1/oauth/request_token';
+ options.accessTokenURL = options.accessTokenURL || 'https://api.500px.com/v1/oauth/access_token';
+ options.userAuthorizationURL = options.userAuthorizationURL || 'https://api.500px.com/v1/oauth/authorize';
+ options.sessionKey = options.sessionKey || 'oauth:500px';
+
+ OAuthStrategy.call(this, options, verify);
+ this.name = '500px';
+}
+
+/**
+ * Inherit from `OAuthStrategy`.
+ */
+util.inherits(Strategy, OAuthStrategy);
+
+/**
+ * Retrieve user profile from 500px.
+ *
+ * This function constructs a normalized profile, with the following properties:
+ *
+ * - `provider` always set to `facebook`
+ * - `id` the user's 500px ID
+ * - `username` the user's 500px username
+ * - `displayName` the user's full name
+ * - `name.familyName` the user's last name
+ * - `name.givenName` the user's first name
+ * - `profileUrl` the URL of the profile for the user on 500px
+ * - `emails` the proxied or contact email address granted by the user
+ *
+ * @param {String} accessToken
+ * @param {Function} done
+ * @api protected
+ */
+Strategy.prototype.userProfile = function(token, tokenSecret, params, done) {
+ this._oauth.get('https://api.500px.com/v1/users', token, tokenSecret, function (err, body, res) {
+ if (err) { return done(new InternalOAuthError('failed to fetch user profile', err)); }
+
+ try {
+ var json = JSON.parse(body);
+
+ var profile = { provider: '500px' };
+ profile.id = json.user.id;
+ profile.username = json.user.username;
+ profile.displayName = json.user.fullname;
+ profile.name = { familyName: json.user.lastname,
+ givenName: json.user.firstname };
+ profile.profileUrl = 'http://500px.com/'+json.user.username;
+ profile.emails = [{ value: json.user.email }];
+
+ profile._raw = body;
+ profile._json = json;
+
+ done(null, profile);
+ } catch(e) {
+ done(e);
+ }
+ });
+}
+
+
+/**
+ * Expose `Strategy`.
+ */
+module.exports = Strategy;
24 package.json
@@ -0,0 +1,24 @@
+{
+ "name": "passport-500px",
+ "version": "0.1.1",
+ "description": "500px authentication strategy for Passport.",
+ "author": { "name": "Jeremy Benail", "email": "jeremybenaim@gmail.com", "url": "http://jeremybenaim.com/" },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/jeremybenaim/passport-500px.git"
+ },
+ "bugs": {
+ "url": "http://github.com/jeremybenaim/passport-500px/issues"
+ },
+ "main": "./lib/passport-500px",
+ "dependencies": {
+ "pkginfo": "0.2.x",
+ "passport-oauth": "0.1.x"
+ },
+ "engines": { "node": ">= 0.4.0" },
+ "licenses": [ {
+ "type": "MIT",
+ "url": "http://www.opensource.org/licenses/MIT"
+ } ],
+ "keywords": ["passport", "500px", "auth", "authn", "authentication", "identity"]
+}

0 comments on commit 9e5af26

Please sign in to comment.