Angular Auth0 после входа в систему защищенная страница авторизации не отображается после перенаправления - PullRequest
1 голос
/ 17 февраля 2020

Я тестирую Auth0 с angular впервые и столкнулся с проблемой. Я разрешаю моему пользователю войти в систему через Auth0, и после того, как они войдут в систему, я перенаправлю их на страницу панели управления, защищенную Auth0 guard. Мне удалось перенаправить пользователя, но после входа в систему URL-адрес показывает, что пользователь находится на маршруте панели мониторинга, однако он не может видеть фактическое содержимое панели мониторинга. Я попытался увидеть, что происходит, и я думаю, что проблема в том, что пользователь вошел в систему, но логическое значение auth guard никогда не устанавливается в значение true, что заставляет мою программу постоянно обновлять sh 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.spe c .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

...