diff --git a/package-lock.json b/package-lock.json index a3f7442..0289a8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1297,6 +1297,16 @@ "@types/passport": "*" } }, + "@types/passport-twitter": { + "version": "1.0.36", + "resolved": "https://registry.npmjs.org/@types/passport-twitter/-/passport-twitter-1.0.36.tgz", + "integrity": "sha512-DeOicHcgxkUcW1d33VQbhaQikXfWiGcF5AOGjG/DPzIFdTZUYbuTEoeuK7k42ZRd9rrqdN5qe9Ry39lls00R3Q==", + "dev": true, + "requires": { + "@types/express": "*", + "@types/passport": "*" + } + }, "@types/prop-types": { "version": "15.7.3", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.3.tgz", @@ -6586,6 +6596,32 @@ "passport-oauth2": "1.x.x" } }, + "passport-google-oauth20": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", + "integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==", + "requires": { + "passport-oauth2": "1.x.x" + } + }, + "passport-instagram": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-instagram/-/passport-instagram-1.0.0.tgz", + "integrity": "sha1-6qK0LRFHO8/aUZDyYjTPSF9kVlY=", + "requires": { + "passport-oauth2": "1.x.x" + } + }, + "passport-oauth1": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/passport-oauth1/-/passport-oauth1-1.1.0.tgz", + "integrity": "sha1-p96YiiEfnPRoc3cTDqdN8ycwyRg=", + "requires": { + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "utils-merge": "1.x.x" + } + }, "passport-oauth2": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.5.0.tgz", @@ -6603,6 +6639,15 @@ "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" }, + "passport-twitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/passport-twitter/-/passport-twitter-1.0.4.tgz", + "integrity": "sha1-AaeZ4fdgvy3knyul+6MigvGJMtc=", + "requires": { + "passport-oauth1": "1.x.x", + "xtraverse": "0.1.x" + } + }, "path-browserify": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", @@ -10794,11 +10839,24 @@ "async-limiter": "~1.0.0" } }, + "xmldom": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", + "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==" + }, "xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, + "xtraverse": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/xtraverse/-/xtraverse-0.1.0.tgz", + "integrity": "sha1-t0G60BjveNip0ug63gB7P3lZxzI=", + "requires": { + "xmldom": "0.1.x" + } + }, "y18n": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", diff --git a/package.json b/package.json index 2466f1c..c013d83 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,9 @@ "mongoose": "^5.10.7", "passport": "^0.4.1", "passport-facebook": "^3.0.0", + "passport-google-oauth20": "^2.0.0", + "passport-instagram": "^1.0.0", + "passport-twitter": "^1.0.4", "react": "^16.13.0", "react-dom": "^16.13.0", "redis": "^3.0.2" @@ -32,6 +35,7 @@ "@types/node": "^12.11.6", "@types/passport": "^1.0.4", "@types/passport-facebook": "^2.1.10", + "@types/passport-twitter": "^1.0.36", "@types/react": "^16.9.11", "@types/react-dom": "^16.9.4", "@types/redis": "^2.8.27", diff --git a/server/auth/passport.ts b/server/auth/passport.ts index 82a7e7c..ff43ae1 100644 --- a/server/auth/passport.ts +++ b/server/auth/passport.ts @@ -1,5 +1,6 @@ import passport from 'passport'; import { facebookStrategy, facebookRouter } from './providers/facebook'; +import { twitterStrategy, twitterRouter } from './providers/twitter'; import { Router } from 'express' import UserModel, { User } from '../models/user' @@ -15,7 +16,9 @@ export function initPassport(): void { }); passport.use('facebook', facebookStrategy()); + passport.use('twitter', twitterStrategy()); } export const authRouter = Router(); authRouter.use(facebookRouter); +authRouter.use(twitterRouter); diff --git a/server/auth/providers/twitter.ts b/server/auth/providers/twitter.ts new file mode 100644 index 0000000..da3aa43 --- /dev/null +++ b/server/auth/providers/twitter.ts @@ -0,0 +1,23 @@ +import { Strategy, Profile, IStrategyOptionBase } from 'passport-twitter'; + +import { Router } from 'express' +import passport from 'passport' + +import genericStrategy from '../strategy' + +const strategyOptions: IStrategyOptionBase = { + consumerKey: process.env.TWITTER_CONSUMER_KEY as string, + consumerSecret: process.env.TWITTER_CONSUMER_SECRET as string, + callbackURL: '/auth/twitter/redirect', + includeEmail: true, +} + +export function twitterStrategy() { + return new Strategy(strategyOptions, genericStrategy('twitter')); +} + +export const twitterRouter = Router() + +twitterRouter.get('/twitter', passport.authenticate('twitter')); +twitterRouter.get('/twitter/redirect', + passport.authenticate('twitter', { successRedirect: '/museo', failureRedirect: '/' })); diff --git a/server/auth/strategy.ts b/server/auth/strategy.ts index c7e89a0..df7f80d 100644 --- a/server/auth/strategy.ts +++ b/server/auth/strategy.ts @@ -4,13 +4,16 @@ import { authProviders } from '../types' type doneCallback = (error: string | null, user?: Promise | User | boolean) => void -function genericStrategy(provider: authProviders) { +function genericStrategy(provider: authProviders) { return async ( _accessToken: string, _refreshToken: string, profile: ProfileT, done: doneCallback ) => { + console.log(profile) + + if (!profile.emails?.[0].value) { console.error(`${provider} Email permission not provided`) return done(null, false); @@ -32,7 +35,7 @@ function genericStrategy(provider: authProviders) { name: profile.displayName, provider, email: profile.emails?.[0].value, - photo: profile.photos?.[0].value, + photo: profile.photos?.[0].value.replace('_normal', ''), }).save((err: string) => { if (err) throw (err); }); diff --git a/views/index.tsx b/views/index.tsx index cc35d00..8d2831a 100644 --- a/views/index.tsx +++ b/views/index.tsx @@ -8,6 +8,7 @@ const Index: React.FC = () => { Museo Autenticarse con Facebook + Autenticarse con Twitter ); };