diff --git a/README.md b/README.md index 5e416c4c..83b36546 100644 --- a/README.md +++ b/README.md @@ -115,10 +115,10 @@ You can add the following to your `package.json` file to start the project: You will need to create following pages under `./pages/auth` in your project: -* index.js // Sign In +* index.js // Sign In (and Link/Unlink) * error.js // Error handling * check-email.js // Check email prompt -* callback.js // Callback page for Single Page Apps +* callback.js // Callback page, used to update state in Single Page Apps You can [find examples of these](https://github.com/iaincollins/next-auth/tree/master/example) included which you can copy and paste into your project. @@ -162,8 +162,8 @@ It is where the **next-auth.functions.js** and **next-auth.providers.js** files Methods for user management and sending email are defined in **next-auth.functions.js** * find({id,email,emailToken,provider}) -* insert(user) -* update(user) +* insert(user, oAuthProfile) +* update(user, oAuthProfile) * remove(id) * serialize(user) * deserialize(id) diff --git a/example/next-auth.functions.js b/example/next-auth.functions.js index 47761617..c8e0ef46 100644 --- a/example/next-auth.functions.js +++ b/example/next-auth.functions.js @@ -102,7 +102,7 @@ module.exports = () => { } else if (emailToken) { query = { emailToken: emailToken } } else if (provider) { - query = { [`${provider.name}.id`]: provider.id } + query = { [`${provider.name}.id`]: provider.id } } return new Promise((resolve, reject) => { @@ -112,7 +112,14 @@ module.exports = () => { }) }) }, - insert: (user) => { + // The user parameter contains a basic user object to be added to the DB. + // The oAuthProfile parameter is passed when signing in via oAuth. + // + // The optional oAuthProfile parameter contains all properties associated + // with the users account on the oAuth service they are signing in with. + // + // You can use this to capture profile.avatar, profile.location, etc. + insert: (user, oAuthProfile) => { return new Promise((resolve, reject) => { usersCollection.insert(user, (err, response) => { if (err) return reject(err) @@ -125,7 +132,14 @@ module.exports = () => { }) }) }, - update: (user) => { + // The user parameter contains a basic user object to be added to the DB. + // The oAuthProfile parameter is passed when signing in via oAuth. + // + // The optional oAuthProfile parameter contains all properties associated + // with the users account on the oAuth service they are signing in with. + // + // You can use this to capture profile.avatar, profile.location, etc. + update: (user, profile) => { return new Promise((resolve, reject) => { usersCollection.update({_id: MongoObjectId(user._id)}, user, {}, (err) => { if (err) return reject(err) @@ -133,6 +147,10 @@ module.exports = () => { }) }) }, + // The remove parameter is passed the ID of a user account to delete. + // + // This method is not used in the current version of next-auth but will + // be in a future release, to provide an endpoint for account deletion. remove: (id) => { return new Promise((resolve, reject) => { usersCollection.remove({_id: MongoObjectId(id)}, (err) => { @@ -145,15 +163,18 @@ module.exports = () => { serialize: (user) => { // Supports serialization from Mongo Object *and* deserialize() object if (user.id) { - return Promise.resolve(user.id) + // Handle responses from deserialize() + return Promise.resolve(user.id) } else if (user._id) { + // Handle responses from find(), insert(), update() return Promise.resolve(user._id) } else { return Promise.reject(new Error("Unable to serialise user")) } }, // Deseralize turns a User ID into a normalized User object that is - // exported to clients. It should not return private/sensitive fields. + // exported to clients. It should not return private/sensitive fields, + // only fields you want to expose via the user interface. deserialize: (id) => { return new Promise((resolve, reject) => { usersCollection.findOne({ _id: MongoObjectId(id) }, (err, user) => { diff --git a/example/package.json b/example/package.json index d23a9260..d48b0976 100644 --- a/example/package.json +++ b/example/package.json @@ -17,7 +17,7 @@ "mongodb": "^3.0.1", "nedb": "^1.8.0", "next": "^4.2.3", - "next-auth": "^1.1.1", + "next-auth": "^1.3.0", "next-auth-client": "^1.1.1", "nodemailer": "^4.4.2", "nodemailer-direct-transport": "^3.3.2", diff --git a/index.js b/index.js index c05e04a7..230c04f7 100644 --- a/index.js +++ b/index.js @@ -56,8 +56,8 @@ module.exports = (nextApp, { emailToken, provider // provider = { name: 'twitter', id: '123456' } } = {}) => { Promise.resolve(user) }, - update: (user) => { Promise.resolve(user) }, - insert: (user) => { Promise.resolve(user) }, + update: (user, profile) => { Promise.resolve(user) }, + insert: (user, profile) => { Promise.resolve(user) }, remove: (id) => { Promise.resolve(id) }, serialize: (user) => { Promise.resolve(id) }, deserialize: (id) => { Promise.resolve(user) }, @@ -303,8 +303,9 @@ module.exports = (nextApp, { functions.find({ emailToken: req.params.token }) .then(user => { if (user) { - // Reset token and update email address as verified - user.emailToken = null + // Delete current token so it cannot be used again + delete user.emailToken + // Mark email as verified now we know they have access to it user.emailVerified = true return functions.update(user) } else { diff --git a/package.json b/package.json index 63ec11f6..9238dcc1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "next-auth", - "version": "1.2.1", + "version": "1.3.0", "description": "An authentication library for Next.js", "repository": "https://github.com/iaincollins/next-auth.git", "main": "index.js", diff --git a/passport-strategies.js b/passport-strategies.js index d927f7c7..48cf5f7c 100644 --- a/passport-strategies.js +++ b/passport-strategies.js @@ -17,8 +17,8 @@ module.exports = ({ emailToken, provider } = {}) => {}, - update: (user) => {}, - insert: (user) => {}, + update: (user, profile) => {}, + insert: (user, profile) => {}, serialize: (user) => {}, deserialize: (id) => {} } @@ -69,11 +69,12 @@ module.exports = ({ strategyOptions.callbackURL = (serverUrl || '') + `${pathPrefix}/oauth/${providerName.toLowerCase()}/callback` strategyOptions.passReqToCallback = true - passport.use(new Strategy(strategyOptions, (req, accessToken, refreshToken, profile, next) => { + passport.use(new Strategy(strategyOptions, (req, accessToken, refreshToken, _profile, next) => { try { - // Normalise the provider specific profile into a standard user object. - profile = getProfile(profile) + // Normalise the provider specific profile into a standard basic + // profile object with just { id, name, email } properties. + let profile = getProfile(_profile) // Save the Access Token to the current session. req.session[providerName.toLowerCase()] = { @@ -115,7 +116,7 @@ module.exports = ({ refreshToken: refreshToken } - functions.update(user) + functions.update(user, _profile) .then(user => { return next(null, user) }) @@ -133,7 +134,7 @@ module.exports = ({ // This prevents users from linking an oAuth account to more // than one local account at the same time. return next(null, false) - } + } } else { // This secion handles if a user is already logged in and is // trying to link a new account. @@ -177,7 +178,7 @@ module.exports = ({ } // Update details for the new provider for this user. - return functions.update(user) + return functions.update(user, _profile) .then(user => { return next(null, user) }) @@ -200,10 +201,10 @@ module.exports = ({ // as that user. // Update Access and Refresh Tokens for the user if we got them. - if (accessToken || refreshToken) { + if (accessToken || refreshToken) { if (accessToken) user[providerName.toLowerCase()].accessToken = accessToken if (refreshToken) user[providerName.toLowerCase()].refreshToken = refreshToken - return functions.update(user) + return functions.update(user, _profile) .then(user => { return next(null, user) }) @@ -234,7 +235,7 @@ module.exports = ({ // or create an account elsewhere for another users email // address then trying to sign in from it, so don't do that. if (user) return next(null, false) - + // If an account does not exist, create one for them and return // a user object to passport, which will sign them in. return functions.insert({ @@ -245,7 +246,7 @@ module.exports = ({ accessToken: accessToken, refreshToken: refreshToken } - }) + }, _profile) .then(user => { return next(null, user) })