vue.js 및 Auth0을 사용하여 사용자가 이미 인증되어 있는 경우 로그인 페이지를 건너뛰려면 어떻게 해야 합니까?
묘사
나는 꽤 좋은 기준을 가지고 있다.SPA
로 건설된.vue.js
사용하고 있는 장소Auth0
공식 예에 따라 인증 부분을 처리합니다.앱 흐름은 다음과 같습니다.
Register in the Initial.vue via Auth0 lock
->Callback is called
->User's redirected to /home
위의 흐름은 모두 정상적으로 동작하고 있습니다만, 여기에 문제가 있습니다.
문제
사용자가 등록되면/home
다른 모든 경로(예: 다른 경로)에 액세스할 수 있도록 합니다./doctors
인증을 받은 경우, 인증을 받지 않은 경우 다시 로그인하도록 프롬프트가 표시됩니다.위의 링크에 따라 이것은router.beforeEach
기능.
에 액세스 하면, 문제가 표시됩니다./
로그인 페이지(Initialvue
사용자가 이미 등록되어 있고 해당 루트에 접속하려고 할 때 사용자가 해당 루트로 리다이렉트되도록 합니다./home
를 생략합니다.login
page. 이 기능을 구현하려고 합니다.beforeEnter
하지만auth.isAuthenticated
에 의해 실패하다tokenExpiry
null입니다(사용자가 인증되어 있는 경우에도 마찬가지입니다.
코드
나의AuthService.js
:
import auth0 from 'auth0-js';
import EventEmitter from 'events';
import authConfig from '../config/auth_config.json';
const webAuth = new auth0.WebAuth({
domain: authConfig.domain,
redirectUri: `${window.location.origin}/callback`,
clientID: authConfig.clientId,
responseType: 'id_token',
scope: 'openid profile email'
});
const localStorageKey = 'loggedIn';
const loginEvent = 'loginEvent';
class AuthService extends EventEmitter {
idToken = null;
profile = null;
tokenExpiry = null;
// Starts the user login flow
login(customState) {
webAuth.authorize({
appState: customState
});
}
// Handles the callback request from Auth0
handleAuthentication() {
return new Promise((resolve, reject) => {
webAuth.parseHash((err, authResult) => {
if (err) {
reject(err);
} else {
this.localLogin(authResult);
resolve(authResult.idToken);
}
});
});
}
localLogin(authResult) {
// console.log(authResult); TODO-me: Handle this
this.idToken = authResult.idToken;
this.profile = authResult.idTokenPayload;
// Convert the JWT expiry time from seconds to milliseconds
this.tokenExpiry = new Date(this.profile.exp * 1000);
localStorage.setItem(localStorageKey, 'true');
this.emit(loginEvent, {
loggedIn: true,
profile: authResult.idTokenPayload,
state: authResult.appState || {}
});
}
renewTokens() {
return new Promise((resolve, reject) => {
if (localStorage.getItem(localStorageKey) !== "true") {
return reject("Not logged in");
}``;
webAuth.checkSession({}, (err, authResult) => {
if (err) {
reject(err);
} else {
this.localLogin(authResult);
resolve(authResult);
}
});
});
}
logOut() {
localStorage.removeItem(localStorageKey);
this.idToken = null;
this.tokenExpiry = null;
this.profile = null;
webAuth.logout({
returnTo: window.location.origin
});
this.emit(loginEvent, { loggedIn: false });
}
isAuthenticated() {
console.log('In tokenExp is:');
console.log(this.tokenExpiry); //THIS returns null when /home -> /
return (
Date.now() < this.tokenExpiry &&
localStorage.getItem(localStorageKey) === 'true'
);
}
}
export default new AuthService();
나의Initial.vue
:
<template>
<v-container
app
fluid
>
<v-parallax
src="https://cdn.vuetifyjs.com/images/backgrounds/vbanner.jpg"
height="1000"
>
<v-layout
row
wrap
>
<!-- LOGIN-->
<v-toolbar
flat
light
dense
color="transparent"
>
<v-spacer></v-spacer>
<v-toolbar-items>
<v-btn
medium
color="lime lighten-2"
@click="login"
class="font-weight-bold title text-uppercase"
>
Login
</v-btn>
</v-toolbar-items>
</v-toolbar>
<v-layout
align-center
column
>
<h1 class="display-2 font-weight-thin mb-3 text-uppercase lime--text lighten-2" >Pulse</h1>
<h4 class="subheading">A digital intelligent insurance built for you!</h4>
</v-layout>
</v-layout>
</v-parallax>
</v-container>
</template>
<script>
import VContainer from "vuetify/lib/components/VGrid/VContainer";
import VFlex from "vuetify/lib/components/VGrid/VFlex";
import VLayout from "vuetify/lib/components/VGrid/VLayout";
import VBtn from "vuetify/lib/components/VBtn/VBtn";
import VToolbar from "vuetify/lib/components/VToolbar/VToolbar";
import VParallax from "vuetify/lib/components/VParallax/VParallax";
export default {
name: "Initial",
components: {
VContainer,
VLayout,
VFlex,
VBtn,
VToolbar,
VParallax
},
data() {
return {
isAuthenticated: false
};
},
async created() {
try {
await this.$auth.renewTokens();
} catch (e) {
// console.log(e);
}
},
methods: {
login() {
this.$auth.login();
},
// logout() {
// this.$auth.logOut();
// },
handleLoginEvent(data) {
this.isAuthenticated = data.loggedIn;
this.profile = data.profile;
}
}
}
</script>
<style scoped>
</style>
나의Callback.vue
:
<template>
<div>
<p>Loading...</p>
</div>
</template>
<script>
export default {
methods: {
handleLoginEvent(data) {
console.log('State.target is:');
console.log(data.state.target);
//If user has just signed up redirect to complete-signup form
if ((data.profile['<AUTH_DOMAIN>'].justSignedUp) && (data.state.target===undefined)){
// this.$router.push(data.state.target || "/complete-signup");
this.$router.push('/complete-signup');
}else {
// this.$router.push('/home');
this.$router.push(data.state.target);
}
}
},
created() {
this.$auth.handleAuthentication();
}
}
</script>
<style scoped>
</style>
나의router.js
:
import Vue from 'vue';
import Router from 'vue-router';
import auth from '../auth/AuthService';
import Callback from '../components/Callback';
Vue.use(Router)
// export default new Router({
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
// {
// path: '/',
// name: 'login',
// component: () => import('@/views/Login')
// },
{
path: '/',
name: 'initial',
component: () => import('@/views/Initial'),
// meta: {isAuth: true},
beforeEnter: ((to, from, next) => {
// if (to.matched.some(record => record.meta.isAuth)) {
console.log(auth.isAuthenticated()); //THIS is false for the above scenario
if (auth.isAuthenticated()) {
next({
path: '/home',
query: {redirect: to.fullPath}
})
} else {
next()
}
// }
})
},
{
path: '/callback',
name: 'callback',
component: Callback
},
{
path: '/home',
name: 'home',
component: () => import('@/views/Home')
},
{
path: '/doctors',
name: 'doctors',
component: () => import('@/views/Doctors')
},
{
path: '/complete-signup',
name: 'complete-signup',
component: () => import('@/views/CompleteSignup')
},
]
});
// Add a `beforeEach` handler to each route
router.beforeEach((to, from, next) => {
if (to.path === "/" || to.path === "/callback" || auth.isAuthenticated()) {
return next();
}
// Specify the current path as the customState parameter, meaning it
// will be returned to the application after auth
console.log('OUT beforeach if');
auth.login({ target: to.path });
});
'Complete Signup(등록 완료)'is my signup form after registering where the user's is filling out a form and then posting it via
악세서and then redirected to
/home':
//Form data before
methods: {
this.$store.dispatch(REGISTER,registerFormData)
.then(() => this.$router.push('/home'));
}
저도 쓰고 있어요.vuetify
그리고 나의 메인App.vue
컴포넌트는 다음과 같습니다.
<template>
<v-app
style= "background: #E0EAFC; /* fallback for old browsers */
background: -webkit-linear-gradient(to left, #CFDEF3, #E0EAFC); /* Chrome 10-25, Safari 5.1-6 */
background: linear-gradient(to left, #CFDEF3, #E0EAFC); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
"
>
<v-content>
<router-view></router-view>
</v-content>
</v-app>
</template>
<script>
export default {
name: 'App',
components: {
}
};
</script>
<style>
</style>
디폴트 동작을 사용자가 로그인한 동작으로 하고 루트 가드를 사용하여 각 루트를 보호함으로써 문제를 단순화할 수 있습니다.
1) 포인트:/
로./home
2) 로그인/"인셜"을 위한 개별 경로 생성
3) 사용방법beforeEach
훅을 사용하여 사용자가 인증되었는지 확인하고 사용자가 인증되지 않은 경우 사용자로 리디렉션합니다.Initial.vue
(또는 트리거)auth.login()
직접)
...
{
path: '/',
redirect: 'home'
},
{
path: '/initial',
...
...
}
...
router.beforeEach((to, from, next) => {
if(to.name == 'callback' || auth.isAuthenticated()) {
next()
} else { // trigger auth0 login or redirect to your Initial.vue
auth.login()
// next({ path: '/initial' })
}
})
난 이해했다.문제는 이 시스템이this.tokenExpiry
,this.idToken
,this.profile
값이 할당되어 있습니다.callback
다음에 오는 그림login
또한 이러한 값은 에서 정의한 특정 Vue 프로토타입 인스턴스와 관련되어 있습니다.mixin
첫 페이지로 돌아가면this
특정 Vue 인스턴스에 연결되지 않았기 때문에 정의되지 않았습니다.
저도 (React와) 같은 상황이었는데, 해결 방법을 설명하겠습니다.
먼저 인증에서는 토큰을 클라이언트 측에 저장해야 합니다(localStorage/cookie 사용 가능).
필요한 것은
SecureComponent
이 컴포넌트는 저장된 토큰이 존재하는지 여부만 확인합니다.FetchHandler
이 컴포넌트는 각각을 처리합니다.Protected Application
는 응답 코드를 검사하고 401(예를 들어)인 경우 사용자를 인증 컴포넌트로 리다이렉트합니다.이 스텝은 에 추가할 수 있습니다.SecureComponent
추가 레이어로 사용할 수 있습니다.
언급URL : https://stackoverflow.com/questions/56088916/using-vue-js-and-auth0-how-can-i-skip-the-login-page-if-the-users-already-authe
'programing' 카테고리의 다른 글
링크 리스트에서 루프를 검출하려면 어떻게 해야 합니다. (0) | 2022.07.08 |
---|---|
std::ios_base:에 대한 정의되지 않은 참조:초기화::Init()' (0) | 2022.07.08 |
Vue에서의 키다운 및 키업 (0) | 2022.07.08 |
Vuex getters 오디오 업데이트 실시간current Time 상태 (0) | 2022.07.07 |
vuej 루트 경로 변환 (0) | 2022.07.07 |