How to handle hash fragments from oauth redirect urls in Angular2 rc3 routing

倾然丶 夕夏残阳落幕 提交于 2019-11-30 12:14:57
NColey

I was eventually able to find a solution that uses the preferred PathLocationStrategy but also pulls the token out of the oauth redirect uri before the part of the url after the hash fragment is dropped (from the final answer here which is pulled from the QueryParams and Fragment section in the following blog post).

Essentially I updated the redirect url when registering my application with doorkeeper/oauth2 to be http://localhost:4200/login/ (which leads the redirect url containing the token to look like http://localhost:4200/login/#access_token=TOKEN) and added the following route:

{
  path: 'login',
  component: LoginComponent
}

This catches the redirect url but drops everything after the hash fragment, removing the token I needed. To prevent it from dropping everything after the hash fragment I added the following code to the constructor of my 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);
});

}

How exactly you choose to handle the token is up to you (I have a TokenService with methods to set, retrieve, and clear it from localStorage) but this is how you access the portion of the url after the hash fragment. Feel free to update/post here if anyone has a better solution.

UPDATE: Small update to the above login component code to deal with 'fragment is possibly null' typescript errors in Angular v4.2.0 & strictNullChecks set to true in the tsconfig.json in case anyone needs it. Functionality is the same:

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);
}

Note: Since RxJS 6, the map operator has been made pipeable which means that you have to pass it in the pipe method of Observable as seen below:

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);
    }
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!