* google oauth added * google credentials updated .env description for google oauth * changes done wrt review
This commit is contained in:
parent
55d8722a02
commit
307091ad3c
8 changed files with 156 additions and 0 deletions
|
@ -23,6 +23,8 @@ This project is currently in development! It will be announced when there is a (
|
||||||
S3_BUCKET=<your-s3-bucket>
|
S3_BUCKET=<your-s3-bucket>
|
||||||
GITHUB_ID=<your-github-client-id>
|
GITHUB_ID=<your-github-client-id>
|
||||||
GITHUB_SECRET=<your-github-client-secret>
|
GITHUB_SECRET=<your-github-client-secret>
|
||||||
|
GOOGLE_ID=<your-google-client-id> (use google+ api)
|
||||||
|
GOOGLE_SECRET=<your-google-client-secret> (use google+ api)
|
||||||
MAILGUN_KEY=<your-mailgun-api-key>
|
MAILGUN_KEY=<your-mailgun-api-key>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
47
client/images/google.svg
Normal file
47
client/images/google.svg
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
<?xml version="1.0" encoding="iso-8859-1"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||||
|
<path style="fill:#FBBB00;" d="M113.47,309.408L95.648,375.94l-65.139,1.378C11.042,341.211,0,299.9,0,256
|
||||||
|
c0-42.451,10.324-82.483,28.624-117.732h0.014l57.992,10.632l25.404,57.644c-5.317,15.501-8.215,32.141-8.215,49.456
|
||||||
|
C103.821,274.792,107.225,292.797,113.47,309.408z"/>
|
||||||
|
<path style="fill:#518EF8;" d="M507.527,208.176C510.467,223.662,512,239.655,512,256c0,18.328-1.927,36.206-5.598,53.451
|
||||||
|
c-12.462,58.683-45.025,109.925-90.134,146.187l-0.014-0.014l-73.044-3.727l-10.338-64.535
|
||||||
|
c29.932-17.554,53.324-45.025,65.646-77.911h-136.89V208.176h138.887L507.527,208.176L507.527,208.176z"/>
|
||||||
|
<path style="fill:#28B446;" d="M416.253,455.624l0.014,0.014C372.396,490.901,316.666,512,256,512
|
||||||
|
c-97.491,0-182.252-54.491-225.491-134.681l82.961-67.91c21.619,57.698,77.278,98.771,142.53,98.771
|
||||||
|
c28.047,0,54.323-7.582,76.87-20.818L416.253,455.624z"/>
|
||||||
|
<path style="fill:#F14336;" d="M419.404,58.936l-82.933,67.896c-23.335-14.586-50.919-23.012-80.471-23.012
|
||||||
|
c-66.729,0-123.429,42.957-143.965,102.724l-83.397-68.276h-0.014C71.23,56.123,157.06,0,256,0
|
||||||
|
C318.115,0,375.068,22.126,419.404,58.936z"/>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
24
client/modules/User/components/GoogleButton.jsx
Normal file
24
client/modules/User/components/GoogleButton.jsx
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import InlineSVG from 'react-inlinesvg';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
// const googleUrl = require('../../../images/google.svg');
|
||||||
|
import googleUrl from '../../../images/google.svg';
|
||||||
|
|
||||||
|
function GoogleButton(props) {
|
||||||
|
return (
|
||||||
|
<a
|
||||||
|
className="google-button"
|
||||||
|
href="/auth/google/"
|
||||||
|
>
|
||||||
|
<InlineSVG src={googleUrl} className="google-icon" />
|
||||||
|
<span>{props.buttonText}</span>
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
GoogleButton.propTypes = {
|
||||||
|
buttonText: PropTypes.string.isRequired
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GoogleButton;
|
|
@ -8,6 +8,8 @@ import { validateAndLoginUser } from '../actions';
|
||||||
import LoginForm from '../components/LoginForm';
|
import LoginForm from '../components/LoginForm';
|
||||||
import { validateLogin } from '../../../utils/reduxFormUtils';
|
import { validateLogin } from '../../../utils/reduxFormUtils';
|
||||||
import GithubButton from '../components/GithubButton';
|
import GithubButton from '../components/GithubButton';
|
||||||
|
import GoogleButton from '../components/GoogleButton';
|
||||||
|
|
||||||
|
|
||||||
const exitUrl = require('../../../images/exit.svg');
|
const exitUrl = require('../../../images/exit.svg');
|
||||||
const logoUrl = require('../../../images/p5js-logo.svg');
|
const logoUrl = require('../../../images/p5js-logo.svg');
|
||||||
|
@ -51,6 +53,7 @@ class LoginView extends React.Component {
|
||||||
<LoginForm {...this.props} />
|
<LoginForm {...this.props} />
|
||||||
<h2 className="form-container__divider">Or</h2>
|
<h2 className="form-container__divider">Or</h2>
|
||||||
<GithubButton buttonText="Login with Github" />
|
<GithubButton buttonText="Login with Github" />
|
||||||
|
<GoogleButton buttonText="Login with Google" />
|
||||||
<p className="form__navigation-options">
|
<p className="form__navigation-options">
|
||||||
Don't have an account?
|
Don't have an account?
|
||||||
<Link className="form__signup-button" to="/signup">Sign Up</Link>
|
<Link className="form__signup-button" to="/signup">Sign Up</Link>
|
||||||
|
|
|
@ -21,3 +21,32 @@
|
||||||
.github-icon {
|
.github-icon {
|
||||||
margin-right: #{10 / $base-font-size}rem;
|
margin-right: #{10 / $base-font-size}rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.google-button {
|
||||||
|
@include themify() {
|
||||||
|
@extend %button;
|
||||||
|
& path {
|
||||||
|
color: getThemifyVariable('primary-text-color');
|
||||||
|
}
|
||||||
|
&:hover path, &:active path {
|
||||||
|
fill: $white;
|
||||||
|
}
|
||||||
|
&:hover, &:active {
|
||||||
|
background-color: getThemifyVariable('secondary-text-color');
|
||||||
|
border-color: getThemifyVariable('secondary-text-color');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
margin-top: 4px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: #{300 / $base-font-size}rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.google-icon {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
margin-right: #{10 / $base-font-size}rem;
|
||||||
|
}
|
|
@ -99,6 +99,7 @@
|
||||||
"nodemailer-mailgun-transport": "^1.2.2",
|
"nodemailer-mailgun-transport": "^1.2.2",
|
||||||
"passport": "^0.3.2",
|
"passport": "^0.3.2",
|
||||||
"passport-github": "^1.1.0",
|
"passport-github": "^1.1.0",
|
||||||
|
"passport-google-oauth20": "^1.0.0",
|
||||||
"passport-local": "^1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
"pretty-bytes": "^3.0.1",
|
"pretty-bytes": "^3.0.1",
|
||||||
"primer-tooltips": "^1.4.1",
|
"primer-tooltips": "^1.4.1",
|
||||||
|
|
|
@ -4,6 +4,8 @@ const lodash = require('lodash');
|
||||||
const passport = require('passport');
|
const passport = require('passport');
|
||||||
const GitHubStrategy = require('passport-github').Strategy;
|
const GitHubStrategy = require('passport-github').Strategy;
|
||||||
const LocalStrategy = require('passport-local').Strategy;
|
const LocalStrategy = require('passport-local').Strategy;
|
||||||
|
const GoogleStrategy = require('passport-google-oauth20').Strategy;
|
||||||
|
|
||||||
|
|
||||||
passport.serializeUser((user, done) => {
|
passport.serializeUser((user, done) => {
|
||||||
done(null, user.id);
|
done(null, user.id);
|
||||||
|
@ -99,3 +101,46 @@ passport.use(new GitHubStrategy({
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sign in with Google.
|
||||||
|
*/
|
||||||
|
passport.use(new GoogleStrategy({
|
||||||
|
clientID: process.env.GOOGLE_ID,
|
||||||
|
clientSecret: process.env.GOOGLE_SECRET,
|
||||||
|
callbackURL: '/auth/google/callback',
|
||||||
|
passReqToCallback: true,
|
||||||
|
scope: ['email'],
|
||||||
|
}, (req, accessToken, refreshToken, profile, done) => {
|
||||||
|
User.findOne({ google: profile._json.emails[0].value }, (findByGoogleErr, existingUser) => {
|
||||||
|
if (existingUser) {
|
||||||
|
done(null, existingUser);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const primaryEmail = profile._json.emails[0].value;
|
||||||
|
|
||||||
|
User.findOne({
|
||||||
|
email: primaryEmail,
|
||||||
|
}, (findByEmailErr, existingEmailUser) => {
|
||||||
|
if (existingEmailUser) {
|
||||||
|
existingEmailUser.email = existingEmailUser.email || primaryEmail;
|
||||||
|
existingEmailUser.google = profile._json.emails[0].value;
|
||||||
|
existingEmailUser.username = existingEmailUser.username || profile._json.emails[0].value;
|
||||||
|
existingEmailUser.tokens.push({ kind: 'google', accessToken });
|
||||||
|
existingEmailUser.name = existingEmailUser.name || profile._json.displayName;
|
||||||
|
existingEmailUser.verified = User.EmailConfirmation.Verified;
|
||||||
|
existingEmailUser.save(saveErr => done(null, existingEmailUser));
|
||||||
|
} else {
|
||||||
|
const user = new User();
|
||||||
|
user.email = primaryEmail;
|
||||||
|
user.google = profile._json.emails[0].value;
|
||||||
|
user.username = profile._json.emails[0].value;
|
||||||
|
user.tokens.push({ kind: 'google', accessToken });
|
||||||
|
user.name = profile._json.displayName;
|
||||||
|
user.verified = User.EmailConfirmation.Verified;
|
||||||
|
user.save(saveErr => done(null, user));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
|
|
@ -96,6 +96,11 @@ app.get('/auth/github/callback', passport.authenticate('github', { failureRedire
|
||||||
res.redirect('/');
|
res.redirect('/');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.get('/auth/google', passport.authenticate('google'));
|
||||||
|
app.get('/auth/google/callback', passport.authenticate('google', { failureRedirect: '/login' }), (req, res) => {
|
||||||
|
res.redirect('/');
|
||||||
|
});
|
||||||
|
|
||||||
// configure passport
|
// configure passport
|
||||||
require('./config/passport');
|
require('./config/passport');
|
||||||
// const passportConfig = require('./config/passport');
|
// const passportConfig = require('./config/passport');
|
||||||
|
|
Loading…
Reference in a new issue