Once user sign up, we store the user data inside cookie in the broswer and also keep a memory copy in the server.
If next time, user refresh the page, we want to tell that the user is already authed.
Create a endpoint, to retrive the user data:
app.route('/api/user')
.get(getUser);
Router:
import {Request, Response} from 'express'; import {sessionStore} from './session-store'; export function getUser(req: Request, res: Response) { // Get sessionid from cookies const sessionId = req.cookies['SESSIONID']; // get user according to the session id from the session storage const user = sessionStore.findUserBySessionId(sessionId); if (user) { // if there is user, send successful response res.status(200).json(user); } else { // if there is no user, send empty response res.sendStatus(204); } }
SessionStorage:
import {Session} from './session'; import {User} from '../src/app/model/user'; class SessionStore { private sessions: {[key: string]: Session} = {}; createSession(sessionId: string, user: User) { this.sessions[sessionId] = new Session(sessionId, user); } findUserBySessionId(sessionId: string): User | undefined { const session = this.sessions[sessionId]; const isSessionValid = session && session.isValid(); return isSessionValid ? session.user : undefined; } } // We want only global singleton export const sessionStore = new SessionStore();
On the client, once page loaded, we try to get user data first.
import { Injectable } from '@angular/core'; import {HttpClient} from '@angular/common/http'; import {Observable} from 'rxjs/Observable'; import {User} from '../model/user'; import {BehaviorSubject} from 'rxjs/BehaviorSubject'; import 'rxjs/add/operator/map'; import 'rxjs/add/operator/shareReplay'; import 'rxjs/add/operator/filter'; import 'rxjs/add/operator/do'; export const ANONYMOUS_USER: User = { id: undefined, email: '' }; @Injectable() export class AuthService { subject = new BehaviorSubject<User>(undefined); // filter out undefined user user$: Observable<User> = this.subject.asObservable().filter(user => !!user); isLoggedIn$: Observable<boolean> = this.user$.map(user => !!user.id); isLoggedOut$: Observable<boolean> = this.isLoggedIn$.map(isLoggedIn => !isLoggedIn); constructor(private http: HttpClient) { this.http.get<User>('/api/user') // when there is valid session id, emit the user$ .subscribe((user) => this.subject.next(user ? user : ANONYMOUS_USER)); } signUp(email: string, password: string) { return this.http.post<User>('/api/signup', { email, password }).shareReplay() .do((user) => this.subject.next(user)); } }