Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Authentication in angular 2 universal, nodejs

I downloaded universal-starter for nodejs and started migrating my website from old angular-rc4. But when I have to implement authentication (in my case it's JWT which is stored in localStorage), the server dont have localStorage and cookie so that angular is rendered only on client.

I've follow this guide: https://github.com/angular/universal-starter/issues/148 but it didnt work.

Below is my code:

authentication.services.ts

import { OpaqueToken } from '@angular/core'; 

export let AUTH_SERVICES = new OpaqueToken('auth.services');

export interface AuthenticationService {

    forgotPassword(email: any);

    isAuthenticated();

    getCurrentUser();

    refreshToken();

    signin(user : any);

    signout();

    signup(user : any);

}

server.authentication.ts

import { Injectable } from '@angular/core';

import { AuthenticationService } from './authentication.services';

@Injectable()
export class ServerAuthenticationService implements AuthenticationService {
    forgotPassword(email: any) {
        throw new Error('Forgot password cannot be called while doing server side rendering');
    }

    isAuthenticated() {
        return false;
    }

    getCurrentUser(){
        if(this.isAuthenticated()) {
            return {};
        }
        return {};
    }

    refreshToken() {

    }

    signin(user : any) {
        throw new Error('Login cannot be called while doing server side rendering');
    }

    signout() {
        throw new Error('Logout cannot be called while doing server side rendering');
    }

    signup(user : any) {
        throw new Error('Sign up cannot be called while doing server side rendering');
    }
}

clientAuthentication.services.ts

@Injectable()
export class UserService implements AuthenticationService {
    forgotPassword(email: any){
      // client implementation
    }

    isAuthenticated() {
      // client implementation
    }

    getCurrentUser() {
      // client implementation
    }

    refreshToken() {
      // client implementation
    }

    signin(user : any){
      // client implementation
    }

    signout(){
      // client implementation
    }

    signup(user : any) {
      // client implementation
    }
}

app.browser.module.ts

@NgModule({
  bootstrap: [ AppComponent ],
  declarations: [ AppComponent ],
  imports: [
    UniversalModule, // BrowserModule, HttpModule, and JsonpModule are included
    FormsModule,

    SharedModule,
    HomeModule,
    AboutModule,

    NavbarModule,

    AppRoutingModule
  ],
  providers: [
    { provide: 'isBrowser', useValue: isBrowser },
    { provide: 'isNode', useValue: isNode },

    { provide: 'LRU', useFactory: getLRU, deps: [] },
    { provide: AUTH_SERVICES, useFactory: UserService},
    CacheService
  ]

})

app.node.module.ts

@NgModule({
  bootstrap: [ AppComponent ],
  declarations: [ AppComponent ],
  imports: [
    UniversalModule, // NodeModule, NodeHttpModule, and NodeJsonpModule are included
    FormsModule,

    SharedModule,
    HomeModule,
    AboutModule,

    NavbarModule,

    AppRoutingModule
  ],
  providers: [
    { provide: 'isBrowser', useValue: isBrowser },
    { provide: 'isNode', useValue: isNode },

    {
      provide: 'LRU',
      useFactory: getLRU,
      deps: [  
        [new Inject('LRU'), new Optional(), new SkipSelf()]
      ]
    },
    { provide: AUTH_SERVICES, useFactory: ServerAuthenticationService },
    CacheService
  ]
})

Then how to have the same page output while navigating to that page on the client via a router transition vs on the server via a browser refresh?

Thanks in advance

like image 948
user3027246 Avatar asked Nov 10 '16 09:11

user3027246


1 Answers

In node you can use the request and response properties in your express application and inject them in your angular application based on server on browser module. request.cookies holds an objects that maps KVPS as to your cookies.

For some (outdated) examples on this please look here and here: https://github.com/angular/universal-starter/blob/master/src/node.module.ts#L43 https://github.com/angular/universal-starter/blob/master/src/browser.module.ts#L52

The code might get outdated soon, but the principle holds. Use dependency injection to inject the request on the server in your app and some stub for the request ( that might still expose the browser cookies ) in the version for the browser.

like image 84
Sam Vloeberghs Avatar answered Nov 15 '22 09:11

Sam Vloeberghs