Skip to content

Instantly share code, notes, and snippets.

@josepaiva94
Created August 3, 2017 17:55
Show Gist options
  • Save josepaiva94/ee7d4b8d659500aeb5846142e25bd411 to your computer and use it in GitHub Desktop.
Save josepaiva94/ee7d4b8d659500aeb5846142e25bd411 to your computer and use it in GitHub Desktop.
Link multiple OAuth providers to account by email address instead of creating new account (FeathersJS)
import Debug from 'debug';
import { Verifier } from 'feathers-authentication-oauth2';
const debug = Debug('feathers-authentication-emailfirstoauth2:verify');
class EmailFirstOAuth2Verifier extends Verifier {
constructor (app, options = {}) {
options.emailField = options.emailField || 'email';
super(app, options);
}
verify (req, accessToken, refreshToken, profile, done) {
debug('Checking credentials');
const options = this.options;
const query = {
$or: [
{ [options.idField]: profile.id },
{ [options.emailField]: {$in: profile.emails.map(emailObj => emailObj.value)} }
],
$limit: 1
};
const data = { profile, accessToken, refreshToken };
let existing;
// Check request object for an existing entity
if (req && req[options.entity]) {
existing = req[options.entity];
}
// Check the request that came from a hook for an existing entity
if (!existing && req && req.params && req.params[options.entity]) {
existing = req.params[options.entity];
}
// If there is already an entity on the request object (ie. they are
// already authenticated) attach the profile to the existing entity
// because they are likely "linking" social accounts/profiles.
if (existing) {
return this._updateEntity(existing, data)
.then(entity => done(null, entity))
.catch(error => error ? done(error) : done(null, error));
}
// Find or create the user since they could have signed up via facebook.
this.service
.find({ query })
.then(this._normalizeResult)
.then(entity => entity ? this._updateEntity(entity, data) : this._createEntity(data))
.then(entity => {
const id = entity[this.service.id];
const payload = { [`${this.options.entity}Id`]: id };
done(null, entity, payload);
})
.catch(error => error ? done(error) : done(null, error));
}
}
export default EmailFirstOAuth2Verifier;
// How to use:
//
// import EmailFirstOAuth2Verifier from './verifiers/verifier';
//
// app.configure(oauth2(Object.assign({
// name: 'google',
// Strategy: GoogleStrategy,
// Verifier: EmailFirstOAuth2Verifier,
// emailField: 'email'
// }, config.google)));
@pedrogk
Copy link

pedrogk commented Sep 1, 2017

Thanks for sharing this gist, José.

I am using feathers-authentication-oauth and every time I login with a user, a duplicate entry is inserted in the user database (NeDB), even if it is the same user with the same oauth provider. Do you know if that is the default behavior? I suppose I could get over it setting up a custom verifier like this one, but just wanted to double check if you had ran into the same issue.

Thanks for your attention.

@josepaiva94
Copy link
Author

josepaiva94 commented Jan 21, 2018

Hi @pedrogk .

Sorry for the long delay, I was not notified. This gist is exactly to prevent the behavior that you have mentioned.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment