├── .nvmrc ├── static ├── favicon.ico └── README.md ├── middleware ├── vuex-oidc-router.js └── README.md ├── pages ├── oidc-callback-error.vue ├── index.vue ├── oidc-callback.vue └── protected.vue ├── .editorconfig ├── layouts ├── README.md └── default.vue ├── .eslintrc.js ├── config └── oidc.js ├── store ├── README.md └── oidc.js ├── README.md ├── server └── index.js ├── package.json ├── nuxt.config.js ├── .gitignore └── components └── SignedInUser.vue /.nvmrc: -------------------------------------------------------------------------------- 1 | v8.11.1 2 | -------------------------------------------------------------------------------- /static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/perarnborg/vuex-oidc-example-nuxt/HEAD/static/favicon.ico -------------------------------------------------------------------------------- /middleware/vuex-oidc-router.js: -------------------------------------------------------------------------------- 1 | import { vuexOidcCreateNuxtRouterMiddleware } from 'vuex-oidc' 2 | 3 | export default vuexOidcCreateNuxtRouterMiddleware('oidc') 4 | -------------------------------------------------------------------------------- /pages/oidc-callback-error.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /layouts/README.md: -------------------------------------------------------------------------------- 1 | # LAYOUTS 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your Application Layouts. 6 | 7 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/views#layouts). 8 | -------------------------------------------------------------------------------- /pages/index.vue: -------------------------------------------------------------------------------- 1 | 9 | 10 | 19 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | browser: true, 5 | node: true 6 | }, 7 | parserOptions: { 8 | parser: 'babel-eslint' 9 | }, 10 | extends: [ 11 | '@nuxtjs', 12 | 'plugin:nuxt/recommended' 13 | ], 14 | // add your custom rules here 15 | rules: { 16 | 'nuxt/no-cjs-in-config': 'off', 17 | 'no-console': 'off' 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /config/oidc.js: -------------------------------------------------------------------------------- 1 | export const oidcSettings = { 2 | authority: 'https://accounts.google.com', 3 | clientId: '459300396575-3ruj8l8jn69pcgst8rgkqnk6g43gbc78.apps.googleusercontent.com', 4 | redirectUri: 'http://localhost:3000/oidc-callback', 5 | responseType: 'id_token token', 6 | scope: 'openid email', 7 | automaticSilentRenew: true, 8 | silentRedirectUri: 'http://localhost:3000/silent-renew-oidc.html' 9 | } 10 | -------------------------------------------------------------------------------- /middleware/README.md: -------------------------------------------------------------------------------- 1 | # MIDDLEWARE 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your application middleware. 6 | Middleware let you define custom functions that can be run before rendering either a page or a group of pages. 7 | 8 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing#middleware). 9 | -------------------------------------------------------------------------------- /store/README.md: -------------------------------------------------------------------------------- 1 | # STORE 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your Vuex Store files. 6 | Vuex Store option is implemented in the Nuxt.js framework. 7 | 8 | Creating a file in this directory automatically activates the option in the framework. 9 | 10 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/vuex-store). 11 | -------------------------------------------------------------------------------- /static/README.md: -------------------------------------------------------------------------------- 1 | # STATIC 2 | 3 | **This directory is not required, you can delete it if you don't want to use it.** 4 | 5 | This directory contains your static files. 6 | Each file inside this directory is mapped to `/`. 7 | Thus you'd want to delete this README.md before deploying to production. 8 | 9 | Example: `/static/robots.txt` is mapped as `/robots.txt`. 10 | 11 | More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#static). 12 | -------------------------------------------------------------------------------- /pages/oidc-callback.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 29 | -------------------------------------------------------------------------------- /pages/protected.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vuex-oidc-example-nuxt 2 | 3 | An example of how to use [vuex-oidc](https://github.com/perarnborg/vuex-oidc) with Nuxt. 4 | 5 | vuex-oidc supports Nuxt from v2.0. Not tested with Nuxt v3. 6 | 7 | > :warning: **NOTICE**: vuex-oidc v4 introduces some breaking changes (such as dropping support for the implicit flow). This example uses v3. 8 | 9 | ## Build Setup 10 | 11 | ``` bash 12 | # install dependencies 13 | $ npm install 14 | 15 | # serve with hot reload at localhost:3000 16 | $ npm run dev 17 | 18 | # build for production and launch server 19 | $ npm run build 20 | $ npm start 21 | 22 | # generate static project 23 | $ npm run generate 24 | ``` 25 | 26 | For detailed explanation on how things work, checkout [Nuxt.js docs](https://nuxtjs.org). 27 | -------------------------------------------------------------------------------- /server/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const consola = require('consola') 3 | const { Nuxt, Builder } = require('nuxt') 4 | const app = express() 5 | 6 | // Import and Set Nuxt.js options 7 | const config = require('../nuxt.config.js') 8 | config.dev = !(process.env.NODE_ENV === 'production') 9 | 10 | async function start() { 11 | // Init Nuxt.js 12 | const nuxt = new Nuxt(config) 13 | 14 | const { host, port } = nuxt.options.server 15 | 16 | // Build only in dev mode 17 | if (config.dev) { 18 | const builder = new Builder(nuxt) 19 | await builder.build() 20 | } else { 21 | await nuxt.ready() 22 | } 23 | 24 | // Give nuxt middleware to express 25 | app.use(nuxt.render) 26 | 27 | // Listen the server 28 | app.listen(port, host) 29 | consola.ready({ 30 | message: `Server listening on http://${host}:${port}`, 31 | badge: true 32 | }) 33 | } 34 | start() 35 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vuex-oidc-example-nuxt", 3 | "version": "1.0.0", 4 | "description": "", 5 | "author": "Per Arnborg", 6 | "private": true, 7 | "scripts": { 8 | "dev": "cross-env NODE_ENV=development nodemon server/index.js --watch server", 9 | "build": "nuxt build", 10 | "start": "cross-env NODE_ENV=production node server/index.js", 11 | "generate": "nuxt generate", 12 | "lint": "eslint --ext .js,.vue --ignore-path .gitignore .", 13 | "precommit": "npm run lint" 14 | }, 15 | "dependencies": { 16 | "cross-env": "^5.2.0", 17 | "express": "^4.16.4", 18 | "json-markup": "^1.1.3", 19 | "nuxt": "^2.4.0", 20 | "vuex-oidc": "^2.0.3" 21 | }, 22 | "devDependencies": { 23 | "nodemon": "^1.18.9", 24 | "@nuxtjs/eslint-config": "^0.0.1", 25 | "babel-eslint": "^10.0.1", 26 | "eslint": "^5.15.1", 27 | "eslint-config-standard": ">=12.0.0", 28 | "eslint-plugin-import": ">=2.16.0", 29 | "eslint-plugin-jest": ">=22.3.0", 30 | "eslint-plugin-node": ">=8.0.1", 31 | "eslint-plugin-nuxt": ">=0.4.2", 32 | "eslint-plugin-promise": ">=4.0.1", 33 | "eslint-plugin-standard": ">=4.0.0", 34 | "eslint-loader": "^2.1.2", 35 | "eslint-plugin-vue": "^5.2.2" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /nuxt.config.js: -------------------------------------------------------------------------------- 1 | const pkg = require('./package') 2 | 3 | module.exports = { 4 | mode: 'spa', 5 | 6 | /* 7 | ** Headers of the page 8 | */ 9 | head: { 10 | title: pkg.name, 11 | meta: [ 12 | { charset: 'utf-8' }, 13 | { name: 'viewport', content: 'width=device-width, initial-scale=1' }, 14 | { hid: 'description', name: 'description', content: pkg.description } 15 | ], 16 | link: [ 17 | { rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' } 18 | ] 19 | }, 20 | 21 | /* 22 | ** Customize the progress-bar color 23 | */ 24 | loading: { color: '#fff' }, 25 | 26 | /* 27 | ** Global CSS 28 | */ 29 | css: [ 30 | ], 31 | 32 | /* 33 | ** Plugins to load before mounting the App 34 | */ 35 | plugins: [ 36 | ], 37 | 38 | /* 39 | ** Nuxt.js modules 40 | */ 41 | modules: [ 42 | ], 43 | 44 | /* 45 | ** Build configuration 46 | */ 47 | build: { 48 | /* 49 | ** You can extend webpack config here 50 | */ 51 | extend(config, ctx) { 52 | // Run ESLint on save 53 | if (ctx.isDev && ctx.isClient) { 54 | config.module.rules.push({ 55 | enforce: 'pre', 56 | test: /\.(js|vue)$/, 57 | loader: 'eslint-loader', 58 | exclude: /(node_modules)/ 59 | }) 60 | } 61 | } 62 | }, 63 | 64 | router: { 65 | middleware: 'vuex-oidc-router' 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /layouts/default.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 47 | 48 | 69 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Node template 3 | # Logs 4 | logs 5 | *.log 6 | npm-debug.log* 7 | yarn-debug.log* 8 | yarn-error.log* 9 | 10 | # Runtime data 11 | pids 12 | *.pid 13 | *.seed 14 | *.pid.lock 15 | 16 | # Directory for instrumented libs generated by jscoverage/JSCover 17 | lib-cov 18 | 19 | # Coverage directory used by tools like istanbul 20 | coverage 21 | 22 | # nyc test coverage 23 | .nyc_output 24 | 25 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 26 | .grunt 27 | 28 | # Bower dependency directory (https://bower.io/) 29 | bower_components 30 | 31 | # node-waf configuration 32 | .lock-wscript 33 | 34 | # Compiled binary addons (https://nodejs.org/api/addons.html) 35 | build/Release 36 | 37 | # Dependency directories 38 | node_modules/ 39 | jspm_packages/ 40 | 41 | # TypeScript v1 declaration files 42 | typings/ 43 | 44 | # Optional npm cache directory 45 | .npm 46 | 47 | # Optional eslint cache 48 | .eslintcache 49 | 50 | # Optional REPL history 51 | .node_repl_history 52 | 53 | # Output of 'npm pack' 54 | *.tgz 55 | 56 | # Yarn Integrity file 57 | .yarn-integrity 58 | 59 | # dotenv environment variables file 60 | .env 61 | 62 | # parcel-bundler cache (https://parceljs.org/) 63 | .cache 64 | 65 | # next.js build output 66 | .next 67 | 68 | # nuxt.js build output 69 | .nuxt 70 | 71 | # Nuxt generate 72 | dist 73 | 74 | # vuepress build output 75 | .vuepress/dist 76 | 77 | # Serverless directories 78 | .serverless 79 | 80 | # IDE 81 | .idea 82 | 83 | # Service worker 84 | sw.* 85 | -------------------------------------------------------------------------------- /store/oidc.js: -------------------------------------------------------------------------------- 1 | import { vuexOidcCreateStoreModule } from 'vuex-oidc' 2 | import { oidcSettings } from '../config/oidc' 3 | // NOTE: If you want to customize how tokens are stored you can use WebStorageStateStore from oidc-client (see bellow) 4 | // Default storage is window.localStorage 5 | // import { WebStorageStateStore } from 'oidc-client' 6 | 7 | const storeModule = vuexOidcCreateStoreModule( 8 | oidcSettings, 9 | // NOTE: If you do not want to use localStorage for tokens, in stead of just passing oidcSettings, you can 10 | // spread your oidcSettings and define a userStore of your choice 11 | // { 12 | // ...oidcSettings, 13 | // userStore: new WebStorageStateStore({ store: window.sessionStorage }) 14 | // }, 15 | // Optional OIDC store settings 16 | { 17 | namespaced: true, 18 | dispatchEventsOnWindow: true, 19 | publicRoutePaths: ['/', 'oidc-callback-error'] 20 | }, 21 | // Optional OIDC event listeners 22 | { 23 | userLoaded: user => console.log('OIDC user is loaded:', user), 24 | userUnloaded: () => console.log('OIDC user is unloaded'), 25 | accessTokenExpiring: () => console.log('Access token will expire'), 26 | accessTokenExpired: () => console.log('Access token did expire'), 27 | silentRenewError: () => console.log('OIDC user is unloaded'), 28 | userSignedOut: () => console.log('OIDC user is signed out') 29 | } 30 | ) 31 | 32 | export const state = () => (storeModule.state) 33 | 34 | export const getters = storeModule.getters 35 | 36 | export const actions = storeModule.actions 37 | 38 | export const mutations = storeModule.mutations 39 | -------------------------------------------------------------------------------- /components/SignedInUser.vue: -------------------------------------------------------------------------------- 1 |