Auth0 client integration ready

This commit is contained in:
Luis Fernando Molina committed 2018-09-06 20:34:06 +02:00
1 parent 3f9423e91d
commit eca2e6deff
12 files changed
+614 -10

No files matched your search

+32 -1
View File
@@ -1,6 +1,9 @@
import React, { Component } from 'react';
import ApolloClient from 'apollo-boost';
import {ApolloProvider} from 'react-apollo';
import { ApolloLink } from 'apollo-link';
import { HttpLink } from 'apollo-link-http'
import { setContext } from 'apollo-link-context';
import { Route, BrowserRouter, Switch } from 'react-router-dom'
@@ -16,13 +19,37 @@ import About from './components/About'
import Contact from './components/Contact'
import Post from './components/Post'
import Footer from './components/Footer'
import Callback from './components/Callback'
import Auth from './auth/index'
/*
const httpLink = new HttpLink({ uri: 'http://localhost:4000/graphql', changeOrigin: true })
// Apollo Client Setup
const client = new ApolloClient({
const authLink = setContext((_, { headers }) => {
// get the authentication token from local storage if it exists
const token = localStorage.getItem('access_token')
// return the headers to the context so httpLink can read them
return {
headers: {
...headers,
Authorization: token ? `Bearer ${token}` : ``
}
}
})
export const client = new ApolloClient({
link: httpLink
})
*/
export const client = new ApolloClient({
uri:'http://localhost:4000/graphql'
})
export const auth = new Auth(result => console.log('auth result', result), client);
class App extends Component {
render() {
@@ -40,6 +67,10 @@ class App extends Component {
<Route path='/about' component={About} />
<Route path='/contact' component={Contact} />
<Route path='/:post_id' component={Post} />
<Route path='/callback' render={(props) => {
auth.handleAuthentication(props)
return <Callback {...props} />
}}/>
</Switch>
<Footer/>
</div>
+211
View File
@@ -0,0 +1,211 @@
import Auth0Lock from 'auth0-lock'
import gql from 'graphql-tag'
import { getItem, setItem, removeItem } from './local-storage'
import { validObject, deleteCookie } from './js-helpers'
import { client } from '../App'
import { AUTH_CONFIG } from './Auth0'
console.log(process.env.AUTH0_CLIENTID)
const AUTHENTICATE = gql`
mutation authenticate($idToken: String!) {
authenticate(idToken: $idToken) {
id
nickname
auth0id
profile {
email
avatar
}
}
}
`
const lock = new Auth0Lock(AUTH_CONFIG.clientId, AUTH_CONFIG.domain, {
oidcConformant: true,
autoclose: true,
auth: {
sso: true,
redirectUrl: window.location.origin + '/callback',
responseType: 'token id_token',
audience: `${AUTH_CONFIG.api_audience}`,
params: {
scope: `openid profile email user_metadata app_metadata picture`
}
}
})
class Auth {
constructor (cb, apolloClient) {
this.handleAuthentication()
// binds functions to keep this context
this.apolloClient = apolloClient
this.cb = cb.bind(this)
this.login = this.login.bind(this)
this.logout = this.logout.bind(this)
this.isAuthenticated = this.isAuthenticated.bind(this)
this.checkSession = this.checkSession.bind(this)
}
login () {
// Call the show method to display the widget.
lock.show()
}
handleAuthentication () {
// Add a callback for Lock's `authenticated` event
lock.on('authenticated', this.setSession.bind(this))
// Add a callback for Lock's `authorization_error` event
lock.on('authorization_error', err => {
console.log(err)
const data = { status: `error`, errMessage: err.error }
this.cb(data)
})
}
checkSession () {
return new Promise((resolve, reject) => {
// Add a callback for Lock's `authenticated` event
lock.checkSession(
{
responseType: 'token id_token',
audience: AUTH_CONFIG.api_audience,
scope:
'openid email profile read:teams write:teams read:member write:member',
connection: 'github',
prompt: 'none'
},
function (err, authResult) {
if (!err) {
resolve(authResult)
} else {
reject(err)
}
}
)
})
}
setSession (authResult) {
console.log('setSession')
if (authResult && authResult.accessToken && authResult.idToken) {
// Set the time that the access token will expire at
let expiresAt = JSON.stringify(
authResult.expiresIn * 1000 + new Date().getTime()
)
setItem('access_token', authResult.accessToken)
setItem('id_token', authResult.idToken)
setItem('expires_at', expiresAt)
const data = {
status: `success`,
accessToken: authResult.accessToken,
idToken: authResult.idToken,
expiresAt
}
console.log('setSession idTokenPayload: ', authResult.idTokenPayload)
this.signinOrCreateAccount({ ...data })
this.cb(data)
console.log(authResult.idTokenPayload)
setItem('user', JSON.stringify(authResult.idTokenPayload))
if (window.location.href.includes(`callback`)) {
window.location.href = '/'
}
return true
}
}
async signinOrCreateAccount ({ accessToken, idToken, expiresAt }) {
console.log(
'signinOrCreateAccount: ',
client,
this.apolloClient,
accessToken,
idToken,
expiresAt
)
try {
const data = await client.mutate({
mutation: AUTHENTICATE,
variables: { idToken }
})
console.log('signinOrCreateAccount auth: ', await data)
setItem('user', data.data.authenticate.auth0id)
if (window.location.href.includes(`callback`)) {
window.location.href = '/'
} else {
window.location.reload()
}
return data
} catch (err) {
return console.log('Sign in or create account error: ', err)
}
}
logout () {
// Clear access token and ID token from local storage
removeItem('access_token')
removeItem('id_token')
removeItem('expires_at')
removeItem('user')
removeItem('auth0.ssodata')
window.localStorage.clear()
deleteCookie('ajs_anonymous_id')
deleteCookie('ajs_user_id')
deleteCookie('current_tenant')
lock.logout({ returnTo: AUTH_CONFIG.logoutUrl })
console.log('logout')
}
async isAuthenticated () {
// check session and run Auth0 SS0
const getUser = await getItem('user')
let user = JSON.parse(getUser)
if (validObject(user, 'exp') && new Date().getTime() < (user.exp * 1000)) {
console.log('handleAuth.user exp: ', user, window.location.href)
return user
}
const checkSSO = await this.checkSession()
.then(result => {
console.log('handleAuth.checksessions: ', result)
setItem('user', result.idTokenPayload.sub)
// user confirmed, log into client
this.setSession(result)
return result.idTokenPayload
})
.catch(err => {
console.log('handleAuth.checksessions err: ', err)
if (err.error === 'login_required') {
// return this.login()
}
return err
})
if (
(window.location.href.includes(`manage`) ||
window.location.href.includes(`profile`)) &&
!user
) {
window.location.href = '/'
}
if (/manage|profile|create|dashboard/.test(window.location.href) && !user) {
this.login()
}
console.log('handleAuth.isAuthenticated 2: ', checkSSO, user)
if (validObject(checkSSO, 'error')) {
return false
} else {
return checkSSO
}
}
}
export default Auth
+60
View File
@@ -0,0 +1,60 @@
export function isDefined (d) {
return d !== null && typeof d !== 'undefined'
}
export function isNotDefined (d) {
return !isDefined(d)
}
export const isArray = Array.isArray
export function isObject (d) {
return isDefined(d) && typeof d === 'object' && !Array.isArray(d)
}
export function isEmpty (obj) {
for (var key in obj) {
if (obj.hasOwnProperty(key)) return false
}
return true
}
export function validObject (object, ...keys) {
return keys.reduce((a, b) => (a || { })[b], object) !== undefined
}
export function mergeDeep (target, ...sources) {
if (!sources.length) return target
const source = sources.shift()
if (isObject(target) && isObject(source)) {
for (const key in source) {
if (isObject(source[key])) {
if (!target[key]) Object.assign(target, { [key]: {} })
mergeDeep(target[key], source[key])
} else {
Object.assign(target, { [key]: source[key] })
}
}
}
return mergeDeep(target, ...sources)
}
export function deleteCookie (c) {
document.cookie.split(';').forEach(function (c) { document.cookie = c.replace(/^ +/, '').replace(/=.*/, '=;expires=' + new Date().toUTCString() + ';path=/') })
}
export function slugify (string) {
const a = 'àáäâãåèéëêìíïîòóöôùúüûñçßÿœæŕśńṕẃǵǹḿǘẍźḧ·/_,:;'
const b = 'aaaaaaeeeeiiiioooouuuuncsyoarsnpwgnmuxzh------'
const p = new RegExp(a.split('').join('|'), 'g')
return string.toString().toLowerCase()
.replace(/\s+/g, '-') // Replace spaces with -
.replace(p, c => b.charAt(a.indexOf(c))) // Replace special characters
.replace(/&/g, '-and-') // Replace & with 'and'
.replace(/[^\w-]+/g, '') // Remove all non-word characters
.replace(/--+/g, '-') // Replace multiple - with single -
.replace(/^-+/, '') // Trim - from start of text
.replace(/-+$/, '') // Trim - from end of text
}
+35
View File
@@ -0,0 +1,35 @@
const getStateFromStorage = version => {
const localState = JSON.parse(window.localStorage.getItem('aa-team'))
try {
if (localState !== undefined && localState !== null) {
if (
localState.appVersion !== undefined &&
localState.appVersion !== null
) {
if (localState.appVersion === version) {
return localState
}
}
} else {
throw new Error()
}
} catch (error) {
return false
}
}
const storeStateInStorage = state =>
window.localStorage.setItem('aa-team', JSON.stringify(state))
const getItem = async name => window.localStorage.getItem(name)
const setItem = async (name, value) => window.localStorage.setItem(name, value)
const removeItem = async name => window.localStorage.removeItem(name)
export {
getStateFromStorage,
storeStateInStorage,
getItem,
setItem,
removeItem
}
+13
View File
@@ -0,0 +1,13 @@
import React, { Component } from 'react'
class Callback extends Component {
render() {
return (
<div>
Authenticating...
</div>
)
}
}
export default Callback
+4 -2
View File
@@ -1,13 +1,14 @@
import React, { Component } from 'react';
import {graphql} from 'react-apollo';
import {getUserByAuthIdQuery} from '../queries/queries';
import {auth} from '../App';
class LoggedInUser extends Component {
displayLoggedInUser(){
const user = this.props.data.userByAuthId;
console.log(this.props);
if(user){
if (user.firstName) {
return(
@@ -24,7 +25,8 @@ class LoggedInUser extends Component {
}
} else {
return( <div>Login / Sign up</div> );
console.log(auth);
return( <div onClick={() => auth.login()}>Login / Sign up</div> );
}
}
@@ -62,7 +62,7 @@ function ButtonAppBar(props) {
<IconButton className={classes.menuButton} color="inherit" title="About this Module" component={AboutLink}><AboutIcon /></IconButton>
<IconButton className={classes.menuButton} color="inherit" title="Go to another Module" component={AboutLink}><ModulesIcon /></IconButton>
<LoggedInUser authId="2"/>
<LoggedInUser authId="999"/>
</Toolbar>
</AppBar>
</div>
@@ -37,6 +37,7 @@ const styles = theme => ({
class ProfileTabs extends React.Component {
state = {
value: 0,
cureateDisabled: "false"
};
handleChange = (event, value) => {
@@ -44,12 +45,14 @@ class ProfileTabs extends React.Component {
};
updateUser = () => {
this.setState({ value: 1 });
this.setState({ value: 1, cureateDisabled: "true" });
};
render() {
const { classes } = this.props;
const { value } = this.state;
const { createDisabled } = this.state;
console.log(createDisabled);
return (
<div className={classes.root}>
@@ -62,7 +65,8 @@ class ProfileTabs extends React.Component {
indicatorColor="primary"
textColor="primary"
>
<Tab label="Create Profile" icon={<AddIcon />} />
<Tab label="Create Profile" icon={<AddIcon />} />
<Tab disabled={createDisabled} label="Create Profile" icon={<AddIcon />} />
<Tab label="Update Profile" icon={<UpdateIcon />} />
<Tab label="Manage Images" icon={<ImageIcon />} />
</Tabs>