我第一次使用 Angular 测试 Auth0 并遇到了问题。我让我的用户通过 Auth0 登录,在他们登录后,我将他们重定向到受 Auth0 保护的仪表板页面。我已设法重定向用户,但在他们登录后,URL 显示用户在仪表板路线上,但他们看不到实际的仪表板内容。我试图查看发生了什么,我认为问题在于用户已登录,但 auth guard 布尔值从未设置为 true,这使我的程序不断刷新 URL。当我将身份验证防护从路由中移除时,重定向会起作用并显示内容。我玩过代码,希望能弄明白,但到目前为止还没有运气。
如果我必须分享更多代码,我将分享我的代码,请告诉我。
app.module.ts
const appRoutes: Routes = [
{ path: 'app-dashboard', component: DashboardComponent,
canActivate: [AuthGuard]
},
{ path: 'login', component: LoginComponent },
{ path: 'app-shell-start', component: ShellStartComponent },
{
path: '',
redirectTo: '/app-shell-start',
pathMatch: 'full'
},
];
auth.guard.ts
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private auth: AuthService, public router:Router) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean> | Promise<boolean|UrlTree> | boolean {
console.log("start")
return this.auth.isAuthenticated$.pipe(
tap(loggedIn => {
console.log("loggedIn",loggedIn)
this.router.navigate(['']);
if (!loggedIn) {
this.auth.login(state.url);
}
})
);
}
}
auth.services.spec.ts
import { TestBed } from '@angular/core/testing';
import { AuthService } from './auth.service';
describe('AuthService', () => {
let service: AuthService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AuthService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});
auth.service.ts
@Injectable({
providedIn: 'root'
})
export class AuthService {
// Create an observable of Auth0 instance of client
auth0Client$ = (from(
createAuth0Client({
domain: "techradartest.eu.auth0.com",
client_id: "KxM7ICZKf08Mt5czJnxxD3a47HwH3jE1",
redirect_uri: "http://localhost:4200/app-dashboard" // `${window.location.origin}`
})
) as Observable<Auth0Client>).pipe(
shareReplay(1), // Every subscription receives the same shared value
catchError(err => throwError(err))
);
// Define observables for SDK methods that return promises by default
// For each Auth0 SDK method, first ensure the client instance is ready
// concatMap: Using the client instance, call SDK method; SDK returns a promise
// from: Convert that resulting promise into an observable
isAuthenticated$ = this.auth0Client$.pipe(
concatMap((client: Auth0Client) => from(client.isAuthenticated())),
tap(res => this.loggedIn = res)
);
handleRedirectCallback$ = this.auth0Client$.pipe(
concatMap((client: Auth0Client) => from(client.handleRedirectCallback()))
);
// Create subject and public observable of user profile data
private userProfileSubject$ = new BehaviorSubject<any>(null);
userProfile$ = this.userProfileSubject$.asObservable();
// Create a local property for login status
loggedIn: boolean = null;
constructor(private router: Router) {
// On initial load, check authentication state with authorization server
// Set up local auth streams if user is already authenticated
this.localAuthSetup();
// Handle redirect from Auth0 login
this.handleAuthCallback();
}
// When calling, options can be passed if desired
// https://auth0.github.io/auth0-spa-js/classes/auth0client.html#getuser
getUser$(options?): Observable<any> {
return this.auth0Client$.pipe(
concatMap((client: Auth0Client) => from(client.getUser(options))),
tap(user => this.userProfileSubject$.next(user))
);
}
private localAuthSetup() {
// This should only be called on app initialization
// Set up local authentication streams
const checkAuth$ = this.isAuthenticated$.pipe(
concatMap((loggedIn: boolean) => {
if (loggedIn) {
// If authenticated, get user and set in app
// NOTE: you could pass options here if needed
return this.getUser$();
}
// If not authenticated, return stream that emits 'false'
return of(loggedIn);
})
);
checkAuth$.subscribe();
}
login(redirectPath: string = '/') {
// A desired redirect path can be passed to login method
// (e.g., from a route guard)
// Ensure Auth0 client instance exists
this.auth0Client$.subscribe((client: Auth0Client) => {
// Call method to log in
client.loginWithRedirect({
redirect_uri: "http://localhost:4200/app-dashboard", //`${window.location.origin}`,
appState: { target: redirectPath }
});
});
}
private handleAuthCallback() {
// Call when app reloads after user logs in with Auth0
const params = window.location.search;
debugger;
if (params.includes('code=') && params.includes('state=')) {
console.log("loggedIn handleAuthCallback")
let targetRoute: string; // Path to redirect to after login processsed
const authComplete$ = this.handleRedirectCallback$.pipe(
// Have client, now call method to handle auth callback redirect
tap(cbRes => {
// Get and set target redirect route from callback results
targetRoute = cbRes.appState && cbRes.appState.target ? cbRes.appState.target : '/';
}),
concatMap(() => {
// Redirect callback complete; get user and login status
return combineLatest([
this.getUser$(),
this.isAuthenticated$
]);
})
);
// Subscribe to authentication completion observable
// Response will be an array of user and login status
authComplete$.subscribe(([user, loggedIn]) => {
// Redirect to target route after callback processing
console.log("targetRoute: ",targetRoute)
this.router.navigate([targetRoute]);
});
}
}
logout() {
// Ensure Auth0 client instance exists
this.auth0Client$.subscribe((client: Auth0Client) => {
// Call method to log out
client.logout({
client_id: "KxM7ICZKf08Mt5czJnxxD3a47HwH3jE1",
returnTo: `${window.location.origin}`
});
});
}
}
我正在使用 Angular 9