redirect after login works now

This commit is contained in:
2021-06-18 18:24:01 +02:00
parent 6b7c080e17
commit ac4ff602ae
10 changed files with 86 additions and 15 deletions

View File

@ -6725,6 +6725,11 @@
"set-immediate-shim": "~1.0.1" "set-immediate-shim": "~1.0.1"
} }
}, },
"jwt-decode": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
"integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A=="
},
"karma": { "karma": {
"version": "5.1.1", "version": "5.1.1",
"resolved": "https://registry.npmjs.org/karma/-/karma-5.1.1.tgz", "resolved": "https://registry.npmjs.org/karma/-/karma-5.1.1.tgz",

View File

@ -21,6 +21,7 @@
"@angular/platform-browser": "~11.0.6", "@angular/platform-browser": "~11.0.6",
"@angular/platform-browser-dynamic": "~11.0.6", "@angular/platform-browser-dynamic": "~11.0.6",
"@angular/router": "~11.0.6", "@angular/router": "~11.0.6",
"jwt-decode": "^3.1.2",
"rxjs": "~6.6.0", "rxjs": "~6.6.0",
"tslib": "^2.0.0", "tslib": "^2.0.0",
"zone.js": "~0.10.2" "zone.js": "~0.10.2"

View File

@ -1,5 +1,6 @@
import { NgModule } from '@angular/core'; import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router'; import { RouterModule, Routes } from '@angular/router';
import { AuthGuardService } from './auth-guard.service';
import { LoginComponent } from './login/login.component'; import { LoginComponent } from './login/login.component';
import { LogoutComponent } from './logout/logout.component'; import { LogoutComponent } from './logout/logout.component';
import { TestOutputComponent } from './test-output/test-output.component'; import { TestOutputComponent } from './test-output/test-output.component';
@ -7,7 +8,7 @@ import { TestOutputComponent } from './test-output/test-output.component';
const routes: Routes = [ const routes: Routes = [
{ path: 'test', component: TestOutputComponent }, { path: 'test', component: TestOutputComponent, canActivate: [ AuthGuardService ] },
{ path: 'logout', component: LogoutComponent }, { path: 'logout', component: LogoutComponent },
{ path: 'login', component: LoginComponent } { path: 'login', component: LoginComponent }
] ]

View File

@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { AuthGuardService } from './auth-guard.service';
describe('AuthGuardService', () => {
let service: AuthGuardService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(AuthGuardService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@ -0,0 +1,22 @@
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import { MessageService } from './message.service';
import { TokenService } from './token.service';
@Injectable({
providedIn: 'root'
})
export class AuthGuardService implements CanActivate {
constructor(public tokenService: TokenService, public router: Router, private messageService: MessageService) {
}
canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
this.messageService.add(`Activated: ${next.url}`)
if (! this.tokenService.checkAuthenticated()) {
return this.router.parseUrl(`/login?returnUrl=${next.url}`)
} else {
return true;
}
}
}

View File

@ -21,7 +21,7 @@ export class ErrorHandlerInterceptor implements HttpInterceptor {
catchError((errorResponse: HttpErrorResponse) => { catchError((errorResponse: HttpErrorResponse) => {
this.messageService.add(`Intercepted http error: ${JSON.stringify(errorResponse, undefined, 4)}`) this.messageService.add(`Intercepted http error: ${JSON.stringify(errorResponse, undefined, 4)}`)
if (errorResponse.status === 401) { if (errorResponse.status === 401) {
this.router.navigateByUrl('/login') this.router.navigate(['login'])
} }
return throwError(errorResponse) return throwError(errorResponse)
}) })

View File

@ -22,7 +22,7 @@ export class LoginComponent implements OnInit {
private tokenService: TokenService, private tokenService: TokenService,
private messageService: MessageService) { private messageService: MessageService) {
this.returnUrl = this.route.snapshot.queryParams.returnUrl || '/' this.returnUrl = this.route.snapshot.queryParams.returnUrl || '/'
this.messageService.add(`Return URL is ${this.returnUrl}`)
this.form = this.fb.group({ this.form = this.fb.group({
username: ['', Validators.required], username: ['', Validators.required],
password: ['', Validators.required] password: ['', Validators.required]
@ -30,6 +30,9 @@ export class LoginComponent implements OnInit {
} }
ngOnInit(): void { ngOnInit(): void {
if (this.tokenService.checkAuthenticated()) {
this.router.navigate([this.returnUrl])
}
} }
async onSubmit(): Promise<void> { async onSubmit(): Promise<void> {
@ -40,6 +43,7 @@ export class LoginComponent implements OnInit {
const username = this.form.get('username')?.value; const username = this.form.get('username')?.value;
const password = this.form.get('password')?.value; const password = this.form.get('password')?.value;
await this.tokenService.login(username, password); await this.tokenService.login(username, password);
this.router.navigate([this.returnUrl])
} catch (err) { } catch (err) {
this.messageService.add(`Login err: ${err.message}`) this.messageService.add(`Login err: ${err.message}`)
this.loginInvalid = true; this.loginInvalid = true;

View File

@ -1,4 +1,5 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { MessageService } from '../message.service'; import { MessageService } from '../message.service';
import { TokenService } from '../token.service'; import { TokenService } from '../token.service';
@ -9,11 +10,11 @@ import { TokenService } from '../token.service';
}) })
export class LogoutComponent implements OnInit { export class LogoutComponent implements OnInit {
constructor(private messageService: MessageService) { } constructor(private tokenService: TokenService, private router: Router, private messageService: MessageService) { }
ngOnInit(): void { ngOnInit(): void {
localStorage.removeItem(TokenService.Id_Token_Key) this.tokenService.logout()
this.messageService.add("Token removed from local storage") this.router.navigateByUrl('/login')
} }
} }

View File

@ -2,6 +2,7 @@ import { Component } from '@angular/core';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators'; import { map, shareReplay } from 'rxjs/operators';
import { TokenService } from '../token.service';
@Component({ @Component({
selector: 'app-navigation', selector: 'app-navigation',
@ -10,12 +11,18 @@ import { map, shareReplay } from 'rxjs/operators';
}) })
export class NavigationComponent { export class NavigationComponent {
public authenticated: boolean
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset) isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
.pipe( .pipe(
map(result => result.matches), map(result => result.matches),
shareReplay() shareReplay()
); );
constructor(private breakpointObserver: BreakpointObserver) {} constructor(private breakpointObserver: BreakpointObserver, private tokenService: TokenService) {}
ngOnInit() {
this.authenticated = this.tokenService.checkAuthenticated()
}
} }

View File

@ -2,7 +2,8 @@ import { Injectable } from '@angular/core';
import { MessageService } from './message.service'; import { MessageService } from './message.service';
import { HttpClient, HttpHeaders } from '@angular/common/http'; import { HttpClient, HttpHeaders } from '@angular/common/http';
import { UserCreds } from './userCreds' import { UserCreds } from './userCreds'
import { ThrowStmt } from '@angular/compiler'; import jwt_decode from 'jwt-decode'
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
@ -11,14 +12,28 @@ export class TokenService {
public static Id_Token_Key : string = "id_token"; public static Id_Token_Key : string = "id_token";
constructor(private http: HttpClient, private messageService: MessageService) { constructor(private http: HttpClient, private messageService: MessageService) {
this.messageService.add("TokenService started, token created")
if (! localStorage.getItem(TokenService.Id_Token_Key)) {
localStorage.setItem(TokenService.Id_Token_Key, "abc")
this.messageService.add("Token set in local storage")
}
} }
checkAuthenticated(): boolean {
let result: boolean = false
const token = localStorage.getItem(TokenService.Id_Token_Key)
if (token) {
let expiration = jwt_decode(token)["exp"]
if ((expiration * 1000) > Date.now()) {
result = true
} else {
this.logout()
}
}
return result
}
logout() {
localStorage.removeItem(TokenService.Id_Token_Key)
this.messageService.add("Token removed from local storage")
}
async login(login: string, password: string) { async login(login: string, password: string) {
this.messageService.add(`TokenService: trying to login and obtain token`); this.messageService.add(`TokenService: trying to login and obtain token`);
@ -32,7 +47,6 @@ export class TokenService {
userCreds, userCreds,
{responseType:'text'} {responseType:'text'}
).toPromise() ).toPromise()
this.messageService.add(`Token is ${token}`)
localStorage.setItem(TokenService.Id_Token_Key, token) localStorage.setItem(TokenService.Id_Token_Key, token)
this.messageService.add("Token saved") this.messageService.add("Token saved")
} }