added auth service
This commit is contained in:
parent
0be5c36194
commit
bdc9ec3ee0
|
@ -1,38 +1,77 @@
|
||||||
import { HttpClient } from '@angular/common/http';
|
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Router } from '@angular/router';
|
|
||||||
|
import { BehaviorSubject } from 'rxjs';
|
||||||
|
|
||||||
import { environment } from '../../../environments/environment';
|
import { environment } from '../../../environments/environment';
|
||||||
import { LoginCredentials, Tokens } from '../types';
|
import { LoginCredentials, Tokens } from '../types';
|
||||||
|
|
||||||
|
import { LocalStorageService } from './local-storage.service';
|
||||||
|
import { SessionStorageService } from './session-storage.service';
|
||||||
|
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
})
|
})
|
||||||
export class AuthService {
|
export class AuthService {
|
||||||
private isAuthenticated: boolean = false;
|
private readonly path: string = '/api/auth';
|
||||||
private access_token: string | null = null;
|
private access_token: string | null = null;
|
||||||
private refresh_token: string | null = null;
|
private refresh_token: string | null = null;
|
||||||
|
private isAuthenticated$: BehaviorSubject<boolean> =
|
||||||
|
new BehaviorSubject<boolean>(false);
|
||||||
|
|
||||||
public constructor(
|
public constructor(
|
||||||
private readonly httpClient: HttpClient,
|
private readonly httpClient: HttpClient,
|
||||||
private readonly router: Router
|
private readonly localStorageService: LocalStorageService,
|
||||||
|
private readonly sessionStorageService: SessionStorageService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public signin(credentials: LoginCredentials): void {
|
public signin(credentials: LoginCredentials): void {
|
||||||
this.httpClient
|
this.httpClient
|
||||||
.post<Tokens>(environment.api.base + '/api/auth/signin', credentials)
|
.post<Tokens>(environment.api.base + `${this.path}/signin`, credentials)
|
||||||
.subscribe((response: Tokens) => {
|
.subscribe((response: Tokens) => {
|
||||||
this.access_token = response.access_token;
|
this.handleSuccess(response);
|
||||||
this.refresh_token = response.refresh_token;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public signup(credentials: LoginCredentials): void {
|
public signup(credentials: LoginCredentials): void {
|
||||||
this.httpClient
|
this.httpClient
|
||||||
.post<Tokens>(environment.api.base + '/api/auth/signup', credentials)
|
.post<Tokens>(environment.api.base + `${this.path}/signup`, credentials)
|
||||||
.subscribe((response: Tokens) => {
|
.subscribe((response: Tokens) => {
|
||||||
this.access_token = response.access_token;
|
// The checked accept terms should be saved with a timestamp in the db
|
||||||
this.refresh_token = response.refresh_token;
|
this.handleSuccess(response);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public signout(): void {
|
||||||
|
this.access_token = null;
|
||||||
|
this.refresh_token = null;
|
||||||
|
this.localStorageService.removeItem('access_token');
|
||||||
|
this.sessionStorageService.removeItem('refresh_token');
|
||||||
|
this.isAuthenticated$.next(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public refreshToken(): void {
|
||||||
|
const headers = new HttpHeaders().set(
|
||||||
|
'Authorization',
|
||||||
|
'Bearer ' + this.refresh_token
|
||||||
|
);
|
||||||
|
|
||||||
|
this.httpClient
|
||||||
|
.post<Tokens>(
|
||||||
|
environment.api.base + `${this.path}/refresh`,
|
||||||
|
{},
|
||||||
|
{ headers: headers }
|
||||||
|
)
|
||||||
|
.subscribe((response: Tokens) => {
|
||||||
|
this.handleSuccess(response);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleSuccess(tokens: Tokens): void {
|
||||||
|
this.access_token = tokens.access_token;
|
||||||
|
this.refresh_token = tokens.refresh_token;
|
||||||
|
this.localStorageService.setItem('access_token', tokens.access_token);
|
||||||
|
this.sessionStorageService.setItem('refresh_token', tokens.refresh_token);
|
||||||
|
this.isAuthenticated$.next(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { EncryptionService } from './encryption.service';
|
||||||
|
import { SanitizationService } from './sanitization.service';
|
||||||
|
|
||||||
|
export abstract class BaseStorageService {
|
||||||
|
protected abstract getStorage(): Storage;
|
||||||
|
|
||||||
|
public setItem<T>(key: string, value: T): void {
|
||||||
|
const sanitizedValue = SanitizationService.sanitize(JSON.stringify(value));
|
||||||
|
const encryptedValue = EncryptionService.encrypt(sanitizedValue);
|
||||||
|
|
||||||
|
this.getStorage().setItem(key, encryptedValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getItem<T>(key: string): T | null {
|
||||||
|
const encryptedValue = this.getStorage().getItem(key);
|
||||||
|
|
||||||
|
if (encryptedValue) {
|
||||||
|
const decryptedValue = EncryptionService.decrypt(encryptedValue);
|
||||||
|
const sanitizedValue = SanitizationService.sanitize(decryptedValue);
|
||||||
|
|
||||||
|
return JSON.parse(sanitizedValue) as T;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public removeItem(key: string): void {
|
||||||
|
this.getStorage().removeItem(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public clear(): void {
|
||||||
|
this.getStorage().clear();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
import * as CryptoJS from 'crypto-js';
|
||||||
|
|
||||||
|
import { environment } from '../../../environments/environment';
|
||||||
|
|
||||||
|
export class EncryptionService {
|
||||||
|
private static readonly key: string = environment.security.encryptionKey;
|
||||||
|
|
||||||
|
public static encrypt(data: string): string {
|
||||||
|
return CryptoJS.AES.encrypt(data, this.key).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static decrypt(data: string): string {
|
||||||
|
return CryptoJS.AES.decrypt(data, this.key).toString(CryptoJS.enc.Utf8);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +1,3 @@
|
||||||
export * from './auth.service';
|
export * from './auth.service';
|
||||||
|
export * from './local-storage.service';
|
||||||
|
export * from './session-storage.service';
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { BaseStorageService } from './base-storage.service';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class LocalStorageService extends BaseStorageService {
|
||||||
|
protected getStorage(): Storage {
|
||||||
|
return localStorage;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
import DOMPurify from 'dompurify';
|
||||||
|
|
||||||
|
export class SanitizationService {
|
||||||
|
public static sanitize(data: string): string {
|
||||||
|
return DOMPurify.sanitize(data);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
|
import { BaseStorageService } from './base-storage.service';
|
||||||
|
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
export class SessionStorageService extends BaseStorageService {
|
||||||
|
protected getStorage(): Storage {
|
||||||
|
return sessionStorage;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue