Skip to content

Commit 4394480

Browse files
spolezhaevbruce-willis
authored andcommitted
Auth0 Implementation (#1)
* Defining Settings * Server-Side implementation * Fixed querys parameters on client, added axios, fixed server * Various fixes, remove hardcoded redirect url * Update HomeController.cs
1 parent efc052b commit 4394480

File tree

22 files changed

+2190
-40
lines changed

22 files changed

+2190
-40
lines changed

ClientApp/@types/alltypes.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
declare module 'EventEmitter';

ClientApp/assets/loading.svg

Lines changed: 1 addition & 0 deletions
Loading

ClientApp/auth/AuthService.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import auth0, { WebAuth } from 'auth0-js'
2+
import router from '../router/'
3+
import EventEmitter from 'EventEmitter'
4+
5+
export default class AuthService {
6+
authenticated = this.isAuthenticated()
7+
authNotifier = new EventEmitter()
8+
auth0: WebAuth
9+
constructor(hostname:string, port:string, protocol:string) {
10+
this.login = this.login.bind(this);
11+
this.setSession = this.setSession.bind(this)
12+
this.logout = this.logout.bind(this)
13+
this.isAuthenticated = this.isAuthenticated.bind(this)
14+
var stringBuild = protocol + "//" + hostname;
15+
if (port !== "")
16+
stringBuild += ':' + port
17+
stringBuild += '/callback'
18+
this.auth0 = new auth0.WebAuth({
19+
domain: 'dotnextrussia.eu.auth0.com',
20+
clientID: 'g7saZcm47evyY3kWWP26ZxifDpxycl9h',
21+
redirectUri: stringBuild,
22+
audience: 'http://medhelp20171124063439.azurewebsites.net/',
23+
responseType: 'token id_token',
24+
scope: 'openid profile read:templates'
25+
});
26+
}
27+
28+
29+
30+
31+
login() {
32+
this.auth0.authorize();
33+
}
34+
35+
handleAuthentication () {
36+
this.auth0.parseHash((err, authResult) => {
37+
if (authResult && authResult.accessToken && authResult.idToken) {
38+
this.setSession(authResult)
39+
router.replace('home')
40+
} else if (err) {
41+
router.replace('home')
42+
console.log(err)
43+
alert(`Error: ${err.error}. Check the console for further details.`)
44+
}
45+
location.reload()
46+
})
47+
}
48+
49+
setSession (authResult : any) {
50+
// Set the time that the access token will expire at
51+
let expiresAt = JSON.stringify(
52+
authResult.expiresIn * 1000 + new Date().getTime()
53+
)
54+
localStorage.setItem('access_token', authResult.accessToken)
55+
localStorage.setItem('id_token', authResult.idToken)
56+
localStorage.setItem('expires_at', expiresAt)
57+
this.authNotifier.emit('authChange', { authenticated: true })
58+
}
59+
60+
logout () {
61+
// Clear access token and ID token from local storage
62+
localStorage.removeItem('access_token')
63+
localStorage.removeItem('id_token')
64+
localStorage.removeItem('expires_at')
65+
//this.userProfile = null
66+
this.authNotifier.emit('authChange', false)
67+
// navigate to the home route
68+
router.replace('home')
69+
location.reload()
70+
}
71+
72+
isAuthenticated () {
73+
// Check whether the current time is past the
74+
// access token's expiry time
75+
let expiresAt = JSON.parse(localStorage.getItem('expires_at') || '{}')
76+
return new Date().getTime() < expiresAt
77+
}
78+
}

ClientApp/boot.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,13 @@ import './css/site.css';
22
import 'bootstrap';
33
import Vue from 'vue';
44
import VueRouter from 'vue-router';
5+
import router from './router'
6+
import App from './components/app/app'
57
Vue.use(VueRouter);
68

7-
const routes = [
8-
{ path: '/', component: require('./components/home/home.vue.html') },
9-
{ path: '/counter', component: require('./components/counter/counter.vue.html') },
10-
{ path: '/fetchdata', component: require('./components/fetchdata/fetchdata.vue.html') }
11-
];
129

1310
new Vue({
1411
el: '#app-root',
15-
router: new VueRouter({ mode: 'history', routes: routes }),
12+
router: router,
1613
render: h => h(require('./components/app/app.vue.html'))
1714
});

ClientApp/components/app/app.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,29 @@
11
import Vue from 'vue';
22
import { Component } from 'vue-property-decorator';
3+
import AuthService from '../../auth/AuthService';
34

4-
@Component({
5+
6+
7+
const auth = new AuthService(window.location.hostname, window.location.port, window.location.protocol)
8+
9+
var { login, logout, authenticated, authNotifier } = auth
10+
11+
export default Vue.extend({
12+
name: 'app',
513
components: {
614
MenuComponent: require('../navmenu/navmenu.vue.html')
15+
},
16+
data() {
17+
authNotifier.on('authChange', (authState:any) => {
18+
authenticated = authState.authenticated
19+
})
20+
return {
21+
auth,
22+
authenticated
23+
}
24+
},
25+
methods: {
26+
login,
27+
logout
728
}
8-
})
9-
export default class AppComponent extends Vue {
10-
}
29+
})

ClientApp/components/app/app.vue.html

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,18 @@
33
<div class="row">
44
<div class="col-sm-3">
55
<menu-component />
6+
67
</div>
78
<div class="col-sm-9">
8-
<router-view></router-view>
9+
<router-view
10+
:auth="auth"
11+
:authenticated="authenticated">
12+
</router-view>
913
</div>
1014
</div>
15+
1116
</div>
17+
1218
</template>
1319

1420
<script src="./app.ts"></script>
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import Vue from "vue";
2+
3+
export default Vue.extend({
4+
name: 'callback',
5+
props: ['auth'],
6+
data () {
7+
// alert(JSON.stringify(this.auth))
8+
this.auth.handleAuthentication()
9+
return {}
10+
}
11+
})
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<template>
2+
<div class="spinner">
3+
<img src="../../assets/loading.svg" alt="loading"/>
4+
</div>
5+
</template>
6+
7+
<style>
8+
.spinner {
9+
position: absolute;
10+
display: flex;
11+
justify-content: center;
12+
height: 100vh;
13+
width: 100vw;
14+
background-color: white;
15+
top: 0;
16+
bottom: 0;
17+
left: 0;
18+
right: 0;
19+
}
20+
</style>
Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import Vue from 'vue';
22
import { Component } from 'vue-property-decorator';
3+
import axios from 'axios';
4+
35

46
interface WeatherForecast {
57
dateFormatted: string;
@@ -11,12 +13,25 @@ interface WeatherForecast {
1113
@Component
1214
export default class FetchDataComponent extends Vue {
1315
forecasts: WeatherForecast[] = [];
14-
16+
HTTP = axios.create({
17+
baseURL: 'api/SampleData/WeatherForecasts',
18+
19+
})
1520
mounted() {
16-
fetch('api/SampleData/WeatherForecasts')
17-
.then(response => response.json() as Promise<WeatherForecast[]>)
18-
.then(data => {
19-
this.forecasts = data;
20-
});
21+
axios.get("api/SampleData/WeatherForecasts",
22+
{
23+
headers: {
24+
Authorization: 'Bearer ' + localStorage.getItem('access_token')
25+
}
26+
})
27+
.then(response => {
28+
this.forecasts = response.data
29+
})
30+
.catch(e => {
31+
alert(e)
32+
})
33+
34+
// fetch('api/SampleData/WeatherForecasts')
35+
2136
}
2237
}

ClientApp/components/home/home.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import Vue from 'vue';
2+
export default Vue.extend({
3+
name: 'home',
4+
props: ['auth', 'authenticated']
5+
})

0 commit comments

Comments
 (0)