web-dev-qa-db-ja.com

oauth Angular2rc3ルーティングのリダイレクトURLからのハッシュフラグメントを処理する方法

ハッシュフラグメントで始まるルートを処理するAngular2TypeScriptルート(3.0.0-alpha.8ルーターを使用)の設定を処理する方法を見つけようとしています。

私が取り組んでいるアプリは、Railsバックエンドとoauth2を介して、すべてのログインを外部で処理します(制御できません)。ユーザーを外部ログインページにリダイレクトすることは問題なく機能しますが、リダイレクトURLが常に何らかの形式の_http://localhost:4200#access_token=TOKEN_(TOKENは一連の数字と文字)が返送されますが、_#_記号を処理できるルートを設定する方法がわからないため、キャッチできますそれを適切なコンポーネントにリダイレクトします。

以前のAngular1アプリでは、_ui-router_は次のルートで使用できました。

_.state('accessToken', {
  url: '/access_token=:token',
  controller: 'LoginController',
  params: { token: null }
})
_

これにより、返送されたリダイレクトURLを受け入れることに問題はなく、すべてをLoginControllerに渡して、フロントエンドで残りの認証/トークンビジネスを処理しました。

ただし、このアプリはAngular2とTypeScriptであり、ルーターのクエリパラメーターの柔軟性がはるかに低いようで、同様のソリューションの実装に問題があります。私はドキュメントの このセクション に基づいていますが、すべての例は、クエリパラメータの複雑な部分に到達する前に、ex _/heroes_などの他の何かを構築しています。ex_/heroes/:id_。 stackoverflowも検索しましたが、Angular2とTypeScript、および現在のルーターで機能するものは見つかりませんでした。

これは私の現在の(機能していない)解決策です:

_import { provideRouter, RouterConfig } from '@angular/router';

import { HomeComponent } from './components/home/home.component';
import { TestComponent } from './components/test/test.component';


export const appRoutes: RouterConfig = [
  {
    path: '',
    component: HomeComponent,
    terminal: true
  },
  {
    path: 'access_token',
    component: TestComponent
  }
];

export const APP_ROUTER_PROVIDERS = [
  provideRouter(appRoutes)
];
_

返送されたリダイレクトURLを(純粋にテスト目的で)_http://localhost:4200/access_token=TOKEN_のようなものに変更すると、正常に機能します。残念ながら、実際にはリダイレクトURLの形式を制御することはできず、_/_ではなくハッシュフラグメントで始まるという事実を処理できるソリューションを思い付くことができません。次に、私のクエリパラメータ。私が見つけることができる複雑な記号または文字を使用したルーティングの例はすべて、_/_で始まります。

上記のソリューションを_:access_token_に変更しようとしましたが、これは機能しませんでした。また、次のようにベースルートの下に子ルートとしてリストしました。

_{
  path: '',
  component: HomeComponent,
  terminal: true,
  children: [
    { path: 'access_token',  component: TestComponent },
  ]
}
_

その結果、次のコンソールエラーが発生しました:platform-browser.umd.js:2312 EXCEPTION: Error: Uncaught (in promise): Error: Cannot match any routes: ''

特に、非常に多くのAPIがこのようなリダイレクトURLを介して認証を処理するため、これに対するクリーンなソリューションが絶対に必要だと感じていますが、ドキュメントをいくら調べても、それを見つけることができないようです。これを実装する方法についてのアドバイスをいただければ幸いです。

11
NColey

最終的に、優先PathLocationStrategyを使用するだけでなく、ハッシュフラグメントがドロップされた後のURLの一部の前にoauth redirect uri)からトークンを引き出すソリューションを見つけることができました(最終的な回答から) here これは次のQueryParams and Fragmentセクションから取得されます ブログ投稿 )。

基本的に、アプリケーションをdoorkeeper/oauth2に登録するときにリダイレクトURLを http:// localhost:4200/login / に更新しました(これにより、トークンを含むリダイレクトURLはhttp://localhost:4200/login/#access_token=TOKENのようになります。 )そして次のルートを追加しました:

{
  path: 'login',
  component: LoginComponent
}

これはリダイレクトURLをキャッチしますが、ハッシュフラグメントの後のすべてを削除し、必要なトークンを削除します。ハッシュフラグメントの後にすべてがドロップされないようにするために、LoginComponentのコンストラクターに次のコードを追加しました。

constructor(private activatedRoute: ActivatedRoute, 
            private router: Router, 
            private tokenService: TokenService) {

// Pulls token from url before the hash fragment is removed

const routeFragment: Observable<string> = activatedRoute.fragment;
routeFragment.subscribe(fragment => {
  let token: string = fragment.match(/^(.*?)&/)[1].replace('access_token=', '');
  this.tokenService.setToken(token);
});

}

トークンの処理をどの程度正確に選択するかはあなた次第です(localStorageからトークンを設定、取得、クリアするメソッドを備えたTokenServiceがあります)が、これがハッシュフラグメントの後のURLの部分にアクセスする方法です。誰かがより良い解決策を持っているなら、ここで更新/投稿してください。

更新:上記のログインコンポーネントコードを少し更新して、「フラグメントがnullである可能性があります」Angular v4.2.0&strictNullChecksが必要な場合に備えてtsconfig.jsonでtrueに設定されている。機能は同じです:

let routeFragment = this.activatedRoute.fragment.map(fragment => fragment);

routeFragment.subscribe(fragment => {
  let f = fragment.match(/^(.*?)&/);
  if(f) {
   let token: string = f[1].replace('access_token=', '');
   this.tokenService.setToken(token);
}

注:RxJS 6以降、map演算子はパイプ可能になりました。つまり、以下に示すように、pipeObservableメソッドで渡す必要があります。

import { map } from 'rxjs/operators';

// ...

this.activatedRoute.fragment
  .pipe(map(fragment => fragment))
  .subscribe(fragment => {
    let f = fragment.match(/^(.*?)&/);
    if(f) {
      let token: string = f[1].replace('access_token=', '');
      this.tokenService.setToken(token);
    }
15
NColey