Angular路由回调路径和auth0

Angular Routing callback path and auth0

背景:

我正在尝试一个 angular 应用程序,但我在思考路由时遇到了一个大问题。

我有 2 个问题需要解决,这些问题我已经苦苦思索了好几天,此时,我只是在兜圈子,浪费时间。

详情:

我在根应用程序模块中定义了一个路由树,如下所示:

export const ROUTES: Routes = [  
  { 
    path: "callback",  
    component: CallbackComponent
  },
  {
    path: "secure",
    loadChildren: "./secure/secure.module#SecureModule",
    canActivate: [AuthGuard]
  },  
  {
    path: "public",
    loadChildren: "./public/public.module#PublicModule"
  }, 
  {
    path: "",
    redirectTo: "public",    
    pathMatch: "full"
  },
  { path: "**", component: PageNotFoundComponent }
];

@NgModule({
  declarations: [AppComponent, PageNotFoundComponent],  
  imports: [    
    AuthModule,
    BrowserModule,
    BrowserAnimationsModule,    
    HttpClientModule,
    RouterModule.forRoot(ROUTES, {enableTracing: (environment.production === false)}),
    StoreModule.forRoot(reducers, { metaReducers }), //sets the entire app up to use ngrx store and applies the metaReducers class as a parent to all reducers used throughout the system. this helps with the debug tools
    EffectsModule.forRoot(effects),
    StoreRouterConnectingModule,
    environment.production === false ? StoreDevtoolsModule.instrument() : [],
  ],
  providers: [
    { provide: ErrorHandler, useClass: AppServices.RollbarErrorHandler },
    {
      provide: AppServices.RollbarService,
      useFactory: AppServices.rollbarFactory
    }
  ],
  exports: [AppComponent, PageNotFoundComponent]
})

当我第一次使用 URL localhost:4200 加载我的应用程序时,public 路径被加载。这对我来说很有意义,因为 URL 模式匹配“”路径,因此它被重定向到 "public" 路径并加载它。这工作正常,因为我的 public 路径已正确加载。

当我针对 Auth0 进行身份验证时,我遇到了这个问题,它在用户通过身份验证后调用定义为 localhost:4200/callback 的回调 URL。我会认为这个 URL 匹配 "callback" 路由并且应该加载 CallbackComponent。不幸的是,它没有,它再次加载 public 路径。

我的 CallbackComponent 是在我的 AuthModule 中定义的(它也在那里导出),这显然是一个单独的模块。在我的实验中,在 AppModule 页面中加载组件没有问题,所以我不认为这个组件在另一个模块中是一个问题,但我想我会提到它以防万一。

问题

1) 当 URL 是 localhost:4200/callback 时,为什么 "callback" 路径没有加载?

