mongoose-authã§OAuthèªè¨¼
ä»åã¯everyauthã¨ããèªè¨¼ãã¸ãã¯ã®ã©ããã¼ã©ã¤ãã©ãªã§ã¯ãªãããµã¼ãã¹æ¯ã«çºãã¦å¯¾å¿ããèªè¨¼ã©ã¤ãã©ãªãæ´ã«mongooseã®ãã©ã°ã¤ã³ã¨ãã¦ä½¿ããmongoose-authã使ã£ã¦èªè¨¼ããã¾ãï¼ãããããï¼
ããããã«å人çãªã¡ã¢ã§ã
ç¨æãããã®
- node.js
- mongoose
- mongoose-auth
ãã®åã«
ãã®mongoose-authã¯å½¢å¼ã¨ãã¦ã¯everyauthãmongooseãã使ãããã®pluginã¨ããå½¢å¼ã§ãããããã§ããã°åãã£ã¦everyauthã®ç¥èã¯ããç¨åº¦æ¬²ããã¨ããã§ãã
å®éã®ã¨ãããREADMEã«ãããµã³ãã«ãåãããã°å¤§ä½ã§ãã¾ãï¼ããï¼ããã READMEã«ç¡ãé¨åã§ãããã«ããé¨åãããã®ã§ãã®ã¸ãããµã³ãã«ã§æ¸ãã¦ã¿ã¾ã
Schemaã®æ¡å¼µ
mongoose-authã使ãã¨githubãªãgithubã¢ã¸ã¥ã¼ã«ãfacebookãªãfacebookã¢ã¸ã¥ã¼ã«ã使ãã®ã§ãäºãç¨æãããUserSchemaããã¼ã¹ã«DBã«æ ¼ç´ããã¾ã
mongoose-auth:lib/modules/github/schema.js
module.exports = { github: { id: Number , login: String , gravatarId: String , name: String , email: String , publicRepoCount: Number , publicGistCount: Number , followingCount: Number , followersCount: Number , company: String , blog: String , location: String , permission: String , createdAt: Date // Private data , totalPrivateRepoCount: Number , collaborators: Number , diskUsage: Number , ownedPrivateRepoCount: Number , privateGistCount: Number , plan: { name: String , collaborators: Number , space: Number , privateRepos: Number } } , 'github.type': String };
ãã®ã¾ã¾ã§ãã¾ãæä½éå¿ è¦ãªæ å ±ã¯ç¢ºä¿ããã¦ãããã§ãããããã«è¿½å ã§å±æ§è¿½å ããããªãããªãã¦æãã¾ãããã
var mongoose = require('mongoose'), mongooseAuth = require('mongoose-auth'), Schema = mongoose.Schema, ObjectId = mongoose.Schema.ObjectId; // å ±éé ç®ã¨ãã¦displayNameã¨ããå±æ§ã追å ãã var UserSchema = new Schema({ displayName: {type:String, default: null} });
ãããã¦ããã¨åã¢ã¸ã¥ã¼ã«ã®Schemaã§è¿½å ããé ç®ãmongooseçµç±ã§æ´æ°ã§ããããã«ãªãã¾ãã
findOrCreateUserã®è¨å®
ä¾ãã°ãæ®éã«å©ç¨ããå ´åã¯ä»¥ä¸ã®ãããªã½ã¼ã¹ã§åãã¾ã
var mongoose = require('mongoose') , Schema = mongoose.Schema , mongooseAuth = require('mongoose-auth'); var UserSchema = new Schema({}) , User; // STEP 1: Schema Decoration and Configuration for the Routing UserSchema.plugin(mongooseAuth, { // Here, we attach your User model to every module everymodule: { everyauth: { User: function () { return User; } } } , github: { everyauth: { myHostname: 'http://localhost:3000' , appId: 'YOUR APP ID HERE' , appSecret: 'YOUR APP SECRET HERE' , redirectPath: '/' } } }); ...
ããã¯READMEããã®æç²ã§ãããUserSchemaã«å¯¾ããpluginã¨ãã¦githubã®è¨å®é ç®ãè¨è¿°ããã ãã§ããããã¯å®éã«ã¯everyauthã®githubã¢ã¸ã¥ã¼ã«ã«å¯¾ããè¨å®ã«ç´çµãã¦ãã ãã§ããeveryauthã§ã¯findOrCreateUseré¢æ°ãå®è£ ãã¦ãã訳ã§ã¯ããã¾ããããeveryauthã®OAuth2ã®å®è£ é¨åã§findOrCreateUserãèªè¨¼ã·ã¼ã±ã³ã¹ã®stepã¨ãã¦å¼ã³åºãã¦ãã¾ãã
everyauth:lib/modules/oauth2.js
.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') //<- ã³ã³ //.optional() .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)
ãããå©ç¨ãã¦findOrCreateUseré¢æ°ãå®ç¾©ã¨ãã¦å®è£ ãã¦ããã¨èªè¨¼å®äºæã«èªåçã«findOrCreateUserãå®è¡ã§ãã¾ããæè¬hookçãªç©ã§ããmongoose-authã§ã¯defaultã®å®ç¾©ã¨ãã¦äºãfindOrCreateUseré¢æ°ãå®ç¾©ããã¦ãã¾ãã
mongoose-auth:lib/modules/github/everyauth.js
// Defaults module.exports = { findOrCreateUser: function (sess, accessTok, accessTokExtra, ghUser) { var promise = this.Promise() , self = this; // TODO Check user in session or request helper first // e.g., req.user or sess.auth.userId this.User()().findOne({'github.id': ghUser.id}, function (err, foundUser) { if (foundUser) return promise.fulfill(foundUser); self.User()().createWithGithub(ghUser, accessTok, function (err, createdUser) { return promise.fulfill(createdUser); }); }); return promise; } };
ãããã£ã¦ãã®æåãå¤ãããå ´åã¯ããã¤ãoverrideããå®ç¾©ã追å ãã¦ããã°è¯ã訳ã§ãã
UserSchema.plugin(mongooseAuth, { everymodule: { everyauth: { User: function() { return User; }, handleLogout: function(req, res) { req.logout(); res.writeHead(303, {'Location': this.logoutRedirectPath()}); res.end(); } } }, github: { everyauth: { myHostname: conf.myHostname, appId: conf.github.oauth.appId, appSecret: conf.github.oauth.appSecret, scope: 'user,public_repo,repo,gist', redirectPath: '/', // ã³ã³ãã findOrCreateUser: function(session, accessTok, accessTokExtra, ghUser) { var promise = this.Promise(), User = this.User()(); // mongodbãã該å½ããidã®æ å ±ãæ¤ç´¢ User.findOne({'github.id': ghUser.id}, function(err, foundUser) { if(err) return promise.fail(err); if(foundUser) return promise.fulfill(foundUser); // ç¡ãå ´åã¯UserSchemaãå ã«ä½æ console.log('CREATE GITHUB USER'); User.createWithGithub(ghUser, accessTok, function(err, createUser) { if(err) return promise.fail(err); // Schemaã§å®ç¾©ãã追å å±æ§ã«å¤ãã»ãã createUser.displayName = ghUser.name; // ä¿å createUser.save(function(err, modUser) { if(err) return promise.fail(err); return promise.fulfill(modUser); }); }); }); return promise; } } } });
使ãéã¨ãã¦ã¯ãä¾ãã°èªè¨¼å¾ã®accessTokenãsessionã«å ¥ãã¦ããã¨ãï¼ãããæªããã¯å¥ã«ãã¦â¦ï¼ãå¥ã®schemaãæ´æ°ãããã¾ããããã使ãéã¯ããããããã¾ããã