Angular2 Redirect After Login

Another way (WITHOUT using query parameters using @angular/router 3.0.0) to achieve the same requirement of redirecting to the original requested resource after authentication is to use RouterStateSnapshot.url, which is a string that contains the url of the resource the user requested. Before redirecting user back to your login form after a failed authentication attempt, inside of the CanActivate hook, get the requested url from RouterStateSnapshot.url and store it in a variable that is accessible to your login function. When the user logs in successfully simply redirect to the stored URL. Here's my example:

//GuardService - implements CanActivate hook for the protected route

import { Injectable } from '@angular/core';
import { CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { AuthService } from './auth.service';

@Injectable()
export class GuardService implements CanActivate {
    constructor( private router: Router, private authService: AuthService ) {}

    canActivate(state: RouterStateSnapshot): boolean {
        let url: string = state.url;
        return this.checkLogin(url);
    }

    checkLogin(url: string): boolean {
        if (this.authService.loggedIn()) { return true; }
        this.authService.redirectUrl = url; // set url in authService here
        this.router.navigate([ '/login' ]); // then ask user to login
        return false;
    }

}

My AuthService (below), which performs the login, will redirect user to the originally requested resource on successful login.

import { Injectable, Inject } from '@angular/core';
import { tokenNotExpired } from 'angular2-jwt';
import { Router } from '@angular/router';
import { Headers, Http, Response, RequestOptions  } from '@angular/http';
import { Observable } from 'rxjs';
import './../rxjs-operators';

const API_URL: string = '';

@Injectable()
export class AuthService {
    public redirectUrl: string = ''; //Here is where the requested url is stored

constructor( @Inject('API_URL') private apiURL: string, private router: Router, private http: Http ) {}

    public loggedIn(): boolean {
        return tokenNotExpired('token');
    }

    public authenticate(username: string, password: string)  {
        let body: string = JSON.stringify({ un: username, pw: password});
        let headers: Headers = new Headers({ 'Content-Type': 'application/json' });
        let options: RequestOptions = new RequestOptions({ headers: headers });
        return this.http.post(this.apiURL + '/authenticate', body, options)
            .map(res => res.json())
            .subscribe(res => {
                localStorage.setItem('token',res.token);
                this.redirect(); // Redirect to the stored url after user is logged in
            });

        .catch(this.handleError);
    }

    private redirect(): void {
        this.router.navigate([ this.redirectUrl ]); //use the stored url here
    }
}

This is how your application can remember the originally requested resource WITHOUT using query parameters.

For more details please see the example guide at angular.io starting at the "GUARD THE ADMIN FEATURE" section: https://angular.io/guide/router#guard-the-admin-feature

Hope this helps someone.


Yes there is a way:

let url = router.generate(['./Login', {next: nextInstr.urlPath}]).toRootUrl();

Lets say following structure example depending on routeconfig:

login?next=my-redirect-url

And then you use navigateByUrl to navigate to following url

router.navigateByUrl('/' + url);

I have tested it with my example and result you can see on image:

let instruction = router.generate(['./Country', {country: 'de', a: 1, b: 2}]);
console.log(instruction, instruction.toRootUrl());

enter image description here