add Google auth plugin

This commit is contained in:
Kit Westneat
2018-02-16 14:40:28 -05:00
parent 26476f42f7
commit 499a7fe686
17 changed files with 241 additions and 1 deletions
+1
View File
@@ -25,6 +25,7 @@ plugins.json
plugins/*
!plugins/talk-plugin-akismet
!plugins/talk-plugin-facebook-auth
!plugins/talk-plugin-google-auth
!plugins/talk-plugin-auth
!plugins/talk-plugin-respect
!plugins/talk-plugin-offtopic
+25 -1
View File
@@ -77,6 +77,30 @@ or by visiting the
guide. This is only required while the `talk-plugin-facebook-auth` plugin is
enabled.
## TALK_GOOGLE_CLIENT_ID
The Google OAuth2 client ID for your Google login web app. You can learn more
about getting a Google Client ID at the
[Google API Console](https://console.developers.google.com/apis/){:target="_blank"}.
You will need to enable the Google+ API in the dashboard and create credentials
for a new OAuth client ID web application. The authorized JavaScript origin
should be set to the Talk domain, and the authorized redirect URI should be set
to http://<example.com>/api/v1/auth/google/callback. This is only required while
the `talk-plugin-google-auth` plugin is enabled.
## TALK_GOOGLE_CLIENT_SECRET
The Google OAuth2 client ID for your Google login web app. You can learn more
about getting a Google Client ID at the
[Google API Console](https://console.developers.google.com/apis/){:target="_blank"}.
You will need to enable the Google+ API in the dashboard and create credentials
for a new OAuth client ID web application. The authorized JavaScript origin
should be set to the Talk domain, and the authorized redirect URI should be set
to http://<example.com>/api/v1/auth/google/callback. This is only required while
the `talk-plugin-google-auth` plugin is enabled.
## TALK_HELMET_CONFIGURATION
A JSON string representing the configuration passed to the
@@ -538,4 +562,4 @@ This is a **Build Variable** and must be consumed during build. If using the
[Docker-onbuild]({{ "/installation-from-docker/#onbuild" | relative_url }})
image you can specify it with `--build-arg TALK_REPLY_COMMENTS_LOAD_DEPTH=3`.
Specifies the initial replies to load for a comment. (Default `3`)
Specifies the initial replies to load for a comment. (Default `3`)
@@ -0,0 +1,3 @@
{
"extends": "@coralproject/eslint-config-talk"
}
@@ -0,0 +1,3 @@
{
"extends": "@coralproject/eslint-config-talk/client"
}
@@ -0,0 +1,7 @@
export const loginWithGoogle = () => (dispatch, _, { rest }) => {
window.open(
`${rest.uri}/auth/google`,
'Continue with Google',
'menubar=0,resizable=0,width=500,height=500,top=200,left=500'
);
};
@@ -0,0 +1,13 @@
.button {
background-color: #db3236;
border-color: #db3236;
color: rgb(255, 255, 255);
width: 100%;
box-sizing: border-box;
padding: 10px 20px;
}
.button:hover {
background-color: #c71e22;
border-color: #c71e22;
}
@@ -0,0 +1,11 @@
import React from 'react';
import { BareButton } from 'plugin-api/beta/client/components/ui';
import styles from './GoogleButton.css';
export default ({ onClick, children }) => {
return (
<BareButton className={styles.button} onClick={onClick}>
{children}
</BareButton>
);
};
@@ -0,0 +1,9 @@
import React from 'react';
import GoogleButton from '../containers/GoogleButton';
import { t } from 'plugin-api/beta/client/services';
export default () => {
return (
<GoogleButton>{t('talk-plugin-google-auth.sign_in')}</GoogleButton>
);
};
@@ -0,0 +1,9 @@
import React from 'react';
import GoogleButton from '../containers/GoogleButton';
import { t } from 'plugin-api/beta/client/services';
export default () => {
return (
<GoogleButton>{t('talk-plugin-google-auth.sign_up')}</GoogleButton>
);
};
@@ -0,0 +1,9 @@
import { connect } from 'plugin-api/beta/client/hocs';
import { bindActionCreators } from 'redux';
import { loginWithGoogle } from '../actions';
import GoogleButton from '../components/GoogleButton';
const mapDispatchToProps = dispatch =>
bindActionCreators({ onClick: loginWithGoogle }, dispatch);
export default connect(null, mapDispatchToProps)(GoogleButton);
@@ -0,0 +1,11 @@
import SignIn from './components/SignIn';
import SignUp from './components/SignUp';
import translations from './translations.yml';
export default {
translations,
slots: {
authExternalSignIn: [SignIn],
authExternalSignUp: [SignUp],
},
};
@@ -0,0 +1,20 @@
en:
talk-plugin-google-auth:
sign_in: "Sign in with Google"
sign_up: "Sign up with Google"
es:
talk-plugin-google-auth:
google_sign_in: "Entrar con Google"
google_sign_up: "Registrarse con Google"
fr:
talk-plugin-google-auth:
google_sign_in: "Connectez-vous avec Google"
google_sign_up: "Inscrivez-vous avec Google"
zh_CN:
talk-plugin-google-auth:
google_sign_in: "使用 Google 帐号"
google_sign_up: "使用 Google 帐号"
zh_TW:
talk-plugin-google-auth:
google_sign_in: "使用 Google 帳號"
google_sign_up: "使用 Google 帳號"
+7
View File
@@ -0,0 +1,7 @@
const passport = require('./server/passport');
const router = require('./server/router');
module.exports = {
passport,
router,
};
@@ -0,0 +1,9 @@
{
"name": "talk-plugin-google-auth",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"passport-google-oauth2": "^0.1.6"
}
}
@@ -0,0 +1,41 @@
const GoogleStrategy = require('passport-google-oauth2').Strategy;
const UsersService = require('services/users');
const { ValidateUserLogin } = require('services/passport');
let { ROOT_URL } = require('config');
if (ROOT_URL[ROOT_URL.length - 1] !== '/') {
ROOT_URL += '/';
}
module.exports = passport => {
if (
process.env.TALK_GOOGLE_CLIENT_ID &&
process.env.TALK_GOOGLE_CLIENT_SECRET &&
process.env.TALK_ROOT_URL
) {
passport.use(
new GoogleStrategy(
{
clientID: process.env.TALK_GOOGLE_CLIENT_ID,
clientSecret: process.env.TALK_GOOGLE_CLIENT_SECRET,
callbackURL: `${ROOT_URL}api/v1/auth/google/callback`,
passReqToCallback: true,
},
async (req, accessToken, refreshToken, profile, done) => {
let user;
try {
user = await UsersService.findOrCreateExternalUser(profile);
} catch (err) {
return done(err.toString());
}
return ValidateUserLogin(profile, user, done);
}
)
);
} else if (process.env.NODE_ENV !== 'test') {
throw new Error(
'Google cannot be enabled, missing one of TALK_GOOGLE_CLIENT_ID, TALK_GOOGLE_CLIENT_SECRET, TALK_ROOT_URL'
);
}
};
@@ -0,0 +1,29 @@
module.exports = router => {
const { passport, HandleAuthPopupCallback } = require('services/passport');
/**
* Google auth endpoint, this will redirect the user immediatly to google
* for authorization.
*/
router.get(
'/api/v1/auth/google',
passport.authenticate('google', {
display: 'popup',
authType: 'rerequest',
scope: ['profile'],
})
);
/**
* Google callback endpoint, this will send the user a html page designed to
* send back the user credentials upon sucesfull login.
*/
router.get('/api/v1/auth/google/callback', (req, res, next) => {
// Perform the google login flow and pass the data back through the opener.
passport.authenticate(
'google',
{ session: false },
HandleAuthPopupCallback(req, res, next)
)(req, res, next);
});
};
+34
View File
@@ -0,0 +1,34 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
oauth@0.9.x:
version "0.9.15"
resolved "https://registry.yarnpkg.com/oauth/-/oauth-0.9.15.tgz#bd1fefaf686c96b75475aed5196412ff60cfb9c1"
passport-google-oauth2@^0.1.6:
version "0.1.6"
resolved "https://registry.yarnpkg.com/passport-google-oauth2/-/passport-google-oauth2-0.1.6.tgz#dfd7016ac7449fe27cfeb252ae974afc23257a0d"
dependencies:
passport-oauth2 "^1.1.2"
passport-oauth2@^1.1.2:
version "1.4.0"
resolved "https://registry.yarnpkg.com/passport-oauth2/-/passport-oauth2-1.4.0.tgz#f62f81583cbe12609be7ce6f160b9395a27b86ad"
dependencies:
oauth "0.9.x"
passport-strategy "1.x.x"
uid2 "0.0.x"
utils-merge "1.x.x"
passport-strategy@1.x.x:
version "1.0.0"
resolved "https://registry.yarnpkg.com/passport-strategy/-/passport-strategy-1.0.0.tgz#b5539aa8fc225a3d1ad179476ddf236b440f52e4"
uid2@0.0.x:
version "0.0.3"
resolved "https://registry.yarnpkg.com/uid2/-/uid2-0.0.3.tgz#483126e11774df2f71b8b639dcd799c376162b82"
utils-merge@1.x.x:
version "1.0.1"
resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713"