Syncing Lots Of Auth Tweaks

This commit is contained in:
Annika Merris 2024-02-10 17:33:57 -05:00
parent baf8e0f954
commit a1aa171bb1
11 changed files with 227 additions and 28 deletions

BIN
bun.lockb

Binary file not shown.

View file

@ -14,6 +14,7 @@
"format": "prettier --write src/"
},
"dependencies": {
"@zitadel/vue": "^1.0.0",
"axios": "^1.6.5",
"axios-retry": "^4.0.0",
"pinia": "^2.1.7",

View file

@ -1,3 +1,3 @@
{
"apiBaseUrl": "http://localhost:3000"
"apiBaseURL": "http://localhost:3000"
}

View file

@ -13,6 +13,8 @@ import { createVuetify } from 'vuetify'
import * as components from 'vuetify/components'
import * as directives from 'vuetify/directives'
import axios from 'axios'
import zitadelAuth from '@/services/zitadelAuth'
import { apiBaseURL } from './types/ConfigSymbols'
const vuetify = createVuetify({
components,
@ -25,20 +27,32 @@ const vuetify = createVuetify({
}
})
const app = createApp(App)
const pinia = createPinia()
app.use(pinia)
app.use(router)
app.use(vuetify)
// Stuff to get OIDC auth working through Zitadel
declare module 'vue' {
interface ComponentCustomProperties {
$zitadel: typeof zitadelAuth
}
}
// Fetch my config
axios
.get('/config.json?noCache=' + Date.now())
.then((resp) => {
app.config.globalProperties.$apiBaseUrl = resp.data.apiBaseUrl
zitadelAuth.oidcAuth.startup().then(() => {
const app = createApp(App)
const pinia = createPinia()
app.mount('#app')
})
.catch((err) => {
console.log(err)
})
app.use(router)
app.use(vuetify)
app.use(pinia)
app.config.globalProperties.$zitadel = zitadelAuth
// Fetch my config
axios
.get('/config.json?noCache=' + Date.now())
.then((resp) => {
app.provide(apiBaseURL, resp.data.apiBaseURL)
app.mount('#app')
})
.catch((err) => {
console.log(err)
})
})

View file

@ -1,3 +1,4 @@
import zitadelAuth from '@/services/zitadelAuth'
import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({
@ -9,26 +10,46 @@ const router = createRouter({
component: () => import('@/views/HomeView.vue')
},
{
path: "/blessing-power",
name: "blessing-power",
path: '/blessing-power',
name: 'blessing-power',
component: () => import('@/views/BlessingPowerView.vue')
},
{
path: "/fellow-power",
name: "fellow-power",
path: '/fellow-power',
name: 'fellow-power',
component: () => import('@/views/FellowPowerView.vue')
},
{
path: "/intimacy-power",
name: "intimacy-power",
path: '/intimacy-power',
name: 'intimacy-power',
component: () => import('@/views/IntimacyPowerView.vue')
},
{
path: "/test",
name: "test",
path: '/test',
name: 'test',
component: () => import('@/views/Test.vue')
},
{
path: '/login',
name: 'login',
meta: {
authName: zitadelAuth.oidcAuth.authName
},
component: () => import('@/views/Login.vue')
},
{
path: '/admin',
name: 'admin',
meta: {
authName: zitadelAuth.oidcAuth.authName
},
component: () =>
zitadelAuth.hasRole('admin') ? import('@/views/Admin.vue') : import('@/views/NoAccess.vue')
}
]
})
zitadelAuth.oidcAuth.useRouter(router)
export default router

View file

@ -0,0 +1,46 @@
import {createZITADELAuth} from "@zitadel/vue";
import {User} from "oidc-client";
const zitadelAuth = createZITADELAuth({
project_resource_id: '252968011466539011',
client_id: "252968365600079875@isl",
issuer: "http://localhost:8080/",
})
// handle events
zitadelAuth.oidcAuth.events.addAccessTokenExpiring(function() {
// eslint-disable-next-line no-console
console.log('access token expiring')
})
zitadelAuth.oidcAuth.events.addAccessTokenExpired(function() {
// eslint-disable-next-line no-console
console.log('access token expired')
})
zitadelAuth.oidcAuth.events.addSilentRenewError(function(err: Error) {
// eslint-disable-next-line no-console
console.error('silent renew error', err)
})
zitadelAuth.oidcAuth.events.addUserLoaded(function(user: User) {
// eslint-disable-next-line no-console
console.log('user loaded', user)
})
zitadelAuth.oidcAuth.events.addUserUnloaded(function() {
// eslint-disable-next-line no-console
console.log('user unloaded')
})
zitadelAuth.oidcAuth.events.addUserSignedOut(function() {
// eslint-disable-next-line no-console
console.log('user signed out')
})
zitadelAuth.oidcAuth.events.addUserSessionChanged(function() {
// eslint-disable-next-line no-console
console.log('user session changed')
})
export default zitadelAuth

View file

@ -4,6 +4,8 @@ import { defineStore } from 'pinia'
import { computed, ref, toRaw } from 'vue'
import axiosRetry from 'axios-retry'
import { getCurrentInstance } from 'vue'
import { apiBaseURL as apiBaseURLKey } from '@/types/ConfigSymbols'
import { inject } from 'vue'
const BLESSING = 1
const INTIMACY = 2
@ -26,7 +28,9 @@ export const usePowerItems = defineStore('powerItems', () => {
const fellowPowerItems = ref(new Map<string, PowerItem>())
const intimacyPowerItems = ref(new Map<string, PowerItem>())
const isLoadComplete = ref(false)
const apiBaseUrl = getCurrentInstance()?.appContext.config.globalProperties.$apiBaseUrl
const auth = getCurrentInstance()?.appContext.config.globalProperties.$zitadel
auth?.oidcAuth.mgr.getUser().then(res => console.log(res?.id_token))
console.log(auth?.oidcAuth.accessToken)
axiosRetry(axios, {
retries: 3,
@ -34,8 +38,9 @@ export const usePowerItems = defineStore('powerItems', () => {
})
async function fetchPowerItems() {
const apiBaseURL = inject(apiBaseURLKey)
axios
.get(apiBaseUrl + '/powerItem/byType/' + BLESSING + '/asMap', noCacheConfig)
.get(apiBaseURL + '/powerItems/byType/' + BLESSING + '/asMap', noCacheConfig)
.then((resp) => {
const plainMap = new Map<string, PowerItem>(
Object.entries(JSON.parse(localStorage.getItem(BLESSING_POWER_ITEM_STORAGE) || '{}'))
@ -51,7 +56,7 @@ export const usePowerItems = defineStore('powerItems', () => {
console.log(err)
})
axios
.get(apiBaseUrl + '/powerItem/byType/' + FELLOW + '/asMap', noCacheConfig)
.get(apiBaseURL + '/powerItems/byType/' + FELLOW + '/asMap', noCacheConfig)
.then((resp) => {
const plainMap = new Map<string, PowerItem>(
Object.entries(JSON.parse(localStorage.getItem(FELLOW_POWER_ITEM_STORAGE) || '{}'))
@ -67,7 +72,7 @@ export const usePowerItems = defineStore('powerItems', () => {
console.log(err)
})
axios
.get(apiBaseUrl + '/powerItem/byType/' + INTIMACY + '/asMap', noCacheConfig)
.get(apiBaseURL + '/powerItems/byType/' + INTIMACY + '/asMap', noCacheConfig)
.then((resp) => {
const plainMap = new Map<string, PowerItem>(
Object.entries(JSON.parse(localStorage.getItem(INTIMACY_POWER_ITEM_STORAGE) || '{}'))

View file

@ -0,0 +1,7 @@
import type { InjectionKey } from "vue";
const apiBaseURL = Symbol() as InjectionKey<string>
export {
apiBaseURL
}

22
src/views/Admin.vue Normal file
View file

@ -0,0 +1,22 @@
<template>
<div class="admin">
<div>
<h1>
This is an administrator page.
</h1>
<h2>
You can see it because you have the role "admin" in your ZITADEL project.
</h2>
</div>
</div>
</template>
<style>
@media (min-width: 1024px) {
.admin {
min-height: 100vh;
display: flex;
align-items: center;
}
}
</style>

61
src/views/Login.vue Normal file
View file

@ -0,0 +1,61 @@
<template>
<div class="userinfo">
<div>
<h1>This is a login-protected page</h1>
<h2>
The following profile data is extended by information from ZITADELs userinfo endpoint.
</h2>
<p>
<ul class="claims">
<li v-for="c in claims" :key="c.key">
<strong>{{ c.key }}</strong
>: {{ c.value }}
</li>
</ul>
</p>
</div>
<button @click="signout">Sign Out</button>
</div>
</template>
<style>
@media (min-width: 1024px) {
.userinfo {
min-height: 100vh;
display: flex;
align-items: center;
}
}
</style>
<script lang="ts">
import { getCurrentInstance } from 'vue';
import { ref } from 'vue';
import { defineComponent } from 'vue'
export default defineComponent({
computed: {
user() {
return this.$zitadel.oidcAuth.userProfile
},
claims() {
if (this.user) {
return Object.keys(this.user).map((key) => ({
key,
value: this.user[key]
}))
}
return []
}
}
})
</script>
<script setup lang="ts">
const zitadel = ref(getCurrentInstance()?.appContext.config.globalProperties.$zitadel!)
const user = ref(zitadel.value.oidcAuth.userProfile)
const signout = function() {
if (user.value) {
zitadel.value.oidcAuth.signOut()
}
}
</script>

22
src/views/NoAccess.vue Normal file
View file

@ -0,0 +1,22 @@
<template>
<div class="admin">
<div>
<h1>
Access denied
</h1>
<h2>
You don't have the role "admin" in your ZITADEL project.
</h2>
</div>
</div>
</template>
<style>
@media (min-width: 1024px) {
.admin {
min-height: 100vh;
display: flex;
align-items: center;
}
}
</style>