简体   繁体   English

Auth0和Angular 2:使用登录小部件登录和路由失败

[英]Auth0 and Angular 2: login and routing failing using the login widget

I am starting to develop web applications and chose Angular 2 as the front-end framework. 我开始开发Web应用程序,并选择Angular 2作为前端框架。 I'm currently trying out Auth0 for user authorisation. 我目前正在尝试使用Auth0进行用户授权。 The problem is as follows: I am trying to implement a landing page login -> redirect functionality. 问题如下:我正在尝试实现登录页面登录->重定向功能。 Immediately after opening the website it should check if there is a user's token in the localStorage and then either show the login widget or redirect to the home page. 打开网站后,应立即检查localStorage是否有用户令牌,然后显示登录小部件或重定向到主页。 But I have ran into this very nasty bug: 但是我遇到了一个非常讨厌的错误:

When i'm logging in, the page refreshes and the widget appears again: tokenNotExpired() for some reason returns false . 当我登录时,页面刷新,并且小部件再次出现: tokenNotExpired()由于某种原因返回false I press to login again with the same credentials - page refreshes, login widget disappears, logging shows that tokenNotExpired() is returning true now, but my redirect still doesn't work. 我按相同的凭据再次登录-页面刷新,登录小部件消失,日志记录显示tokenNotExpired()现在返回true ,但是我的重定向仍然无效。 If I now just enter my base address, http://localhost:4200 , it successfully redirects me to home and tokenNotExpired() returns true . 如果现在仅输入我的基本地址http://localhost:4200 ,它将成功将我重定向到hometokenNotExpired()返回true

I tried debugging it but without any luck - I can't find where it is failing. 我尝试调试它,但没有任何运气-我找不到它出故障的地方。

Essentially, I am very sure there are problems in the way I approach coding the redirect feature, since my lack of experience. 本质上,由于缺乏经验,我非常确定在编码重定向功能时会遇到问题。 I would very kindly appreciate any help, been sitting on this for a while. 一直以来,我都非常感谢您的帮助。

I'm including excerpts of my code omitting the redundant parts. 我包括我的代码节选,省略了多余的部分。 I am injecting the Auth service globally by bootstrapping it in main.ts. 我正在通过在main.ts中引导引导服务来全局注入Auth服务。

app.routes.ts: app.routes.ts:

import {provideRouter, RouterConfig} from "@angular/router";
import {AuthGuard} from './secure/auth.guard';
import {AdminGuard} from "./secure/admin.guard";

import {UserHomeComponent} from "./main/user-cpl/user-home.component";
import {AdminHomeComponent} from "./main/admin-cpl/admin-home.component";
import {LoginPageComponent} from "./login/login-page.component";

const APP_ROUTES: RouterConfig = [

  { path: 'home', canActivate: [AuthGuard],
    children: [
      { path: '', component: UserHomeComponent },
      { path: 'admin', component: AdminHomeComponent, canActivate: [AdminGuard] },
      ] },
  { path: 'login', component: LoginPageComponent },
  { path: '', redirectTo: 'home', pathMatch: 'full' },
  { path: '**', redirectTo: 'home', pathMatch: 'full' }
];

export const APP_ROUTES_PROVIDER = [
  provideRouter(APP_ROUTES)
];

login-page.component.ts: 登录-page.component.ts:

import {Component, OnInit} from '@angular/core';
import {ROUTER_DIRECTIVES, Router} from '@angular/router';
import {Auth} from '../secure/auth.service';

@Component({
  moduleId: module.id,
  selector: 'login-page-component',
  template: `
    <router-outlet></router-outlet>  
  `,
  directives: [ROUTER_DIRECTIVES]
})
export class LoginPageComponent implements OnInit {

  constructor(private auth: Auth, private router: Router) {
  }

  ngOnInit():any {
    console.log('LOGGED IN - ' + this.auth.loggedIn());
    if (this.auth.loggedIn()) {
      if (this.auth.isAdmin()) {
        this.router.navigate(['/home/admin']);
      } else if (!this.auth.isAdmin()) {
        this.router.navigate(['/home']);
      }

    } else {
      this.auth.login();
    }
  }
}

auth.service.ts: auth.service.ts:

import {Injectable} from '@angular/core';
import {tokenNotExpired} from 'angular2-jwt';

declare var Auth0Lock: any;

@Injectable()
export class Auth {
  // Configure Auth0
  lock = new Auth0Lock('omitted', 'omitted', {
    closable: false
  });

  //Store profile object in auth class
  userProfile: any;

  constructor() {
    // Set userProfile attribute if already saved profile
    this.userProfile = JSON.parse(localStorage.getItem('profile'));

    // Add callback for lock `authenticated` event
    this.lock.on("authenticated", (authResult) => {
      localStorage.setItem('id_token', authResult.idToken);

      // Fetch profile information
      this.lock.getProfile(authResult.idToken, (error, profile) => {
        if (error) {
          // Handle error
          alert(error);
          return;
        }

        localStorage.setItem('profile', JSON.stringify(profile));
        this.userProfile = profile;
      });
    });
  }

  login() {
    this.lock.show({
      callbackUrl: 'http://localhost:4200/home'
    });
  }

  logout() {
    localStorage.removeItem('profile');
    localStorage.removeItem('id_token');
    this.userProfile = undefined;
  }

  loggedIn() {
    return tokenNotExpired();
  }

  isAdmin() {
    return this.userProfile && this.userProfile.app_metadata
      && this.userProfile.app_metadata.roles
      && this.userProfile.app_metadata.roles.indexOf('admin') > -1;
  }
}

auth.guard.ts: auth.guard.ts:

import {Injectable} from '@angular/core';
import {Router, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';
import {CanActivate} from '@angular/router';
import {Auth} from './auth.service';

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private auth: Auth, private router: Router) {
  }

  canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    if (this.auth.loggedIn()) {
      console.log('AUTH GUARD PASSED');
      return true;
    } else {
      console.log('BLOCKED BY AUTH GUARD');
      this.router.navigate(['/login']);
      return false;
    }
  }
}

admin.guard.ts: admin.guard.ts:

import {Injectable} from '@angular/core';
import {Router, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';
import {CanActivate} from '@angular/router';
import {Auth} from './auth.service';

@Injectable()
export class AdminGuard implements CanActivate {

  constructor(private auth: Auth, private router: Router) {}

  canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
    if (this.auth.isAdmin()) {
      return true;
    } else {
      return false;
    }
  }
}

You must set redirect: false in the configuration since it is a single page app. 您必须在配置中设置redirect: false ,因为它是单页应用程序。 Auth0 will otherwise make a GET call to the redirectUrl . 否则,Auth0将对redirectUrl进行GET调用。 This call is preventing your authenticated event from firing up. 此呼叫阻止您通过authenticated事件触发。 Thus, in your auth.service.ts file: 因此,在您的auth.service.ts文件中:

lock = new Auth0Lock('omitted', 'omitted', {
  closable: false,
  auth: { // <--- mind this nesting
    redirect: false
  }
});

This will invoke the 'authenticated' event in the service on login. 这将在登录时在服务中调用“已验证”事件。 You probably also want to redirect the user once login is done. 登录完成后,您可能还希望重定向用户。 Thus, in the callback invoke this._router.navigate(['path']) . 因此,在回调中调用this._router.navigate(['path']) Don't forget to import { Router } from 'angular/router' and creating an instance in the constructor: constructor(private _router: Router) {} . 不要忘记import { Router } from 'angular/router'并在构造函数中创建实例: constructor(private _router: Router) {}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM