Skip to content

Commit 70a6a02

Browse files
committed
3: add dashboard component, loginfake and reigsterfake requests.
Then also add the @auth0/angular-jwt and implement it
1 parent 9730e64 commit 70a6a02

File tree

15 files changed

+243
-22
lines changed

15 files changed

+243
-22
lines changed

README.md

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,26 @@
33
## How to run
44
First run `npm i` and then `ng serve`, then you can open localhost:4200 in your Browser
55

6-
### Commands/Cli Commands that were used to generate this project
7-
With the Angular CLI we can generate Angular Scaffolds with just one specific command. e.g. generate a component, a module, or a service
6+
### Hints
7+
Proxy:
8+
With a proxy file you can proxy/rewrite your api calls against your backend.
9+
Currently there is a file under /src/proxy.conf.json (and it is added in angular.json)
10+
with some config details, since there is no backend running, the requests will fail - it's your turn to build the backend :)
11+
12+
Jwt:
13+
The @auth0/angular-jwt is added and with the login request the jwt is stored in the local storage.
14+
The package adds then the jwt to every request to the backend automatically via an interceptoer, so the fe/the user is
15+
always authenticated against the backend.
16+
17+
### Next Steps for you
18+
Add a real backend and replace the placeholders
19+
20+
### Next steps for me
21+
- add a form to reset the password
22+
23+
### Commands/Cli Commands that were used to generate this project
24+
With the Angular CLI we can generate Angular Scaffolds with just one specific command.
25+
e.g. generate a component, a module, or a service
826

927
Let the Angular CLI generate the angular starter for you
1028
`ng new login-and-register-example`
@@ -16,6 +34,17 @@ Generate the modules Public, Private and Shared
1634
`ng g module public`
1735
`ng g module private`
1836

19-
generate proxy file to proxy/rewrite the `/api` requests
20-
create file proxy.conf.json and add the config details
21-
then add it to the angular json under projects....serve.development.proxyConfig...
37+
Generate the components
38+
`ng g c public/login`
39+
`ng g c public/register`
40+
`ng g c protected/dashboard`
41+
42+
Generate the "fake" Service
43+
`ng g s public/auth`
44+
45+
Add an angular jwt package, for handling the jwt, the login etc.
46+
`npm i @auth0/angular-jwt`
47+
48+
Add the Auth guard, to make sure only LoggedIn Users can access the Protected Module
49+
`ng g g Auth`
50+
then implement the CanActivate interface

package-lock.json

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
"@angular/platform-browser": "~13.1.0",
2121
"@angular/platform-browser-dynamic": "~13.1.0",
2222
"@angular/router": "~13.1.0",
23+
"@auth0/angular-jwt": "^5.0.2",
2324
"rxjs": "~7.4.0",
2425
"tslib": "^2.3.0",
2526
"zone.js": "~0.11.4"
@@ -38,4 +39,4 @@
3839
"karma-jasmine-html-reporter": "~1.7.0",
3940
"typescript": "~4.5.2"
4041
}
41-
}
42+
}

src/app/app-routing.module.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,20 @@
11
import { NgModule } from '@angular/core';
22
import { RouterModule, Routes } from '@angular/router';
3+
import { AuthGuard } from './auth-guard/auth.guard';
34

45
const routes: Routes = [
56
{
67
// Lazy Loading the public module (all children routes will be under '/public/{route from lazy loaded module}')
78
path: 'public',
89
loadChildren: () => import('./public/public.module').then(m => m.PublicModule)
910
},
11+
{
12+
// Lazy Loading the protected module (all children routes will be under '/protected/{route from lazy loaded module}')
13+
// The guard will check if the user is having a jwt, otherwise he will be redirected to the base route
14+
path: 'protected',
15+
canActivate: [AuthGuard],
16+
loadChildren: () => import('./protected/protected.module').then(m => m.ProtectedModule)
17+
},
1018
{
1119
// Redirects all paths that are not matching to the 'public' route/path
1220
path: '**',

src/app/app.module.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,16 @@ import { AppComponent } from './app.component';
66
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
77
import { HttpClientModule } from '@angular/common/http';
88

9+
import { JwtModule } from '@auth0/angular-jwt';
10+
11+
// specify the key where the token is stored in the local storage
12+
export const LOCALSTORAGE_TOKEN_KEY = 'angular_material_login_and_register_example';
13+
14+
// specify tokenGetter for the angular jwt package
15+
export function tokenGetter() {
16+
return localStorage.getItem(LOCALSTORAGE_TOKEN_KEY);
17+
}
18+
919
@NgModule({
1020
declarations: [
1121
AppComponent
@@ -14,7 +24,14 @@ import { HttpClientModule } from '@angular/common/http';
1424
BrowserModule,
1525
AppRoutingModule,
1626
BrowserAnimationsModule,
17-
HttpClientModule
27+
HttpClientModule,
28+
29+
JwtModule.forRoot({
30+
config: {
31+
tokenGetter: tokenGetter,
32+
allowedDomains: ['localhost:3000', 'localhost:8080']
33+
}
34+
})
1835
],
1936
providers: [],
2037
bootstrap: [AppComponent]
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { TestBed } from '@angular/core/testing';
2+
3+
import { AuthGuard } from './auth.guard';
4+
5+
describe('AuthGuard', () => {
6+
let guard: AuthGuard;
7+
8+
beforeEach(() => {
9+
TestBed.configureTestingModule({});
10+
guard = TestBed.inject(AuthGuard);
11+
});
12+
13+
it('should be created', () => {
14+
expect(guard).toBeTruthy();
15+
});
16+
});

src/app/auth-guard/auth.guard.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Injectable } from '@angular/core';
2+
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
3+
import { JwtHelperService } from '@auth0/angular-jwt';
4+
import { Observable } from 'rxjs';
5+
6+
@Injectable({
7+
providedIn: 'root'
8+
})
9+
export class AuthGuard implements CanActivate {
10+
11+
constructor(
12+
private router: Router,
13+
private jwtService: JwtHelperService
14+
) { }
15+
16+
canActivate(): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
17+
// isTokenExpired() will return true, if either:
18+
// - token is expired
19+
// - no token or key/value pair in localStorage
20+
// - ... (since the backend should validate the token, even if there is another false token,
21+
// then he can access the frontend route, but will not get any data from the backend)
22+
// --> then redirect to the base route and deny the routing
23+
// --> else return true and allow the routing
24+
if (this.jwtService.isTokenExpired()) {
25+
this.router.navigate(['']);
26+
return false;
27+
} else {
28+
return true;
29+
}
30+
}
31+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<p>Protected Dashboard works.</p>

src/app/protected/dashboard/dashboard.component.scss

Whitespace-only changes.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { DashboardComponent } from './dashboard.component';
4+
5+
describe('DashboardComponent', () => {
6+
let component: DashboardComponent;
7+
let fixture: ComponentFixture<DashboardComponent>;
8+
9+
beforeEach(async () => {
10+
await TestBed.configureTestingModule({
11+
declarations: [ DashboardComponent ]
12+
})
13+
.compileComponents();
14+
});
15+
16+
beforeEach(() => {
17+
fixture = TestBed.createComponent(DashboardComponent);
18+
component = fixture.componentInstance;
19+
fixture.detectChanges();
20+
});
21+
22+
it('should create', () => {
23+
expect(component).toBeTruthy();
24+
});
25+
});

0 commit comments

Comments
 (0)