为什么在我的 Angular 应用程序中刷新页面或单击 link 时我的 auth0 令牌会过期?
Why my auth0 token expires when refreshing page or clicking link in my Angular app?
我正在 Angular SPA 中设置身份验证。
我正在使用 auth0,我正在阅读他们页面上的教程:https://auth0.com/docs/quickstart/spa/angular2
我做了登录教程
import { Injectable } from '@angular/core';
import * as auth0 from 'auth0-js';
import { Router } from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class AuthService {
userProfile: any;
private _idToken: string;
private _accessToken: string;
private _expiresAt: number;
auth0 = new auth0.WebAuth({
clientID: '*****',
domain: '****',
responseType: 'token id_token',
redirectUri: 'http://localhost:4200/callback',
scope: 'openid profile'
});
constructor(public router: Router) {
this._idToken = '';
this._accessToken = '';
this._expiresAt = 0;
}
public login(): void {
this.auth0.authorize();
}
public handleAuthentication(): void {
this.auth0.parseHash((err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
window.location.hash = '';
this.localLogin(authResult);
this.router.navigate(['/']);
} else if (err) {
this.router.navigate(['/']);
console.log(err);
}
});
}
public getProfile(cb): void {
if (!this._accessToken) {
throw new Error('Access Token must exist to fetch profile');
}
const self = this;
this.auth0.client.userInfo(this._accessToken, (err, profile) => {
if (profile) {
self.userProfile = profile;
}
cb(err, profile);
});
}
private localLogin(authResult): void {
localStorage.setItem('isLoggedIn', 'true');
const expiresAt = (authResult.expiresIn * 1000) + new Date().getTime();
this._accessToken = authResult.accessToken;
this._idToken = authResult.idToken;
this._expiresAt = expiresAt;
}
public renewTokens(): void {
this.auth0.checkSession({}, (err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
this.localLogin(authResult);
} else if (err) {
alert(`Could not get a new token (${err.error}: ${err.error_description}).`);
this.logout();
}
});
}
public logout(): void {
this._accessToken = '';
this._idToken = '';
this._expiresAt = 0;
localStorage.removeItem('isLoggedIn');
this.router.navigate(['/']);
}
public isAuthenticated(): boolean {
return new Date().getTime() < this._expiresAt;
}
get accessToken(): string {
return this._accessToken;
}
get idToken(): string {
return this._idToken;
}
}
我在我的页面上点击登录,我成功了,我得到了令牌,一切都很好。但是,当我刷新页面或单击 link 时,它会被注销。我应该怎么做才能保持登录状态?
当前,您正在将数据保存在内存变量中。因此,当您重新加载应用程序时,内存变量 (_expiresAt) 丢失了值。因此,isAuthenticated() 方法 returns false。您可以将数据保存在浏览器localStorage中。
private localLogin(authResult): void {
const expiresAt = JSON.stringify(
authResult.expiresIn * 1000 + new Date().getTime()
);
localStorage.setItem("access_token", authResult.accessToken);
localStorage.setItem("id_token", authResult.idToken);
localStorage.setItem("expires_at", expiresAt);
}
然后,在 isAuthenticated() 方法中,您可以从 localStorage 加载 expiresAt。
public isAuthenticated(): boolean {
const expiresAt = JSON.parse(localStorage.getItem("expires_at") || "{}");
return new Date().getTime() < expiresAt;
}
登出过程中,需要清除localStorage中的数据。
public logout(): void {
// Remove tokens and expiry time from localStorage
localStorage.removeItem("access_token");
localStorage.removeItem("id_token");
localStorage.removeItem("expires_at");
// Remove server SSO session
this.auth0.logout({ returnTo: "http://localhost:4200" });
}
最佳实践:
对于 SPA,请遵循 auth0 最佳实践:https://auth0.com/docs/security/store-tokens#single-page-apps
我正在 Angular SPA 中设置身份验证。
我正在使用 auth0,我正在阅读他们页面上的教程:https://auth0.com/docs/quickstart/spa/angular2
我做了登录教程
import { Injectable } from '@angular/core';
import * as auth0 from 'auth0-js';
import { Router } from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class AuthService {
userProfile: any;
private _idToken: string;
private _accessToken: string;
private _expiresAt: number;
auth0 = new auth0.WebAuth({
clientID: '*****',
domain: '****',
responseType: 'token id_token',
redirectUri: 'http://localhost:4200/callback',
scope: 'openid profile'
});
constructor(public router: Router) {
this._idToken = '';
this._accessToken = '';
this._expiresAt = 0;
}
public login(): void {
this.auth0.authorize();
}
public handleAuthentication(): void {
this.auth0.parseHash((err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
window.location.hash = '';
this.localLogin(authResult);
this.router.navigate(['/']);
} else if (err) {
this.router.navigate(['/']);
console.log(err);
}
});
}
public getProfile(cb): void {
if (!this._accessToken) {
throw new Error('Access Token must exist to fetch profile');
}
const self = this;
this.auth0.client.userInfo(this._accessToken, (err, profile) => {
if (profile) {
self.userProfile = profile;
}
cb(err, profile);
});
}
private localLogin(authResult): void {
localStorage.setItem('isLoggedIn', 'true');
const expiresAt = (authResult.expiresIn * 1000) + new Date().getTime();
this._accessToken = authResult.accessToken;
this._idToken = authResult.idToken;
this._expiresAt = expiresAt;
}
public renewTokens(): void {
this.auth0.checkSession({}, (err, authResult) => {
if (authResult && authResult.accessToken && authResult.idToken) {
this.localLogin(authResult);
} else if (err) {
alert(`Could not get a new token (${err.error}: ${err.error_description}).`);
this.logout();
}
});
}
public logout(): void {
this._accessToken = '';
this._idToken = '';
this._expiresAt = 0;
localStorage.removeItem('isLoggedIn');
this.router.navigate(['/']);
}
public isAuthenticated(): boolean {
return new Date().getTime() < this._expiresAt;
}
get accessToken(): string {
return this._accessToken;
}
get idToken(): string {
return this._idToken;
}
}
我在我的页面上点击登录,我成功了,我得到了令牌,一切都很好。但是,当我刷新页面或单击 link 时,它会被注销。我应该怎么做才能保持登录状态?
当前,您正在将数据保存在内存变量中。因此,当您重新加载应用程序时,内存变量 (_expiresAt) 丢失了值。因此,isAuthenticated() 方法 returns false。您可以将数据保存在浏览器localStorage中。
private localLogin(authResult): void {
const expiresAt = JSON.stringify(
authResult.expiresIn * 1000 + new Date().getTime()
);
localStorage.setItem("access_token", authResult.accessToken);
localStorage.setItem("id_token", authResult.idToken);
localStorage.setItem("expires_at", expiresAt);
}
然后,在 isAuthenticated() 方法中,您可以从 localStorage 加载 expiresAt。
public isAuthenticated(): boolean {
const expiresAt = JSON.parse(localStorage.getItem("expires_at") || "{}");
return new Date().getTime() < expiresAt;
}
登出过程中,需要清除localStorage中的数据。
public logout(): void {
// Remove tokens and expiry time from localStorage
localStorage.removeItem("access_token");
localStorage.removeItem("id_token");
localStorage.removeItem("expires_at");
// Remove server SSO session
this.auth0.logout({ returnTo: "http://localhost:4200" });
}
最佳实践:
对于 SPA,请遵循 auth0 最佳实践:https://auth0.com/docs/security/store-tokens#single-page-apps