3

I am new to Angular 2 and I have the following problem with my routes. My app uses Auth0 for user authentication and i have my main page under http://localhost:3000/ and a profile page under http://localhost:3000/profile.

I had the problem that when refreshing the profile page I got a CANNOT GET error 404. This error I solved using the hash approach

RouterModule.forRoot(appRoutes, { useHash: true })

for my routes as I found in posts like this one: Angular 2 : 404 error occur when i refresh through Browser

My problem now is that with this hash approach I cannot use the login anymore, it returns an error.

EXCEPTION: Uncaught (in promise): Error: Cannot match any routes. URL >Segment: 'access_token' Error: Cannot match any routes. URL Segment: 'access_token' at ApplyRedirects.noMatchError

So I would like to know how can I fix this. My code:

app.routing.ts

import {ModuleWithProviders} from '@angular/core';
import {Routes, RouterModule} from '@angular/router';

import { HomeComponent }  from './components/home/home.component';
import { ProfileComponent }  from './components/profile/profile.component';
import { ItemsComponent }  from './components/items/items.component';

import {AuthGuard} from './auth.guard';

const appRoutes: Routes= [
{
    path:'',
    component: HomeComponent

},
{
    path:'profile',
    component: ProfileComponent,
    canActivate: [AuthGuard]
},
{
    path:'api/items',
    component: ItemsComponent,
    canActivate: [AuthGuard]
}

];



export const appRoutingProviders: any[] = [];


export const routing: ModuleWithProviders = RouterModule.forRoot(appRoutes, { useHash: true });

index.html

 //I skipped copying links and so on

  <body>
    <base href="/">
    <my-app>Loading AppComponent ...</my-app>
  </body>

app.component.ts

import { Component } from '@angular/core';
import {Auth} from './services/auth.service';
import {ItemService} from "./services/itemservice/item.service";

@Component({
  moduleId: module.id,
  selector: 'my-app',
  templateUrl: 'app.component.html',
  providers:[ItemService]
})
export class AppComponent  { 
  constructor(private auth:Auth ){

  }

}

app.component.html

 //skipped elements

<nav class="navbar navbar-default ">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">ngAuth0</a>
    </div>
    <div id="navbar" class="collapse navbar-collapse">
      <ul class="nav navbar-nav">
        <li ><a routerLink="/">Home</a></li>
      </ul>
      <ul class="nav navbar-nav navbar-right">
        <li ><a href="#" (click)="auth.login()" *ngIf="!auth.authenticated()">Login</a></li>
        <li ><a routerLink="/profile" *ngIf="auth.authenticated()">Profile</a></li>
        <li ><a href="#" (click)="auth.logout()" *ngIf="auth.authenticated()">Logout</a></li>
      </ul>
    </div><!--/.nav-collapse -->
  </div>
</nav>

auth.service.ts

import { Injectable }      from '@angular/core';
import { tokenNotExpired } from 'angular2-jwt';

// Avoid name not found warnings
declare var Auth0Lock: any;

@Injectable()
export class Auth {
  // Configure Auth0
  lock = new Auth0Lock('7fZnGMP3H3Sl6aTRPQbLWGwPLeHNlm9z', 'myauthID', {});


  constructor() {
    // Add callback for lock `authenticated` event


    this.lock.on("authenticated", (authResult:any) => {
    this.lock.getProfile(authResult.idToken, function(error:any, profile:any){
        if(error){
                throw new Error(error);
        }

        localStorage.setItem('id_token', authResult.idToken);
        localStorage.setItem('profile', JSON.stringify(profile)); //in localStorage only strings can be stored. stringify is needed

      });

    });
  }

  public login() {
    // Call the show method to display the widget.
    this.lock.show();
  }

  public authenticated() {
    // Check if there's an unexpired JWT
    // This searches for an item in localStorage with key == 'id_token'
    return tokenNotExpired();
  }
Community
  • 1
  • 1
Battalgazi
  • 367
  • 1
  • 4
  • 20
  • This [answer](http://stackoverflow.com/a/39701248/204699) to a similar question (*How to use the HashLocationStrategy with the Auth0 Lock widget for user login*) might be of interest. – João Angelo Jan 03 '17 at 13:28
  • Yes thats exactly the problem, I will have a look on that. What i actually did is to remove the hashstrategy and now i manage it with my server this way so the refresh always works: app.all('/*', function(req, res, next) { res.sendFile(path.join(__dirname, './client', 'index.html')); }); – Battalgazi Jan 03 '17 at 20:42

1 Answers1

1

The problem is that when reloading, you actually trying to find a "profile" file in your server (backend). You actually want all request to be handle by angular2 (front-end). Using hashLocationStrategy, your profile page is now on http://localhost:3000/#/profile.

Another mistake is when you have {path:'', .. } so all urls match that path (because all urls have "nothing" in the start), so you have to make it :

{
  path:'',
  component: HomeComponent,
  pathMatch: 'full' 
}

I don't know if this solves your problem, but try this changes, and search how to config your HashLocationStrategy (common on the app.module.ts)