├── .gitignore ├── client ├── dev-client.js ├── promise-polyfill.js ├── views │ ├── SignOut.vue │ ├── Home.vue │ ├── Profile.vue │ └── SignIn.vue ├── index.js ├── components │ ├── App.vue │ └── Navigation.vue ├── pwa.js ├── app.js ├── store │ └── index.js ├── FirebaseAuthPlugin.js └── router │ └── index.js ├── static └── favicon.ico ├── .eslintrc ├── .editorconfig ├── README.md └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | .DS_Store 4 | /dist 5 | -------------------------------------------------------------------------------- /client/dev-client.js: -------------------------------------------------------------------------------- 1 | import 'webpack-dev-server/client?/' 2 | import 'webpack/hot/dev-server' 3 | -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michalbujalski/firebase-auth-demo/HEAD/static/favicon.ico -------------------------------------------------------------------------------- /client/promise-polyfill.js: -------------------------------------------------------------------------------- 1 | import Promise from 'promise-polyfill' 2 | 3 | window.Promise = window.Promise || Promise 4 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "vue", 3 | "rules": { 4 | "import/no-unresolved": 0, 5 | "import/no-unassigned-import": 0 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /client/views/SignOut.vue: -------------------------------------------------------------------------------- 1 | 4 | 12 | -------------------------------------------------------------------------------- /client/index.js: -------------------------------------------------------------------------------- 1 | import './promise-polyfill' 2 | import { app } from './app' 3 | 4 | // Enable progressive web app support (with offline-plugin) 5 | if (process.env.NODE_ENV === 'production') { 6 | require('./pwa') 7 | } 8 | 9 | app.$mount('#app') 10 | -------------------------------------------------------------------------------- /client/views/Home.vue: -------------------------------------------------------------------------------- 1 | 7 | 18 | -------------------------------------------------------------------------------- /client/components/App.vue: -------------------------------------------------------------------------------- 1 | 7 | 15 | 16 | 18 | -------------------------------------------------------------------------------- /client/views/Profile.vue: -------------------------------------------------------------------------------- 1 | 7 | 18 | -------------------------------------------------------------------------------- /client/pwa.js: -------------------------------------------------------------------------------- 1 | import runtime from 'offline-plugin/runtime' 2 | 3 | runtime.install({ 4 | // When an update is ready, tell ServiceWorker to take control immediately: 5 | onUpdateReady () { 6 | console.log('update ready') 7 | runtime.applyUpdate() 8 | }, 9 | 10 | // Reload to get the new version: 11 | onUpdated () { 12 | console.log('updated') 13 | location.reload() 14 | } 15 | }) 16 | -------------------------------------------------------------------------------- /client/app.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import { sync } from 'vuex-router-sync' 3 | import App from './components/App' 4 | import router from './router' 5 | import store from './store' 6 | import FirebaseAuthPlugin from './FirebaseAuthPlugin' 7 | 8 | Vue.use(FirebaseAuthPlugin) 9 | 10 | sync(store, router) 11 | 12 | const app = new Vue({ 13 | router, 14 | store, 15 | ...App 16 | }) 17 | 18 | export { app, router, store } 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Firebase auth with vue demo 2 | 3 | ## Overview 4 | 5 | This is a demonstration of how to integrate Firebase Auth into Vue+Vuex project. 6 | Check out my Medium post for more details: 7 | https://medium.com/@MichalBujalski/reactive-firebase-auth-with-vue-92577ab78ff6 8 | 9 | ## Running code 10 | 11 | To start: 12 | 13 | ```bash 14 | $ yarn install 15 | ``` 16 | 17 | To develop: 18 | 19 | ```bash 20 | $ yarn dev 21 | ``` 22 | 23 | -------------------------------------------------------------------------------- /client/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | Vue.use(Vuex) 5 | 6 | const state = { 7 | user: null 8 | } 9 | 10 | const mutations = { 11 | updateUser (state, { user }) { 12 | Vue.set(state, 'user', user) 13 | } 14 | } 15 | const actions = { 16 | } 17 | 18 | const getters = { 19 | user: state => state.user 20 | } 21 | const store = new Vuex.Store({ 22 | state, 23 | mutations, 24 | actions, 25 | getters 26 | }) 27 | 28 | export default store 29 | -------------------------------------------------------------------------------- /client/components/Navigation.vue: -------------------------------------------------------------------------------- 1 | 9 | 17 | 18 | -------------------------------------------------------------------------------- /client/FirebaseAuthPlugin.js: -------------------------------------------------------------------------------- 1 | import store from './store' 2 | import Firebase from 'firebase' 3 | 4 | const config = { 5 | apiKey: 6 | authDomain: , 7 | databaseURL: , 8 | projectId: , 9 | storageBucket: , 10 | messagingSenderId: 11 | } 12 | 13 | export default { 14 | install: (Vue, options) => { 15 | const firebase = Firebase.initializeApp(config) 16 | const auth = firebase.auth() 17 | Vue.prototype.$auth = { 18 | login: async (username, pass) => { 19 | return await auth.signInWithEmailAndPassword(username, pass) 20 | }, 21 | logout: async () => { 22 | await auth.signOut() 23 | } 24 | } 25 | auth.onAuthStateChanged(user => { 26 | store.commit('updateUser',{ user }) 27 | }) 28 | } 29 | } 30 | 31 | -------------------------------------------------------------------------------- /client/views/SignIn.vue: -------------------------------------------------------------------------------- 1 | 8 | 37 | 38 | -------------------------------------------------------------------------------- /client/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Home from '../views/Home' 4 | import SignIn from '../views/SignIn' 5 | import SignOut from '../views/SignOut' 6 | import Profile from '../views/Profile' 7 | import store from '../store' 8 | 9 | Vue.use(Router) 10 | 11 | const router = new Router({ 12 | mode: 'history', 13 | routes: [ 14 | { 15 | path: '/', 16 | name: 'home', 17 | component: Home 18 | }, 19 | { 20 | path: '/signin', 21 | name: 'signin', 22 | component: SignIn 23 | }, 24 | { 25 | path: '/signout', 26 | name: 'signout', 27 | component: SignOut 28 | }, 29 | { 30 | path: '/profile', 31 | name: 'profile', 32 | component: Profile, 33 | meta: { 34 | authRequired: true 35 | } 36 | } 37 | ] 38 | }) 39 | 40 | router.beforeEach((to, from, next) => { 41 | if (to.matched.some(record => record.meta.authRequired)) { 42 | if (!store.state.user) { 43 | next({ 44 | path: '/signin', 45 | query: { redirect: to.fullPath } 46 | }) 47 | } else { 48 | next() 49 | } 50 | } else { 51 | next() 52 | } 53 | }) 54 | 55 | export default router 56 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "firebase-auth-demo", 3 | "version": "0.1.0", 4 | "description": "This is an example implementation of Vue+Vuex+Firebase-Auth", 5 | "main": "client/index.js", 6 | "scripts": { 7 | "test": "", 8 | "build": "webpack --config build/webpack.prod.js", 9 | "dev": "node build/server.js", 10 | "lint": "xo **/client/**/*.{vue,js} !node_modules/**" 11 | }, 12 | "author": "Michał Bujalski ", 13 | "license": "MIT", 14 | "xo": { 15 | "extends": "./.eslintrc", 16 | "esnext": true, 17 | "envs": [ 18 | "browser" 19 | ] 20 | }, 21 | "babel": { 22 | "presets": [ 23 | [ 24 | "vue-app", 25 | { 26 | "useBuiltIns": true 27 | } 28 | ] 29 | ] 30 | }, 31 | "postcss": { 32 | "plugins": { 33 | "autoprefixer": {}, 34 | "postcss-nested": {} 35 | } 36 | }, 37 | "browserslist": [ 38 | "last 2 versions", 39 | "ie > 8" 40 | ], 41 | "dependencies": { 42 | "babel-runtime": "^6.18.0", 43 | "firebase": "^4.12.1", 44 | "promise-polyfill": "^6.0.2", 45 | "vue": "^2.2.0", 46 | "vue-router": "^2.0.0", 47 | "vuex": "^2.0.0", 48 | "vuex-router-sync": "^4.0.0" 49 | }, 50 | "devDependencies": { 51 | "autoprefixer": "^6.4.0", 52 | "babel-core": "^6.16.0", 53 | "babel-loader": "^6.2.4", 54 | "babel-preset-vue-app": "^1.1.1", 55 | "chalk": "^1.1.3", 56 | "copy-webpack-plugin": "^4.0.1", 57 | "cross-env": "^2.0.0", 58 | "css-loader": "^0.23.1", 59 | "eslint-config-vue": "latest", 60 | "eslint-plugin-vue": "latest", 61 | "express": "^4.14.0", 62 | "extract-text-webpack-plugin": "^2.0.0-rc.3", 63 | "file-loader": "^0.9.0", 64 | "friendly-errors-webpack-plugin": "^1.1.2", 65 | "html-webpack-plugin": "^3.2.0", 66 | "offline-plugin": "^4.5.3", 67 | "postcss-loader": "^0.9.1", 68 | "postcss-nested": "^1.0.0", 69 | "raw-loader": "^0.5.1", 70 | "rimraf": "^2.6.1", 71 | "style-loader": "^0.13.1", 72 | "vue-loader": "^11.0.0", 73 | "vue-template-compiler": "^2.2.0", 74 | "webpack": "2.2.0", 75 | "webpack-dev-server": "^2.6.1", 76 | "xo": "^0.18.0" 77 | } 78 | } 79 | --------------------------------------------------------------------------------