Путь обратного вызова Angular Routing и 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, загружается общедоступный путь. Для меня это имеет смысл, потому что шаблон URL соответствует "" пути, поэтому он перенаправляется на "общедоступный" путь и загружает его. Это отлично работает, поскольку мой общедоступный путь загружается правильно.

Проблема, с которой я сталкиваюсь, возникает, когда я аутентифицирую Auth0, который вызывает URL-адрес обратного вызова, определенный как localhost: 4200 / callback, после того, как пользователь был аутентифицирован. Я бы подумал, что этот URL-адрес соответствует маршруту «обратного вызова» и должен загружать CallbackComponent. К сожалению, это не так, и он снова загружает общедоступный путь.

Мой CallbackComponent определен в моем AuthModule (куда он также экспортируется), который, очевидно, является отдельным модулем. В моем эксперименте нет проблем с загрузкой компонента на страницах AppModule, поэтому я не думаю, что этот компонент в другом модуле является проблемой, но решил, что упомянул бы об этом, если это так.

ВОПРОСЫ

1) Почему, черт возьми, путь «обратного вызова» не загружается, когда URL-адрес localhost: 4200 / callback?

2) Auth0 будет передавать информацию токена и любые ошибки обратно на тот же URL-адрес в строке запроса после хэша (например, localhost: 4200 / callback # error = ... или, в случае успеха, localhost: 4200 / callback # access_token = ... ). Повлияет ли это на сопоставление путей? Если да, то к чему мне обновить свой путь, чтобы справиться с этим? Если нет, я считаю, что часть URL-адреса будет считаться фрагментом, поэтому я просто получаю эту информацию из activeRoute или есть какой-то другой способ обработки фрагментов в маршрутах?

Заранее благодарю за любую помощь.

ОБНОВЛЕНИЕ

Я прикрепляю блоки трассировки маршрутизатора, чтобы показать, что именно я вижу:

Во-первых, это события навигации, когда я перехожу к корневому 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"}

По сути, это то же самое, за исключением начального значения Navigated to.


person JakeHova    schedule 27.01.2018    source источник
comment
не могли бы вы опубликовать, какую ошибку вы получаете в инструментах разработчика браузера? а как ты по url собираешься? вы используете routerlink или просто набираете текст в строке поиска браузера? Также пути чувствительны к регистру.   -  person Vato    schedule 27.01.2018
comment
Ошибки нет. Я включил трассировку в RouterModule, и он вообще ничего не говорит о маршруте обратного вызова. Он переходит прямо к пустому маршруту по умолчанию. Я попытался перейти по маршруту, просто вставив URL-адрес в панель браузера, но при фактическом использовании Auth0 будет вызывать URL-адрес с некоторыми хеш-значениями после URL-адреса, который мне нужно проанализировать, чтобы получить информацию о пользователе для аутентификации.   -  person JakeHova    schedule 27.01.2018
comment
что произойдет, если вы введете любой другой нелегальный маршрут? в основном он переходит на страницу, не найденную ** компонент пути?   -  person Vato    schedule 27.01.2018
comment
На самом деле, даже в тех случаях, когда я указываю путь, которого не существует, он все равно перенаправляется на общедоступный маршрут.   -  person JakeHova    schedule 27.01.2018
comment
не могли бы вы попробовать использовать вместо? все остальное мне кажется хорошо в коде.   -  person Vato    schedule 27.01.2018
comment
Я попробовал то, что вы предложили, и все равно не повезло. Я также попытался изменить все на прямые компоненты вместо ленивой загрузки модулей, и это тоже не сработало. Я здесь в полной растерянности   -  person JakeHova    schedule 27.01.2018


Ответы (2)


Из того, что я видел, может быть проблема.

Вы должны использовать "" вместо "". Убедитесь, что у вас есть index.html. Также имеет значение порядок путей. Я думаю, вы правильно поняли. Я не уверен, насколько это важно, но вы экспортируете МАРШРУТЫ вместо Routemodule. Попробуйте создать 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]
  })

Проблема где-то здесь

В обоих роутерах вы получаете

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 и узнайте, как они реализуют идентификаторы для героев. Но для жетонов все может быть иначе.

Это все, что у меня есть на данный момент. Удачи! Я постараюсь больше помочь, если вы будете размещать обновления.

person Vato    schedule 27.01.2018
comment
Если AppModule является основным модулем приложения и нет промежуточных общих модулей, я думаю, что AppComponent не следует экспортировать в AppModule, а модуль должен быть закрыт с помощью: export class AppModule {} - person Kristian; 27.01.2018
comment
Спасибо, что посмотрели на это. Я переместил маршрутизацию в свой собственный модуль (на самом деле у меня это было раньше, но я перемещал его в основной модуль на случай, если это была проблема), я изменил все кавычки на одинарные кавычки, я удалил свойство экспорта (у меня это было изначально, потому что Я находился в основной среде .NET, в которой был модуль браузера, расположенный выше AppModule. С тех пор я сделал проект автономным, поэтому в экспорте больше не было необходимости). Но все равно не повезло. Я даже не уверен, что мне нужно искать на этом этапе. - person JakeHova; 27.01.2018
comment
@JakeHova, пожалуйста, не могли бы вы создать какой-нибудь плункер, кроме того, что вы можете настроить этот код как полезный? - person Kristian; 27.01.2018
comment
Меня сейчас нет дома, но когда я вернусь, я постараюсь воссоздать его в plunkr. Я использую Angular CLI 1.6.5 и angular 5.2.0, если это помогает. - person JakeHova; 27.01.2018
comment
Я понял, что случилось. У меня есть это угловое решение внутри основного приложения .net. Основное приложение, по сути, действует как оболочка. Я настроил его на обработку ПОЧТИ всего как маршрута, который должен обрабатывать angular. Оказывается, ранее я перехватил обратный вызов, чтобы получить учетные данные в сеансе приложения .net, а затем передать их на другую страницу FE, которой у меня больше не было. Вот почему он продолжал возвращаться к корневой странице. Я собираюсь отметить это как ответ, потому что он предоставил больше всего информации, но настоящий ответ заключается в том, что мне нужно быть более осторожным. - person JakeHova; 28.01.2018

Только для того, чтобы продлить действительный ответ Вато:

Ваш основной модуль приложения должен экспортировать себя, а не его компонент следующим образом:

import { whatever } from "anywhere";

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