diff --git a/package.json b/package.json
index e2e3599..e905f1f 100644
--- a/package.json
+++ b/package.json
@@ -24,6 +24,7 @@
"babel-preset-es2015": "^6.9.0",
"babel-preset-react": "^6.11.1",
"css-loader": "^0.23.1",
+ "dotenv": "^2.0.0",
"file-loader": "^0.9.0",
"html-webpack-plugin": "^2.22.0",
"postcss": "^5.0.21",
@@ -36,6 +37,8 @@
"webpack-dev-server": "^1.14.1"
},
"dependencies": {
+ "auth0-lock": "^10.0.0",
+ "jwt-decode": "^2.1.0",
"postcss": "^5.1.0",
"react": "^15.2.1",
"react-dom": "^15.2.1"
diff --git a/src/components/App/App.jsx b/src/components/App/App.jsx
index 05145cc..a03d23f 100644
--- a/src/components/App/App.jsx
+++ b/src/components/App/App.jsx
@@ -1,12 +1,54 @@
import React, { Component } from 'react';
+import AuthService from '../../utils/AuthService'
import './App.scss';
+import MainMenu from '../MainMenu/MainMenu';
+import Login from '../Login/Login';
+
+const options = {
+ auth: {
+ params: {
+ redirectUrl: 'http://localhost:8080',
+ responseType: 'token'
+ }
+ }
+};
+const auth = new AuthService(__AUTH0_CLIENT_ID__, __AUTH0_DOMAIN__, options);
class App extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ profile: auth.getProfile()
+ }
+ auth.on('profile_updated', (newProfile) => {
+ this.setState({profile: newProfile})
+ })
+ this.loginButton = this.loginButton.bind(this);
+ }
+
+ logout() {
+ auth.logout()
+ this.setState({
+ profile: auth.getProfile()
+ })
+ }
+
+ loginButton() {
+ if(this.state.profile.hasOwnProperty('user_id'))
+ return ;
+ else
+ return ;
+ }
+
render() {
return (
-
hello world
+
+
+ {this.loginButton()}
+
)
}
}
+//
export default App;
\ No newline at end of file
diff --git a/src/components/Login/Login.jsx b/src/components/Login/Login.jsx
new file mode 100644
index 0000000..2230114
--- /dev/null
+++ b/src/components/Login/Login.jsx
@@ -0,0 +1,36 @@
+import React, { Component, PropTypes as T } from 'react';
+import AuthService from '../../utils/AuthService'
+import './Login.scss';
+
+class Login extends Component {
+ constructor(props) {
+ super(props);
+ this.loginButton = this.loginButton.bind(this);
+ }
+
+ logout() {
+/* this.props.auth.logout()
+ this.setState({
+ profile: this.props.auth.getProfile()
+ }) */
+ }
+
+ loginButton() {
+ if(this.props.profile.hasOwnProperty('user_id'))
+ return ;
+ else
+ return ;
+ }
+
+ render() {
+ return (
+ {this.loginButton()}
+ )
+ }
+}
+
+Login.propTypes = {
+ auth: T.instanceOf(AuthService)
+};
+
+export default Login;
\ No newline at end of file
diff --git a/src/components/Login/Login.scss b/src/components/Login/Login.scss
new file mode 100644
index 0000000..e69de29
diff --git a/src/components/MainMenu/MainMenu.jsx b/src/components/MainMenu/MainMenu.jsx
new file mode 100644
index 0000000..a8b6402
--- /dev/null
+++ b/src/components/MainMenu/MainMenu.jsx
@@ -0,0 +1,12 @@
+import React, { Component } from 'react';
+import './MainMenu.scss';
+
+class MainMenu extends Component {
+ render() {
+ return (
+ {this.props.profile.hasOwnProperty('user_id')?this.props.profile.name+' is logged in':'not logged in'}
+ )
+ }
+}
+
+export default MainMenu;
\ No newline at end of file
diff --git a/src/components/MainMenu/MainMenu.scss b/src/components/MainMenu/MainMenu.scss
new file mode 100644
index 0000000..e69de29
diff --git a/src/utils/AuthService.js b/src/utils/AuthService.js
new file mode 100644
index 0000000..8adfdce
--- /dev/null
+++ b/src/utils/AuthService.js
@@ -0,0 +1,75 @@
+import { EventEmitter } from 'events'
+import { isTokenExpired } from './jwtHelper'
+import Auth0Lock from 'auth0-lock'
+
+export default class AuthService extends EventEmitter {
+ constructor(clientId, domain, options) {
+ super()
+ // Configure Auth0
+ this.lock = new Auth0Lock(clientId, domain, options)
+ // Add callback for lock `authenticated` event
+ this.lock.on('authenticated', this._doAuthentication.bind(this))
+ // Add callback for lock `authorization_error` event
+ this.lock.on('authorization_error', this._authorizationError.bind(this))
+ // binds login functions to keep this context
+ this.login = this.login.bind(this)
+ }
+
+ _doAuthentication(authResult){
+ // Saves the user token
+ this.setToken(authResult.idToken)
+ // Async loads the user profile data
+ this.lock.getProfile(authResult.idToken, (error, profile) => {
+ if (error) {
+ console.log('Error loading the Profile', error)
+ } else {
+ this.setProfile(profile)
+ }
+ })
+ }
+
+ _authorizationError(error){
+ // Unexpected authentication error
+ console.log('Authentication Error', error)
+ }
+
+ login() {
+ // Call the show method to display the widget.
+ this.lock.show()
+ }
+
+ loggedIn(){
+ // Checks if there is a saved token and it's still valid
+ const token = this.getToken()
+ return !!token && !isTokenExpired(token)
+ }
+
+ setProfile(profile){
+ // Saves profile data to localStorage
+ localStorage.setItem('profile', JSON.stringify(profile))
+ // Triggers profile_updated event to update the UI
+ this.emit('profile_updated', profile)
+ }
+
+ getProfile(){
+ // Retrieves the profile data from localStorage
+ const profile = localStorage.getItem('profile')
+ return profile ? JSON.parse(localStorage.profile) : {}
+ }
+
+ setToken(idToken){
+ // Saves user token to localStorage
+ localStorage.setItem('id_token', idToken)
+ }
+
+ getToken(){
+ // Retrieves the user token from localStorage
+ return localStorage.getItem('id_token')
+ }
+
+ logout(){
+ // Clear user token and profile data from localStorage
+ localStorage.removeItem('id_token');
+ localStorage.removeItem('profile');
+ }
+}
diff --git a/src/utils/jwtHelper.js b/src/utils/jwtHelper.js
new file mode 100644
index 0000000..666c0bc
--- /dev/null
+++ b/src/utils/jwtHelper.js
@@ -0,0 +1,21 @@
+import decode from 'jwt-decode';
+
+export function getTokenExpirationDate(token){
+ const decoded = decode(token)
+ if(!decoded.exp) {
+ return null
+ }
+
+ const date = new Date(0) // The 0 here is the key, which sets the date to the epoch
+ date.setUTCSeconds(decoded.exp)
+ return date
+}
+
+export function isTokenExpired(token){
+ const date = getTokenExpirationDate(token)
+ const offsetSeconds = 0
+ if (date === null) {
+ return false
+ }
+ return !(date.valueOf() > (new Date().valueOf() + (offsetSeconds * 1000)))
+}
diff --git a/webpack.config.js b/webpack.config.js
index 2d2b944..c911356 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,8 +1,25 @@
-var path = require('path');
-var webpack = require('webpack');
-var autoprefixer = require('autoprefixer');
-var precss = require('precss');
-var HtmlWebPackPlugin = require('html-webpack-plugin');
+const NODE_ENV = 'development';
+const dotenv = require('dotenv');
+
+const webpack = require('webpack');
+const fs = require('fs');
+const path = require('path');
+const autoprefixer = require('autoprefixer');
+const precss = require('precss');
+const HtmlWebPackPlugin = require('html-webpack-plugin');
+
+const dotEnvVars = dotenv.config();
+const envVariables =
+ Object.assign({}, dotEnvVars);
+const defines =
+ Object.keys(envVariables)
+ .reduce((memo, key) => {
+ const val = JSON.stringify(envVariables[key]);
+ memo[`__${key.toUpperCase()}__`] = val;
+ return memo;
+ }, {
+ __NODE_ENV__: JSON.stringify(NODE_ENV)
+ });
module.exports = {
entry: [
@@ -24,7 +41,8 @@ module.exports = {
filename: '../index.html'
}),
new webpack.HotModuleReplacementPlugin(),
- new webpack.NoErrorsPlugin()
+ new webpack.NoErrorsPlugin(),
+ new webpack.DefinePlugin(defines)
],
module: {
loaders: [
@@ -40,11 +58,11 @@ module.exports = {
loaders: ['style-loader', 'css-loader']
},
{
- test: /\.(png|jpg|svg|woff|woff2)?(\?v=\d+.\d+.\d+)?$/,
+ test: /\.(png|jpg|svg|woff|woff2)?(\?v=\d+.\d+.\d+)?$/,
loader: 'url-loader?limit=25000'
},
{
- test: /\.(eot|ttf)$/,
+ test: /\.(eot|ttf)$/,
loader: 'file-loader'
}
]
diff --git a/webpack.config.prod.js b/webpack.config.prod.js
index 184e5ee..f53d135 100644
--- a/webpack.config.prod.js
+++ b/webpack.config.prod.js
@@ -1,8 +1,25 @@
-var path = require('path');
-var webpack = require('webpack');
-var autoprefixer = require('autoprefixer');
-var precss = require('precss');
-var HtmlWebPackPlugin = require('html-webpack-plugin');
+const NODE_ENV = 'production';
+const dotenv = require('dotenv');
+
+const webpack = require('webpack');
+const fs = require('fs');
+const path = require('path');
+const autoprefixer = require('autoprefixer');
+const precss = require('precss');
+const HtmlWebPackPlugin = require('html-webpack-plugin');
+
+const dotEnvVars = dotenv.config();
+const envVariables =
+ Object.assign({}, dotEnvVars);
+const defines =
+ Object.keys(envVariables)
+ .reduce((memo, key) => {
+ const val = JSON.stringify(envVariables[key]);
+ memo[`__${key.toUpperCase()}__`] = val;
+ return memo;
+ }, {
+ __NODE_ENV__: JSON.stringify(NODE_ENV)
+ });
module.exports = {
devtool: 'cheap-module-source-map',
@@ -35,7 +52,8 @@ module.exports = {
warnings: false
},
}),
- new webpack.NoErrorsPlugin()
+ new webpack.NoErrorsPlugin(),
+ new webpack.DefinePlugin(defines)
],
module: {
loaders: [