Refinement and cleanup
This commit is contained in:
6
KTUSA PS/ClientApp/.prettierrc.js
Normal file
6
KTUSA PS/ClientApp/.prettierrc.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
trailingComma: 'es5',
|
||||||
|
tabWidth: 2,
|
||||||
|
semi: false,
|
||||||
|
singleQuote: true,
|
||||||
|
}
|
5
KTUSA PS/ClientApp/package-lock.json
generated
5
KTUSA PS/ClientApp/package-lock.json
generated
@@ -1113,6 +1113,11 @@
|
|||||||
"integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
|
"integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@popperjs/core": {
|
||||||
|
"version": "2.10.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.1.tgz",
|
||||||
|
"integrity": "sha512-HnUhk1Sy9IuKrxEMdIRCxpIqPw6BFsbYSEUO9p/hNw5sMld/+3OLMWQP80F8/db9qsv3qUjs7ZR5bS/R+iinXw=="
|
||||||
|
},
|
||||||
"@soda/friendly-errors-webpack-plugin": {
|
"@soda/friendly-errors-webpack-plugin": {
|
||||||
"version": "1.7.1",
|
"version": "1.7.1",
|
||||||
"resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.1.tgz",
|
"resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.7.1.tgz",
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
"lint": "vue-cli-service lint"
|
"lint": "vue-cli-service lint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@popperjs/core": "^2.10.1",
|
||||||
"axios": "^0.20.0-0",
|
"axios": "^0.20.0-0",
|
||||||
"bootstrap": "^5.1.1",
|
"bootstrap": "^5.1.1",
|
||||||
"cookies-js": "^1.2.3",
|
"cookies-js": "^1.2.3",
|
||||||
|
@@ -1,21 +1,49 @@
|
|||||||
<template>
|
<template>
|
||||||
<nav-menu></nav-menu>
|
<nav-menu></nav-menu>
|
||||||
|
<div v-if="isLocal" class="container">
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<h4 class="alert-heading">Lokali sistemą aptikta</h4>
|
||||||
|
<span>
|
||||||
|
Buvo aptikta, kad aplikacija veikia ant lokalios mašinos. Tai didelis
|
||||||
|
šansas kad sistemoje pateikiama informacija nėra saugi.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div v-if="isInsecure" class="container">
|
||||||
|
<div class="alert alert-danger">
|
||||||
|
<h4 class="alert-heading">Nesaugus ryšys</h4>
|
||||||
|
<span>
|
||||||
|
Buvo aptikta, kad yra užmegztas nesaugus ryšys. Tai reiškią kad betkokie
|
||||||
|
duomenys perduodami naudojant sistemą, įskaitant ir prisijungimo tokeną,
|
||||||
|
yra neapsaugoti.
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<router-view />
|
<router-view />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import NavMenu from "./components/NavMenu.vue";
|
import NavMenu from './components/NavMenu.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "App",
|
name: 'App',
|
||||||
components: {
|
components: {
|
||||||
NavMenu,
|
NavMenu,
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.$store.dispatch("auth/loadToken");
|
this.$store.dispatch('auth/initialize')
|
||||||
},
|
},
|
||||||
};
|
computed: {
|
||||||
|
isLocal() {
|
||||||
|
return (
|
||||||
|
location.hostname === 'localhost' || location.hostname.startsWith('127')
|
||||||
|
)
|
||||||
|
},
|
||||||
|
isInsecure() {
|
||||||
|
return location.protocol !== 'https:'
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style></style>
|
||||||
</style>
|
|
||||||
|
@@ -1,26 +0,0 @@
|
|||||||
<template>
|
|
||||||
<h1>Counter</h1>
|
|
||||||
|
|
||||||
<p>This is a simple example of an Vue component.</p>
|
|
||||||
|
|
||||||
<p aria-live="polite">Current count: <strong>{{ currentCount }}</strong></p>
|
|
||||||
|
|
||||||
<button class="btn btn-primary" @click="incrementCounter">Increment</button>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: "Counter",
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
currentCount: 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
incrementCounter() {
|
|
||||||
this.currentCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
@@ -1,53 +0,0 @@
|
|||||||
<template>
|
|
||||||
<h1 id="tableLabel">Weather forecast</h1>
|
|
||||||
|
|
||||||
<p>This component demonstrates fetching data from the server.</p>
|
|
||||||
|
|
||||||
<p v-if="!forecasts"><em>Loading...</em></p>
|
|
||||||
|
|
||||||
<table class='table table-striped' aria-labelledby="tableLabel" v-if="forecasts">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Date</th>
|
|
||||||
<th>Temp. (C)</th>
|
|
||||||
<th>Temp. (F)</th>
|
|
||||||
<th>Summary</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr v-for="forecast of forecasts" v-bind:key="forecast">
|
|
||||||
<td>{{ forecast.date }}</td>
|
|
||||||
<td>{{ forecast.temperatureC }}</td>
|
|
||||||
<td>{{ forecast.temperatureF }}</td>
|
|
||||||
<td>{{ forecast.summary }}</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import axios from 'axios'
|
|
||||||
export default {
|
|
||||||
name: "FetchData",
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
forecasts: []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getWeatherForecasts() {
|
|
||||||
axios.get('/weatherforecast')
|
|
||||||
.then((response) => {
|
|
||||||
this.forecasts = response.data;
|
|
||||||
})
|
|
||||||
.catch(function (error) {
|
|
||||||
alert(error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.getWeatherForecasts();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
@@ -1,78 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="hello">
|
|
||||||
<h1>{{ msg }}</h1>
|
|
||||||
<img src="../assets/logo.png" />
|
|
||||||
<p>
|
|
||||||
Template for Vue JS 3.0 and .NET 5 applications developed by <b>Alexandre Malavasi.</b><br />
|
|
||||||
In order to get more content on Vue JS and .NET platform, please follow on my social media profiles:
|
|
||||||
</p>
|
|
||||||
<ul>
|
|
||||||
<li>
|
|
||||||
<a href="https://medium.com/@alexandre.malavasi" target="_blank">Medium</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://twitter.com/alemalavasi" target="_blank">Twitter</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://www.youtube.com/channel/UC-KFGgYiot1eA8QFqIgLmqA" target="_blank">Youtube</a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a href="https://www.facebook.com/alexandre.malavasi.dev" target="_blank">Facebook</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<h3>Vue Documentation</h3>
|
|
||||||
<p>
|
|
||||||
For a guide and recipes on how to configure / customize this project,<br>
|
|
||||||
check out the
|
|
||||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
|
|
||||||
</p>
|
|
||||||
<h3>Installed CLI Plugins</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
|
|
||||||
</ul>
|
|
||||||
<h3>Essential Links</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
|
|
||||||
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
|
|
||||||
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
|
|
||||||
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
|
|
||||||
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
|
|
||||||
</ul>
|
|
||||||
<h3>Ecosystem</h3>
|
|
||||||
<ul>
|
|
||||||
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
|
|
||||||
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
|
|
||||||
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
|
|
||||||
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'Home',
|
|
||||||
props: {
|
|
||||||
msg: String
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
|
||||||
<style scoped>
|
|
||||||
h3 {
|
|
||||||
margin: 40px 0 0;
|
|
||||||
}
|
|
||||||
ul {
|
|
||||||
list-style-type: none;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
li {
|
|
||||||
display: inline-block;
|
|
||||||
margin: 0 10px;
|
|
||||||
}
|
|
||||||
a {
|
|
||||||
color: #42b983;
|
|
||||||
}
|
|
||||||
</style>
|
|
@@ -1,97 +1,65 @@
|
|||||||
<template>
|
<template>
|
||||||
<header>
|
<header class="mb-3">
|
||||||
<nav
|
<nav class="navbar navbar-expand-lg navbar-dark bg-primary">
|
||||||
class="
|
<div class="container-fluid">
|
||||||
navbar navbar-expand-sm navbar-toggleable-sm navbar-light
|
<router-link :to="{ name: 'Home' }" class="navbar-brand"
|
||||||
bg-white
|
>KTU SA Problemų sprendimo sistema</router-link
|
||||||
border-bottom
|
>
|
||||||
box-shadow
|
|
||||||
mb-3
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<div class="container">
|
|
||||||
<a class="navbar-brand">Vue JS Template for .NET 5</a>
|
|
||||||
<button
|
<button
|
||||||
class="navbar-toggler"
|
class="navbar-toggler"
|
||||||
type="button"
|
type="button"
|
||||||
data-toggle="collapse"
|
data-bs-toggle="collapse"
|
||||||
data-target=".navbar-collapse"
|
data-bs-target="#navbarNav"
|
||||||
|
aria-controls="navbarNav"
|
||||||
|
aria-expanded="false"
|
||||||
aria-label="Toggle navigation"
|
aria-label="Toggle navigation"
|
||||||
@click="toggle"
|
|
||||||
>
|
>
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
<div
|
<div
|
||||||
class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse"
|
class="collapse navbar-collapse"
|
||||||
v-bind:class="{ show: isExpanded }"
|
:class="{ show: isExpanded }"
|
||||||
|
id="navbarNav"
|
||||||
>
|
>
|
||||||
<ul class="navbar-nav flex-grow">
|
<ul class="navbar-nav me-auto">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<router-link :to="{ name: 'Home' }" class="nav-link text-dark"
|
<router-link :to="{ name: 'Home' }" class="nav-link"
|
||||||
>Home</router-link
|
>Pagrindinis</router-link
|
||||||
>
|
>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
|
||||||
<router-link :to="{ name: 'Counter' }" class="nav-link text-dark"
|
|
||||||
>Counter</router-link
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
<li class="nav-item">
|
|
||||||
<router-link
|
|
||||||
:to="{ name: 'FetchData' }"
|
|
||||||
class="nav-link text-dark"
|
|
||||||
>Fetch Data</router-link
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
<a
|
|
||||||
href="https://login.microsoftonline.com/3415f2f7-f5a8-4092-b52a-003aaf844853/oauth2/v2.0/authorize?client_id=5931fda0-e9e0-4754-80c2-18bcb9d9561a&response_type=id_token&scope=openid email&nonce=aaaa"
|
|
||||||
>Login</a
|
|
||||||
>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
<div class="navbar-nav">
|
||||||
|
<span v-if="$store.getters['auth/isValid']" class="navbar-text"
|
||||||
|
>Prisijungta kaip {{ $store.getters['auth/email'] }}</span
|
||||||
|
>
|
||||||
|
<div v-else class="nav-item">
|
||||||
|
<a :href="$store.getters['auth/loginUrl']" class="nav-link"
|
||||||
|
>Prisijungti</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<style>
|
|
||||||
a.navbar-brand {
|
|
||||||
white-space: normal;
|
|
||||||
text-align: center;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
|
||||||
font-size: 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
|
||||||
html {
|
|
||||||
font-size: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.box-shadow {
|
|
||||||
box-shadow: 0 0.25rem 0.75rem rgba(0, 0, 0, 0.05);
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
name: "NavMenu",
|
name: 'NavMenu',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isExpanded: false,
|
isExpanded: false,
|
||||||
};
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
collapse() {
|
collapse() {
|
||||||
this.isExpanded = false;
|
this.isExpanded = false
|
||||||
},
|
},
|
||||||
|
|
||||||
toggle() {
|
toggle() {
|
||||||
this.isExpanded = !this.isExpanded;
|
this.isExpanded = !this.isExpanded
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
@@ -1,12 +1,15 @@
|
|||||||
import { createApp } from "vue";
|
import { createApp } from 'vue'
|
||||||
import App from "./App.vue";
|
import App from './App.vue'
|
||||||
import router from "./router";
|
import router from './router'
|
||||||
import store from "./store";
|
import store from './store'
|
||||||
import "./assets/main.scss";
|
import './assets/main.scss'
|
||||||
|
import 'bootstrap'
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App)
|
||||||
|
|
||||||
app.use(router);
|
app.use(router)
|
||||||
app.use(store);
|
app.use(store)
|
||||||
|
|
||||||
app.mount("#app");
|
app.mount('#app')
|
||||||
|
|
||||||
|
window.r = router
|
||||||
|
@@ -5,7 +5,10 @@
|
|||||||
<template v-if="$store.getters['auth/isValid']">
|
<template v-if="$store.getters['auth/isValid']">
|
||||||
<div class="alert alert-success">
|
<div class="alert alert-success">
|
||||||
<h4 class="alert-heading">Tu esi prisijungęs</h4>
|
<h4 class="alert-heading">Tu esi prisijungęs</h4>
|
||||||
<p>Kliento aplikacija turi tavo saugos raktą. aplikacija žino, kad tavo el. paštas yra: <b>{{ $store.getters["auth/email"] }}</b></p>
|
<span>
|
||||||
|
Kliento aplikacija turi tavo saugos raktą. Aplikacija žino, kad tavo
|
||||||
|
el. paštas yra: <b>{{ $store.getters['auth/email'] }}</b>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<h2>Visi laukai gaunami iš Azure Active Directory</h2>
|
<h2>Visi laukai gaunami iš Azure Active Directory</h2>
|
||||||
<table class="table">
|
<table class="table">
|
||||||
@@ -18,17 +21,24 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr v-for="(value, key) in authDataTable" :key="key">
|
<tr v-for="(value, key) in authDataTable" :key="key">
|
||||||
<td>{{ key }}</td>
|
<td>{{ key }}</td>
|
||||||
<td>{{ value }}</td>
|
<td>
|
||||||
|
<pre>{{ value }}</pre>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<h3>Techninė duomenų reprezentacija</h3>
|
<h3>Techninė duomenų reprezentacija</h3>
|
||||||
<a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/access-tokens">Dokumentacija apie laukų reikšmes</a>
|
<a
|
||||||
|
href="https://docs.microsoft.com/en-us/azure/active-directory/develop/access-tokens"
|
||||||
|
>Dokumentacija apie laukų reikšmes</a
|
||||||
|
>
|
||||||
<pre>{{ $store.state.auth.tokenData }}</pre>
|
<pre>{{ $store.state.auth.tokenData }}</pre>
|
||||||
<h3>Saugos raktas.</h3>
|
<h3>Saugos raktas.</h3>
|
||||||
<pre>{{ $store.state.auth.token }}</pre>
|
<pre>{{ $store.state.auth.token }}</pre>
|
||||||
<h3>Serverio tokeno patikrinimas</h3>
|
<h3>Serverio tokeno patikrinimas</h3>
|
||||||
<button type="button" class="btn btn-primary" @click="serverVerify">Patikrinti</button>
|
<button type="button" class="btn btn-primary" @click="serverVerify">
|
||||||
|
Patikrinti
|
||||||
|
</button>
|
||||||
<h5>Verifikacijos atsakas:</h5>
|
<h5>Verifikacijos atsakas:</h5>
|
||||||
<pre>
|
<pre>
|
||||||
{{ verificationResult }}
|
{{ verificationResult }}
|
||||||
@@ -39,59 +49,59 @@
|
|||||||
<p>Prašom paspausti prisijungimo mygtuką navigacijos juostoje.</p>
|
<p>Prašom paspausti prisijungimo mygtuką navigacijos juostoje.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import axios from "axios";
|
import axios from 'axios'
|
||||||
|
|
||||||
const names = {
|
const names = {
|
||||||
"aud": "AppId (Audience)",
|
aud: 'AppId (Audience)',
|
||||||
"iss": "Išdavėjas",
|
iss: 'Išdavėjas',
|
||||||
"iat": "Išdavimo momentas",
|
iat: 'Išdavimo momentas',
|
||||||
"nbf": "Negalioja anksčiau nei",
|
nbf: 'Negalioja anksčiau nei',
|
||||||
"exp": "Galiojimo pabaiga",
|
exp: 'Galiojimo pabaiga',
|
||||||
"email": "El. paštas",
|
email: 'El. paštas',
|
||||||
"nonce": "Aplikacijos sugeneruota nepasikartojanti reikšmė",
|
nonce: 'Aplikacijos sugeneruota nepasikartojanti reikšmė',
|
||||||
"sub": "Subjektas (Vartotojo Id)",
|
sub: 'Subjektas (Vartotojo Id)',
|
||||||
"tid": "Tenanto Identifikatorius",
|
tid: 'Tenanto Identifikatorius',
|
||||||
"ver": "OAuth versija"
|
ver: 'OAuth versija',
|
||||||
}
|
}
|
||||||
|
|
||||||
function lookupName(key) {
|
function lookupName(key) {
|
||||||
if(names[key])
|
if (names[key]) return names[key]
|
||||||
return names[key];
|
return key
|
||||||
return key;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
verificationResult: null
|
verificationResult: null,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
authDataTable() {
|
authDataTable() {
|
||||||
return Object.fromEntries(Object.entries(this.$store.state.auth.tokenData).map(([key, value]) => [lookupName(key), value]))
|
return Object.fromEntries(
|
||||||
}
|
Object.entries(this.$store.state.auth.tokenData).map(([key, value]) => [
|
||||||
|
lookupName(key),
|
||||||
|
value,
|
||||||
|
])
|
||||||
|
)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
serverVerify() {
|
serverVerify() {
|
||||||
this.verificationResult = null
|
this.verificationResult = null
|
||||||
axios
|
axios
|
||||||
.get("/test/authed", {
|
.get('/test/authed', {
|
||||||
headers: { Authorization: `Bearer ${this.$store.state.auth.token}` },
|
headers: { Authorization: `Bearer ${this.$store.state.auth.token}` },
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then(response => {
|
||||||
this.verificationResult = response.data;
|
this.verificationResult = response.data
|
||||||
})
|
})
|
||||||
.catch(function (error) {
|
.catch(function(error) {
|
||||||
alert(error);
|
alert(error)
|
||||||
});
|
})
|
||||||
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
};
|
|
||||||
</script>
|
</script>
|
@@ -1,47 +1,25 @@
|
|||||||
<template>
|
<template>
|
||||||
<h1 @click="makeTestCall">OpenID connect return endpoint</h1>
|
<div class="container">
|
||||||
<pre style="text-align: left">{{ response }}</pre>
|
<h1>Palaukite kol nustatysime jūsų tapatybe...</h1>
|
||||||
{{ openIdToken }}
|
</div>
|
||||||
<hr />
|
|
||||||
{{ $route }}
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// https://login.microsoftonline.com/3415f2f7-f5a8-4092-b52a-003aaf844853/oauth2/v2.0/authorize?client_id=5931fda0-e9e0-4754-80c2-18bcb9d9561a&response_type=id_token&scope=openid email&nonce=a
|
const tokenRegex = /id_token=(.*\..*\..*)&/
|
||||||
|
|
||||||
const tokenRegex = /id_token=(.*\..*\..*)&/;
|
|
||||||
import axios from "axios";
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "OIDC",
|
name: 'OIDC',
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
response: "[empty]",
|
|
||||||
};
|
|
||||||
},
|
|
||||||
created() {
|
created() {
|
||||||
this.$store.dispatch("auth/setToken", this.openIdToken);
|
if (this.openIdToken)
|
||||||
},
|
this.$store.dispatch('auth/setToken', this.openIdToken)
|
||||||
methods: {
|
this.$router.push({ name: 'Home' })
|
||||||
makeTestCall() {
|
|
||||||
axios
|
|
||||||
.get("/test", {
|
|
||||||
headers: { Authorization: `Bearer ${this.openIdToken}` },
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
this.response = response.data;
|
|
||||||
})
|
|
||||||
.catch(function (error) {
|
|
||||||
alert(error);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
openIdToken() {
|
openIdToken() {
|
||||||
// return tokenRegex.test(this.$route.hash)
|
const matches = this.$route.hash.match(tokenRegex)
|
||||||
return this.$route.hash.match(tokenRegex)[1];
|
if (!matches) return null
|
||||||
// return this.$route.hash;
|
return matches[1]
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
</script>
|
</script>
|
||||||
|
@@ -1,35 +1,23 @@
|
|||||||
import { createWebHistory, createRouter } from "vue-router";
|
import { createWebHistory, createRouter } from 'vue-router'
|
||||||
import Home from "@/pages/Home.vue";
|
import Home from '@/pages/Home.vue'
|
||||||
import Counter from "@/components/Counter.vue";
|
import OidcEndpoint from '@/pages/OidcEndpoint.vue'
|
||||||
import FetchData from "@/components/FetchData.vue";
|
|
||||||
import OidcEndpoint from "@/pages/OidcEndpoint.vue";
|
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
path: "/",
|
path: '/',
|
||||||
name: "Home",
|
name: 'Home',
|
||||||
component: Home,
|
component: Home,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/Counter",
|
path: '/oidc',
|
||||||
name: "Counter",
|
name: 'OpenID connect endpoint',
|
||||||
component: Counter,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "/FetchData",
|
|
||||||
name: "FetchData",
|
|
||||||
component: FetchData,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: "/oidc",
|
|
||||||
name: "OpenID connect endpoint",
|
|
||||||
component: OidcEndpoint,
|
component: OidcEndpoint,
|
||||||
},
|
},
|
||||||
];
|
]
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(),
|
history: createWebHistory(),
|
||||||
routes,
|
routes,
|
||||||
});
|
})
|
||||||
|
|
||||||
export default router;
|
export default router
|
||||||
|
@@ -1,70 +1,140 @@
|
|||||||
import Cookies from "cookies-js";
|
import Cookies from 'cookies-js'
|
||||||
import jwt_decode from "jwt-decode";
|
import jwt_decode from 'jwt-decode'
|
||||||
const TokenCookieName = "ktusaktutoken";
|
import axios from 'axios'
|
||||||
|
|
||||||
|
const TokenCookieName = 'ktusaktutoken'
|
||||||
|
const ClientIdCookieName = 'ktusakacas'
|
||||||
|
const AuthorityCookieName = 'ktusakeksas'
|
||||||
|
const TenantCookieName = 'ktusalaimis'
|
||||||
|
const NonceCookieName = 'ktusakumpikas'
|
||||||
|
|
||||||
|
const Scope = 'openid email'
|
||||||
|
|
||||||
// initial state
|
// initial state
|
||||||
const state = () => ({
|
const state = () => ({
|
||||||
token: null,
|
token: null,
|
||||||
tokenData: null,
|
tokenData: null,
|
||||||
});
|
clientId: null, // 5931fda0-e9e0-4754-80c2-18bcb9d9561a
|
||||||
|
authority: null, // https://login.microsoftonline.com/3415f2f7-f5a8-4092-b52a-003aaf844853/v2.0
|
||||||
|
tenant: null, // 3415f2f7-f5a8-4092-b52a-003aaf844853
|
||||||
|
})
|
||||||
|
|
||||||
|
const callbackUrl =
|
||||||
|
window.location.protocol + '//' + window.location.host + '/oidc'
|
||||||
|
|
||||||
// getters
|
// getters
|
||||||
const getters = {
|
const getters = {
|
||||||
isValid(state) {
|
isReady(state) {
|
||||||
if (state.token == null || state.tokenData == null) return false;
|
|
||||||
const d = state.tokenData;
|
|
||||||
if (
|
if (
|
||||||
d.iss !==
|
state.clientId == null ||
|
||||||
"https://login.microsoftonline.com/3415f2f7-f5a8-4092-b52a-003aaf844853/v2.0"
|
state.authority == null ||
|
||||||
|
state.tenant == null
|
||||||
)
|
)
|
||||||
return false;
|
return false
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
isValid(state, getters) {
|
||||||
|
if (!getters.isReady) return false
|
||||||
|
if (state.token == null || state.tokenData == null) return false
|
||||||
|
const d = state.tokenData
|
||||||
|
if (d.nonce !== state.nonce) return false
|
||||||
|
if (d.iss !== state.authority) return false
|
||||||
|
|
||||||
if (d.aud !== "5931fda0-e9e0-4754-80c2-18bcb9d9561a") return false;
|
if (d.aud !== state.clientId) return false
|
||||||
const now = new Date();
|
const now = new Date()
|
||||||
const exp = new Date(d.exp * 1000);
|
const exp = new Date(d.exp * 1000)
|
||||||
if (now > exp) return false;
|
if (now > exp) return false
|
||||||
return true;
|
return true
|
||||||
},
|
},
|
||||||
email(state, getters) {
|
email(state, getters) {
|
||||||
if (!getters.isValid) return null;
|
if (!getters.isValid) return null
|
||||||
return state.tokenData.email;
|
return state.tokenData.email
|
||||||
},
|
},
|
||||||
userId(state, getters) {
|
userId(state, getters) {
|
||||||
if (!getters.isValid) return null;
|
if (!getters.isValid) return null
|
||||||
return state.tokenData.email;
|
return state.tokenData.email
|
||||||
},
|
},
|
||||||
};
|
loginUrl(state, getters) {
|
||||||
|
if (!getters.isReady) return null
|
||||||
|
return `https://login.microsoftonline.com/${
|
||||||
|
state.tenant
|
||||||
|
}/oauth2/v2.0/authorize?client_id=${
|
||||||
|
state.clientId
|
||||||
|
}&redirect_uri=${encodeURIComponent(
|
||||||
|
callbackUrl
|
||||||
|
)}&response_type=id_token&scope=${Scope}&nonce=${state.nonce}`
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
// actions
|
// actions
|
||||||
const actions = {
|
const actions = {
|
||||||
async loadToken({ commit }) {
|
async initialize({ commit }) {
|
||||||
const token = Cookies.get(TokenCookieName);
|
const token = Cookies.get(TokenCookieName)
|
||||||
commit("setToken", token);
|
const primaryClientId = Cookies.get(ClientIdCookieName)
|
||||||
commit("computeTokenVars");
|
const primaryAuthority = Cookies.get(AuthorityCookieName)
|
||||||
|
const primaryTenant = Cookies.get(TenantCookieName)
|
||||||
|
const nonce = Cookies.get(NonceCookieName)
|
||||||
|
if (!nonce) {
|
||||||
|
const newNonce =
|
||||||
|
Date.now().toString(36) +
|
||||||
|
Math.random()
|
||||||
|
.toString(36)
|
||||||
|
.substring(2)
|
||||||
|
Cookies.set(NonceCookieName, newNonce)
|
||||||
|
commit('setNonce', newNonce)
|
||||||
|
} else {
|
||||||
|
commit('setNonce', nonce)
|
||||||
|
}
|
||||||
|
commit('setToken', token)
|
||||||
|
commit('computeTokenVars')
|
||||||
|
commit('setMetadata', [primaryClientId, primaryAuthority, primaryTenant])
|
||||||
|
axios
|
||||||
|
.get('/api/AuthMetadata')
|
||||||
|
.then(response => {
|
||||||
|
Cookies.set(ClientIdCookieName, response.data.clientId)
|
||||||
|
Cookies.set(AuthorityCookieName, response.data.authority)
|
||||||
|
Cookies.set(TenantCookieName, response.data.tenant)
|
||||||
|
commit('setMetadata', [
|
||||||
|
response.data.clientId,
|
||||||
|
response.data.authority,
|
||||||
|
response.data.tenant,
|
||||||
|
])
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error(error)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
async setToken({ commit }, token) {
|
async setToken({ commit }, token) {
|
||||||
Cookies.set(TokenCookieName, token);
|
Cookies.set(TokenCookieName, token)
|
||||||
commit("setToken", token);
|
commit('setToken', token)
|
||||||
commit("computeTokenVars");
|
commit('computeTokenVars')
|
||||||
},
|
},
|
||||||
};
|
}
|
||||||
|
|
||||||
// mutations
|
// mutations
|
||||||
const mutations = {
|
const mutations = {
|
||||||
setToken(state, token) {
|
setToken(state, token) {
|
||||||
state.token = token;
|
state.token = token
|
||||||
|
},
|
||||||
|
setNonce(state, nonce) {
|
||||||
|
state.nonce = nonce
|
||||||
},
|
},
|
||||||
computeTokenVars(state) {
|
computeTokenVars(state) {
|
||||||
if (state.token == null) return;
|
if (state.token == null) return
|
||||||
try {
|
try {
|
||||||
state.tokenData = jwt_decode(state.token);
|
state.tokenData = jwt_decode(state.token)
|
||||||
} catch {
|
} catch {
|
||||||
console.log("Token was invalid.");
|
console.log('Token was invalid.')
|
||||||
state.tokenData = null;
|
state.tokenData = null
|
||||||
state.token = null;
|
state.token = null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
setMetadata(state, [clientId, authority, tenant]) {
|
||||||
|
state.clientId = clientId
|
||||||
|
state.authority = authority
|
||||||
|
state.tenant = tenant
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
namespaced: true,
|
namespaced: true,
|
||||||
@@ -72,4 +142,4 @@ export default {
|
|||||||
getters,
|
getters,
|
||||||
actions,
|
actions,
|
||||||
mutations,
|
mutations,
|
||||||
};
|
}
|
||||||
|
24
KTUSA PS/Controllers/AuthMetadataController.cs
Normal file
24
KTUSA PS/Controllers/AuthMetadataController.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace KTUSA_PS.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
public class AuthMetadataController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IConfiguration _configuration;
|
||||||
|
public AuthMetadataController(IConfiguration configuration)
|
||||||
|
{
|
||||||
|
_configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public object Index() => new { ClientId = _configuration["ClientId"], Authority = _configuration["Authority"], Tenant = _configuration["Tenant"] };
|
||||||
|
}
|
||||||
|
}
|
@@ -15,9 +15,9 @@ namespace KTUSA_PS.Controllers
|
|||||||
public class TestController : ControllerBase
|
public class TestController : ControllerBase
|
||||||
{
|
{
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public Object[] Index()
|
public object[] Index()
|
||||||
{
|
{
|
||||||
return this.HttpContext.User.Claims.Select(x => new { Name = x.Type, Value= x.Value }).ToArray();
|
return HttpContext.User.Claims.Select(x => new { Name = x.Type, Value= x.Value }).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("authed")]
|
[HttpGet("authed")]
|
||||||
|
@@ -9,6 +9,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using VueCliMiddleware;
|
using VueCliMiddleware;
|
||||||
|
|
||||||
@@ -35,13 +36,8 @@ namespace KTUSA_PS
|
|||||||
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||||
.AddJwtBearer(options =>
|
.AddJwtBearer(options =>
|
||||||
{
|
{
|
||||||
|
options.Audience = "5931fda0-e9e0-4754-80c2-18bcb9d9561a";
|
||||||
options.Authority = "https://login.microsoftonline.com/3415f2f7-f5a8-4092-b52a-003aaf844853/v2.0";
|
options.Authority = "https://login.microsoftonline.com/3415f2f7-f5a8-4092-b52a-003aaf844853/v2.0";
|
||||||
|
|
||||||
options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters()
|
|
||||||
{
|
|
||||||
ValidIssuer = "https://login.microsoftonline.com/3415f2f7-f5a8-4092-b52a-003aaf844853/v2.0",
|
|
||||||
ValidAudience = "5931fda0-e9e0-4754-80c2-18bcb9d9561a"
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
services.AddAuthorization((configure) =>
|
services.AddAuthorization((configure) =>
|
||||||
|
@@ -5,5 +5,8 @@
|
|||||||
"Microsoft": "Warning",
|
"Microsoft": "Warning",
|
||||||
"Microsoft.Hosting.Lifetime": "Information"
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"ClientId": "5931fda0-e9e0-4754-80c2-18bcb9d9561a",
|
||||||
|
"Authority": "https://login.microsoftonline.com/3415f2f7-f5a8-4092-b52a-003aaf844853/v2.0",
|
||||||
|
"Tenant": "3415f2f7-f5a8-4092-b52a-003aaf844853"
|
||||||
}
|
}
|
||||||
|
@@ -6,5 +6,8 @@
|
|||||||
"Microsoft.Hosting.Lifetime": "Information"
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"AllowedHosts": "*"
|
"AllowedHosts": "*",
|
||||||
|
"ClientId": "5931fda0-e9e0-4754-80c2-18bcb9d9561a",
|
||||||
|
"Authority": "https://login.microsoftonline.com/3415f2f7-f5a8-4092-b52a-003aaf844853/v2.0",
|
||||||
|
"Tenant": "3415f2f7-f5a8-4092-b52a-003aaf844853"
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user