2) Auth0 将在哈希后将令牌信息和任何错误传递回查询字符串中的相同 URL(例如 localhost:4200/callback#error=... 或者,成功时, localhost:4200/回调#access_token=...)。这会影响路径匹配吗?如果是这样,我应该如何更新我的路径来处理这个问题?如果不是,我相信 URL 的一部分将被视为一个片段,所以我只是从 activatedRoute 中获取该信息,或者我是否缺少其他方式来处理路由中的片段?

在此先感谢您的帮助。

更新

我正在附加路由器跟踪块以显示我所看到的内容:

首先是导航到根目录时的导航事件URL

Navigated to http://localhost:4200/
platform-browser.js:380 Router Event: NavigationStart
platform-browser.js:367 NavigationStart(id: 1, url: '/')
platform-browser.js:367 NavigationStart {id: 1, url: "/"}
platform-browser.js:380 Router Event: RouteConfigLoadStart
platform-browser.js:367 RouteConfigLoadStart(path: public)
platform-browser.js:367 RouteConfigLoadStart {route: {…}}
core.js:3675 Angular is running in the development mode. Call enableProdMode() to enable the production mode.
platform-browser.js:380 Router Event: RouteConfigLoadEnd
platform-browser.js:367 RouteConfigLoadEnd(path: public)
platform-browser.js:367 RouteConfigLoadEnd {route: {…}}
platform-browser.js:380 Router Event: RoutesRecognized
platform-browser.js:367 RoutesRecognized(id: 1, url: '/', urlAfterRedirects: '/public', state: Route(url:'', path:'') { Route(url:'public', path:'public') { Route(url:'', path:'') { Route(url:'', path:'') }  }  } )
platform-browser.js:367 RoutesRecognized {id: 1, url: "/", urlAfterRedirects: "/public", state: RouterStateSnapshot}
platform-browser.js:380 Router Event: NavigationCancel
platform-browser.js:367 NavigationCancel(id: 1, url: '/')
platform-browser.js:367 NavigationCancel {id: 1, url: "/", reason: ""}
platform-browser.js:380 Router Event: NavigationStart
platform-browser.js:367 NavigationStart(id: 2, url: '/')
platform-browser.js:367 NavigationStart {id: 2, url: "/"}
platform-browser.js:380 Router Event: RoutesRecognized
platform-browser.js:367 RoutesRecognized(id: 2, url: '/', urlAfterRedirects: '/public', state: Route(url:'', path:'') { Route(url:'public', path:'public') { Route(url:'', path:'') { Route(url:'', path:'') }  }  } )
platform-browser.js:367 RoutesRecognized {id: 2, url: "/", urlAfterRedirects: "/public", state: RouterStateSnapshot}
platform-browser.js:380 Router Event: GuardsCheckStart
platform-browser.js:367 GuardsCheckStart(id: 2, url: '/', urlAfterRedirects: '/public', state: Route(url:'', path:'') { Route(url:'public', path:'public') { Route(url:'', path:'') { Route(url:'', path:'') }  }  } )
platform-browser.js:367 GuardsCheckStart {id: 2, url: "/", urlAfterRedirects: UrlTree, state: RouterStateSnapshot}
platform-browser.js:380 Router Event: ChildActivationStart
platform-browser.js:367 ChildActivationStart(path: '')
platform-browser.js:367 ChildActivationStart {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ActivationStart
platform-browser.js:367 ActivationStart(path: 'public')
platform-browser.js:367 ActivationStart {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ChildActivationStart
platform-browser.js:367 ChildActivationStart(path: 'public')
platform-browser.js:367 ChildActivationStart {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ActivationStart
platform-browser.js:367 ActivationStart(path: '')
platform-browser.js:367 ActivationStart {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ChildActivationStart
platform-browser.js:367 ChildActivationStart(path: '')
platform-browser.js:367 ChildActivationStart {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ActivationStart
platform-browser.js:367 ActivationStart(path: '')
platform-browser.js:367 ActivationStart {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: GuardsCheckEnd
platform-browser.js:367 GuardsCheckEnd(id: 2, url: '/', urlAfterRedirects: '/public', state: Route(url:'', path:'') { Route(url:'public', path:'public') { Route(url:'', path:'') { Route(url:'', path:'') }  }  } , shouldActivate: true)
platform-browser.js:367 GuardsCheckEnd {id: 2, url: "/", urlAfterRedirects: UrlTree, state: RouterStateSnapshot, shouldActivate: true}
platform-browser.js:380 Router Event: ResolveStart
platform-browser.js:367 ResolveStart(id: 2, url: '/', urlAfterRedirects: '/public', state: Route(url:'', path:'') { Route(url:'public', path:'public') { Route(url:'', path:'') { Route(url:'', path:'') }  }  } )
platform-browser.js:367 ResolveStart {id: 2, url: "/", urlAfterRedirects: UrlTree, state: RouterStateSnapshot}
platform-browser.js:380 Router Event: ResolveEnd
platform-browser.js:367 ResolveEnd(id: 2, url: '/', urlAfterRedirects: '/public', state: Route(url:'', path:'') { Route(url:'public', path:'public') { Route(url:'', path:'') { Route(url:'', path:'') }  }  } )
platform-browser.js:367 ResolveEnd {id: 2, url: "/", urlAfterRedirects: UrlTree, state: RouterStateSnapshot}
platform-browser.js:380 Router Event: ActivationEnd
platform-browser.js:367 ActivationEnd(path: '')
platform-browser.js:367 ActivationEnd {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ChildActivationEnd
platform-browser.js:367 ChildActivationEnd(path: '')
platform-browser.js:367 ChildActivationEnd {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ActivationEnd
platform-browser.js:367 ActivationEnd(path: '')
platform-browser.js:367 ActivationEnd {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ChildActivationEnd
platform-browser.js:367 ChildActivationEnd(path: 'public')
platform-browser.js:367 ChildActivationEnd {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ActivationEnd
platform-browser.js:367 ActivationEnd(path: 'public')
platform-browser.js:367 ActivationEnd {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ChildActivationEnd
platform-browser.js:367 ChildActivationEnd(path: '')
platform-browser.js:367 ChildActivationEnd {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: NavigationEnd
platform-browser.js:367 NavigationEnd(id: 2, url: '/', urlAfterRedirects: '/public')
platform-browser.js:367 NavigationEnd {id: 2, url: "/", urlAfterRedirects: "/public"}

这是我直接进入回调时的路由器跟踪url:

Navigated to http://localhost:4200/callback
platform-browser.js:380 Router Event: NavigationStart
platform-browser.js:367 NavigationStart(id: 1, url: '/')
platform-browser.js:367 NavigationStart {id: 1, url: "/"}
platform-browser.js:380 Router Event: RouteConfigLoadStart
platform-browser.js:367 RouteConfigLoadStart(path: public)
platform-browser.js:367 RouteConfigLoadStart {route: {…}}
core.js:3675 Angular is running in the development mode. Call enableProdMode() to enable the production mode.
platform-browser.js:380 Router Event: RouteConfigLoadEnd
platform-browser.js:367 RouteConfigLoadEnd(path: public)
platform-browser.js:367 RouteConfigLoadEnd {route: {…}}
platform-browser.js:380 Router Event: RoutesRecognized
platform-browser.js:367 RoutesRecognized(id: 1, url: '/', urlAfterRedirects: '/public', state: Route(url:'', path:'') { Route(url:'public', path:'public') { Route(url:'', path:'') { Route(url:'', path:'') }  }  } )
platform-browser.js:367 RoutesRecognized {id: 1, url: "/", urlAfterRedirects: "/public", state: RouterStateSnapshot}
platform-browser.js:380 Router Event: NavigationCancel
platform-browser.js:367 NavigationCancel(id: 1, url: '/')
platform-browser.js:367 NavigationCancel {id: 1, url: "/", reason: ""}
platform-browser.js:380 Router Event: NavigationStart
platform-browser.js:367 NavigationStart(id: 2, url: '/')
platform-browser.js:367 NavigationStart {id: 2, url: "/"}
platform-browser.js:380 Router Event: RoutesRecognized
platform-browser.js:367 RoutesRecognized(id: 2, url: '/', urlAfterRedirects: '/public', state: Route(url:'', path:'') { Route(url:'public', path:'public') { Route(url:'', path:'') { Route(url:'', path:'') }  }  } )
platform-browser.js:367 RoutesRecognized {id: 2, url: "/", urlAfterRedirects: "/public", state: RouterStateSnapshot}
platform-browser.js:380 Router Event: GuardsCheckStart
platform-browser.js:367 GuardsCheckStart(id: 2, url: '/', urlAfterRedirects: '/public', state: Route(url:'', path:'') { Route(url:'public', path:'public') { Route(url:'', path:'') { Route(url:'', path:'') }  }  } )
platform-browser.js:367 GuardsCheckStart {id: 2, url: "/", urlAfterRedirects: UrlTree, state: RouterStateSnapshot}
platform-browser.js:380 Router Event: ChildActivationStart
platform-browser.js:367 ChildActivationStart(path: '')
platform-browser.js:367 ChildActivationStart {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ActivationStart
platform-browser.js:367 ActivationStart(path: 'public')
platform-browser.js:367 ActivationStart {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ChildActivationStart
platform-browser.js:367 ChildActivationStart(path: 'public')
platform-browser.js:367 ChildActivationStart {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ActivationStart
platform-browser.js:367 ActivationStart(path: '')
platform-browser.js:367 ActivationStart {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ChildActivationStart
platform-browser.js:367 ChildActivationStart(path: '')
platform-browser.js:367 ChildActivationStart {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ActivationStart
platform-browser.js:367 ActivationStart(path: '')
platform-browser.js:367 ActivationStart {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: GuardsCheckEnd
platform-browser.js:367 GuardsCheckEnd(id: 2, url: '/', urlAfterRedirects: '/public', state: Route(url:'', path:'') { Route(url:'public', path:'public') { Route(url:'', path:'') { Route(url:'', path:'') }  }  } , shouldActivate: true)
platform-browser.js:367 GuardsCheckEnd {id: 2, url: "/", urlAfterRedirects: UrlTree, state: RouterStateSnapshot, shouldActivate: true}
platform-browser.js:380 Router Event: ResolveStart
platform-browser.js:367 ResolveStart(id: 2, url: '/', urlAfterRedirects: '/public', state: Route(url:'', path:'') { Route(url:'public', path:'public') { Route(url:'', path:'') { Route(url:'', path:'') }  }  } )
platform-browser.js:367 ResolveStart {id: 2, url: "/", urlAfterRedirects: UrlTree, state: RouterStateSnapshot}
platform-browser.js:380 Router Event: ResolveEnd
platform-browser.js:367 ResolveEnd(id: 2, url: '/', urlAfterRedirects: '/public', state: Route(url:'', path:'') { Route(url:'public', path:'public') { Route(url:'', path:'') { Route(url:'', path:'') }  }  } )
platform-browser.js:367 ResolveEnd {id: 2, url: "/", urlAfterRedirects: UrlTree, state: RouterStateSnapshot}
platform-browser.js:380 Router Event: ActivationEnd
platform-browser.js:367 ActivationEnd(path: '')
platform-browser.js:367 ActivationEnd {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ChildActivationEnd
platform-browser.js:367 ChildActivationEnd(path: '')
platform-browser.js:367 ChildActivationEnd {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ActivationEnd
platform-browser.js:367 ActivationEnd(path: '')
platform-browser.js:367 ActivationEnd {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ChildActivationEnd
platform-browser.js:367 ChildActivationEnd(path: 'public')
platform-browser.js:367 ChildActivationEnd {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ActivationEnd
platform-browser.js:367 ActivationEnd(path: 'public')
platform-browser.js:367 ActivationEnd {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: ChildActivationEnd
platform-browser.js:367 ChildActivationEnd(path: '')
platform-browser.js:367 ChildActivationEnd {snapshot: ActivatedRouteSnapshot}
platform-browser.js:380 Router Event: NavigationEnd
platform-browser.js:367 NavigationEnd(id: 2, url: '/', urlAfterRedirects: '/public')
platform-browser.js:367 NavigationEnd {id: 2, url: "/", urlAfterRedirects: "/public"}

除了初始导航到值外,它基本上完全相同。

据我所知,有几件事可能是问题所在。

您应该使用 ' ' 而不是 ""。 确保你有 index.html 路径的顺序也很重要。我认为你是对的。 我不确定它有多重要,但您导出的是 ROUTES 而不是 routemodule。 尝试创建如下所示的路由模块:

const routes: Routes = [
  { path: 'callback', component: CallbackComponent },
  { path: 'secure', loadChildren: './public/public.module#SecureModule' },
  { path: 'public', loadChildren: './public/public.module#PublicModule' },
  { path: '', redirectTo: '/dashboard', pathMatch: 'full' },
  { path: '**' , component: PageNotFoundComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

并将其导入您的应用程序模块。我也不确定你为什么导出 appComponent,我虽然那里应该有 appmodule。

import { AppRoutingModule } from "./app-router.module";

@NgModule({
    declarations: [AppComponent, PageNotFoundComponent],  
    imports: [    
      AuthModule,
      BrowserModule,
      BrowserAnimationsModule,    
      HttpClientModule,
      AppRoutingModule,
      StoreModule.forRoot(reducers, { metaReducers }), //sets the entire app up to use ngrx store and applies the metaReducers class as a parent to all reducers used throughout the system. this helps with the debug tools
      EffectsModule.forRoot(effects),
      StoreRouterConnectingModule,
      environment.production === false ? StoreDevtoolsModule.instrument() : [],
    ],
    providers: [
      { provide: ErrorHandler, useClass: AppServices.RollbarErrorHandler },
      {
        provide: AppServices.RollbarService,
        useFactory: AppServices.rollbarFactory
      }
    ],
    exports: [AppComponent, PageNotFoundComponent]
  })

问题出在这里

在你们两个 routerTracing 中你都得到

platform-browser.js:367 NavigationStart(id: 1, url: '/')
platform-browser.js:367 NavigationStart {id: 1, url: "/"}

在第二个中你应该得到

platform-browser.js:367 NavigationStart(id: 1, url: '/callback')
platform-browser.js:367 NavigationStart {id: 1, url: "/callback"}

关于你的第二个问题我认为你需要在路径中实现'callback:tocken'。检查 Angular main guide 以及他们如何为英雄实现 id。但这对于代币来说可能有所不同。

这就是我到目前为止所得到的。祝你好运!如果您 post 更新,我会尽力提供更多帮助。

仅用于扩展其他有效的 Vato 答案:

您的主应用模块应该像这样导出自身而不是它的组件:

import { whatever } from "anywhere";

@NgModule({
   declarations: [...],  
   imports: [...],
   providers: [...],
   exports: [...] // exporting no AppComponent here
})
export class AppModule {}  // exports self class after all