Skip to content

Commit d1b840e

Browse files
Merge pull request #16 from rodrigokamada/feature/backend-integration
Backend integration
2 parents c014654 + ee8ecc1 commit d1b840e

File tree

16 files changed

+255
-39
lines changed

16 files changed

+255
-39
lines changed

app.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const express = require('express')
22
const path = require("path");
33
const cookieParser = require('cookie-parser')
4+
const cors = require('cors')
45

56
// Some info from package.json
67
const package_json = require('./package.json')
@@ -44,6 +45,8 @@ app.use(function(req, res, next){
4445
next();
4546
})
4647

48+
app.use(cors());
49+
4750
app.use("/", homeRouter);
4851
app.use("/jwt", jwtRouter);
4952
app.use("/demo", demoRouter);

frontend/README.md

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,56 @@
1-
# SuperTokens Frontend
1+
# Auth JWT Frontend
2+
3+
4+
Application example built with [Angular](https://angular.io/) 13.
5+
6+
[![Website](https://shields.braskam.com/v1/shields?name=website&format=rectangle&size=small&radius=5)](https://rodrigo.kamada.com.br)
7+
[![LinkedIn](https://shields.braskam.com/v1/shields?name=linkedin&format=rectangle&size=small&radius=5)](https://www.linkedin.com/in/rodrigokamada)
8+
[![Twitter](https://shields.braskam.com/v1/shields?name=twitter&format=rectangle&size=small&radius=5&socialAccount=rodrigokamada)](https://twitter.com/rodrigokamada)
9+
[![Instagram](https://shields.braskam.com/v1/shields?name=instagram&format=rectangle&size=small&radius=5)](https://www.instagram.com/rodrigokamada/)
10+
11+
12+
13+
## Prerequisites
14+
15+
16+
Before you start, you need to install and configure the tools:
17+
18+
* [git](https://git-scm.com/)
19+
* [Node.js and npm](https://nodejs.org/)
20+
* [Angular CLI](https://angular.io/cli)
21+
* IDE (e.g. [Visual Studio Code](https://code.visualstudio.com/) or [WebStorm](https://www.jetbrains.com/webstorm/))
22+
23+
24+
25+
## Getting started
26+
27+
28+
29+
## Cloning the application
30+
31+
32+
**1.** Clone the repository.
33+
34+
```powershell
35+
git clone [email protected]:gitcommitshow/auth-jwt.git
36+
```
37+
38+
**2.** Go to frontend folder.
39+
40+
```powershell
41+
cd frontend
42+
```
43+
44+
**3.** Install the dependencies.
45+
46+
```powershell
47+
npm install
48+
```
49+
50+
**4.** Run the application.
51+
52+
```powershell
53+
npm start
54+
```
55+
56+
**5.** Access the URL [http://localhost:4200/](http://localhost:4200/).

frontend/src/app/anatomy/anatomy.component.html

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,35 +41,55 @@ <h2 class="my-5">{{ "anatomy.tokenSchema" | transloco }}</h2>
4141
</div>
4242
</div>
4343

44-
<h6 class="my-5">1. {{ "anatomy.header" | transloco }} (<span class="jwt-header">eyJhbG...pXVCJ9</span>):</h6>
44+
<h6 class="my-5">1. {{ "anatomy.header" | transloco }} (<span class="jwt-header">{{ jwtHeaderShort }}</span>):</h6>
4545

4646
<p class="font-grey">{{ "anatomy.header1" | transloco }}</p>
4747

4848
<p class="font-grey">{{ "anatomy.header2" | transloco }}</p>
4949

5050
<p class="font-grey" innerHTML="{{ 'anatomy.header3' | transloco }}"></p>
5151

52-
<button type="button" class="btn btn-primary btn-decode my-2">
52+
<button type="button" (click)="decodeHeader = !decodeHeader" class="btn btn-primary btn-decode my-2" *ngIf="!decodeHeader">
5353
{{ "anatomy.decodeHeader" | transloco }}
5454
<img src="assets/images/icon-arrow-right.svg" class="ms-1" />
5555
</button>
5656

57-
<p class="font-grey fst-italic"><small>{{ "anatomy.decodedHeader" | transloco }}</small></p>
57+
<p class="font-grey fst-italic" *ngIf="!decodeHeader"><small>{{ "anatomy.showDecodedHeader" | transloco }}</small></p>
58+
59+
<div class="card card-jwt my-2" *ngIf="decodeHeader">
60+
<div class="card-header">
61+
{{ "anatomy.decodedHeader" | transloco }}
62+
<br>
63+
{{ jwtHeaderDecoded }}
64+
</div>
65+
</div>
66+
67+
<p class="font-grey fst-italic" *ngIf="decodeHeader"><small>{{ "anatomy.takeawayHeader" | transloco }}</small></p>
5868

59-
<h6 class="my-5">2. {{ "anatomy.payload" | transloco }} (<span class="jwt-payload">eyJkYX...b20ifQ</span>):</h6>
69+
<h6 class="my-5">2. {{ "anatomy.payload" | transloco }} (<span class="jwt-payload">{{ jwtPayloadShort }}</span>):</h6>
6070

6171
<p class="font-grey">{{ "anatomy.payload1" | transloco }}</p>
6272

6373
<p class="font-grey" innerHTML="{{ 'anatomy.payload2' | transloco }}"></p>
6474

65-
<button type="button" class="btn btn-primary btn-decode my-2">
75+
<button type="button" (click)="decodePayload = !decodePayload" class="btn btn-primary btn-decode my-2" *ngIf="!decodePayload">
6676
{{ "anatomy.decodePayload" | transloco }}
6777
<img src="assets/images/icon-arrow-right.svg" class="ms-1" />
6878
</button>
6979

70-
<p class="font-grey fst-italic"><small>{{ "anatomy.decodedPayload" | transloco }}</small></p>
80+
<p class="font-grey fst-italic" *ngIf="!decodePayload"><small>{{ "anatomy.showDecodedPayload" | transloco }}</small></p>
81+
82+
<div class="card card-jwt my-2" *ngIf="decodePayload">
83+
<div class="card-header">
84+
{{ "anatomy.decodedPayload" | transloco }}
85+
<br>
86+
{{ jwtPayloadDecoded }}
87+
</div>
88+
</div>
89+
90+
<p class="font-grey fst-italic" *ngIf="decodePayload"><small>{{ "anatomy.takeawayPayload" | transloco }}</small></p>
7191

72-
<h6 class="my-5">3. {{ "anatomy.signature" | transloco }} (<span class="jwt-payload">rvOx0i...7Jo0_A</span>):</h6>
92+
<h6 class="my-5">3. {{ "anatomy.signature" | transloco }} (<span class="jwt-signature">{{ jwtSignatureShort }}</span>):</h6>
7393

7494
<p class="font-grey">{{ "anatomy.signature1" | transloco }}</p>
7595

Lines changed: 48 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,66 @@
1-
import { Component } from '@angular/core';
1+
import { Component, OnInit } from '@angular/core';
2+
3+
import { JwtService } from '../shared/services/jwt.service';
24

35
@Component({
46
selector: 'app-anatomy',
57
templateUrl: './anatomy.component.html',
68
styleUrls: ['./anatomy.component.scss'],
79
})
8-
export class AnatomyComponent {
10+
export class AnatomyComponent implements OnInit {
911

1012
showToken: boolean;
1113
jwtHeader: string;
14+
jwtHeaderShort: string;
15+
jwtHeaderDecoded: string;
16+
decodeHeader: boolean;
1217
jwtPayload: string;
18+
jwtPayloadShort: string;
19+
jwtPayloadDecoded: string;
20+
decodePayload: boolean;
1321
jwtSignature: string;
22+
jwtSignatureShort: string;
1423
token: string;
1524

16-
constructor() {
25+
constructor(private jwtService: JwtService) {
1726
this.showToken = false;
18-
this.jwtHeader = 'eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9';
19-
this.jwtPayload = 'eyJkYXRhIjoiSSBzZWNyZXRseSBsaWtlIE1vbWluYSBNdXN0ZWhhbiIsImlhdCI6MTY0NjA1NjEzOCwiZXhwIjoxNjQ2MTQyNTM4LCJhdWQiOiJtaWNyb3NvZnQuY29tIiwiaXNzIjoiTWljcm9zb2Z0IEluYyIsInN1YiI6InNvbWVAdXNlci5jb20ifQ';
20-
this.jwtSignature = 'rvOx0iNIzDLkVvJaiM_nU7fmrE8Zh9RbR_lh9iCryOYjYmxuHviYVOOdScNJ-exmjDXssxZ84TWV34KJNUA36EHs3Ew5Pcn5N6_UechJ2MTvUaXyR6JrqdWjw8RuXBmAfkEpizST9jPKybTRWzJlqmr-QErpluTIJyonvHmd8FXCcaNzYJDuQ5T56zI7beuEiSL1tyOwx9AQhr4Q1qF28Ek8RRUg1JMlaGs0d5c4YMaNz8xJE6-YkTIr6LSH3gwXKtbY3qgJxzFwXRqmvxnkBTya9Ji1tu1OYso4NffHZHatU4F7xjex3VzQfwM9uVrsWvsspL5ZyKzJcCa67Jo0_A';
27+
this.jwtHeader = '';
28+
this.jwtHeaderShort = '';
29+
this.jwtHeaderDecoded = '';
30+
this.decodeHeader = false;
31+
this.jwtPayload = '';
32+
this.jwtPayloadShort = '';
33+
this.jwtPayloadDecoded = '';
34+
this.decodePayload = false;
35+
this.jwtSignature = '';
36+
this.jwtSignatureShort = '';
2137
this.token = 'b3NvZnQuY29tIiwiaXNzIjoiTWljcm9zb2Z0IEluYyIsInN1YiI6ISsexmjDXssxZ84TWV34KJNUA36EHs3Ew5Pcn5N6_UechJ2MTvUaXyR6JrqdWjw8RuXBmAfkEpizST9jPKybTRWzJlqmr-QErpluTIJyonvHmd8FXACADS';
2238
}
2339

40+
ngOnInit(): void {
41+
this.load();
42+
}
43+
44+
public load(): void {
45+
this.jwtService.get()
46+
.subscribe({
47+
next: (success: any) => {
48+
console.debug('success:', success);
49+
if (success && success.token) {
50+
const tokenSplitted = success.token.split('.');
51+
this.jwtHeader = tokenSplitted[0];
52+
this.jwtHeaderShort = `${this.jwtHeader.substring(0, 6)}...${this.jwtHeader.substring(this.jwtHeader.length-6, this.jwtHeader.length)}`;
53+
this.jwtPayload = tokenSplitted[1];
54+
this.jwtPayloadShort = `${this.jwtPayload.substring(0, 6)}...${this.jwtPayload.substring(this.jwtPayload.length-6, this.jwtPayload.length)}`;
55+
this.jwtSignature = tokenSplitted[2];
56+
this.jwtSignatureShort = `${this.jwtSignature.substring(0, 6)}...${this.jwtSignature.substring(this.jwtSignature.length-6, this.jwtSignature.length)}`;
57+
this.jwtHeaderDecoded = window.atob(this.jwtHeader);
58+
this.jwtPayloadDecoded = window.atob(this.jwtPayload);
59+
}
60+
}, error: (error: any) => {
61+
console.error('error:', error);
62+
},
63+
});
64+
}
65+
2466
}

frontend/src/app/app.component.html

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -13,47 +13,75 @@
1313
<div class="row">
1414
<div class="col">
1515
</div>
16-
<div class="col-8">
16+
<div class="col-8 mx-3">
1717
<router-outlet></router-outlet>
1818
</div>
19-
<div class="col">
19+
<div class="col border-start">
2020
<ul class="nav flex-column nav-right">
2121
<li class="nav-item m-2">
22-
<img src="assets/images/icon-checked.svg" class="position-fixed" *ngIf="step > 1" />
23-
<img src="assets/images/icon-check.svg" class="position-fixed" *ngIf="step === 1" />
24-
<span class="ms-4">{{ "app.mainPage" | transloco }}</span>
22+
<img src="assets/images/icon-checked.svg" class="w-12px" *ngIf="step > 1" />
23+
<img src="assets/images/icon-check.svg" class="w-12px" *ngIf="step === 1" />
24+
<span class="ms-2">{{ "app.mainPage" | transloco }}</span>
2525
</li>
2626
<li class="nav-item m-2">
27-
<img src="assets/images/icon-checked.svg" class="position-fixed" *ngIf="step > 2" />
28-
<img src="assets/images/icon-check.svg" class="position-fixed" *ngIf="step === 2" />
29-
<span class="ms-4">{{ "app.anatomyJwt" | transloco }}</span>
27+
<img src="assets/images/icon-checked.svg" class="w-12px" *ngIf="step > 2" />
28+
<img src="assets/images/icon-check.svg" class="w-12px" *ngIf="step === 2" />
29+
<span class="w-12px" *ngIf="step > 1"></span>
30+
<span class="ms-2">{{ "app.anatomyJwt" | transloco }}</span>
3031
</li>
3132
<li class="nav-item m-2">
32-
<span class="ms-4">{{ "app.verifyingToken" | transloco }}</span>
33+
<img src="assets/images/icon-checked.svg" class="w-12px" *ngIf="step > 3" />
34+
<img src="assets/images/icon-check.svg" class="w-12px" *ngIf="step === 3" />
35+
<div class="w-12px d-inline-flex" *ngIf="step <= 2"></div>
36+
<span class="ms-2">{{ "app.verifyingToken" | transloco }}</span>
3337
</li>
3438
<li class="nav-item m-2">
35-
<span class="ms-4">{{ "app.generatingToken" | transloco }}</span>
39+
<img src="assets/images/icon-checked.svg" class="w-12px" *ngIf="step > 4" />
40+
<img src="assets/images/icon-check.svg" class="w-12px" *ngIf="step === 4" />
41+
<div class="w-12px d-inline-flex" *ngIf="step <= 3"></div>
42+
<span class="ms-2">{{ "app.generatingToken" | transloco }}</span>
3643
</li>
3744
<li class="nav-item m-2">
38-
<span class="ms-4">{{ "app.tokenAuthenticate" | transloco }}</span>
45+
<img src="assets/images/icon-checked.svg" class="w-12px" *ngIf="step > 5" />
46+
<img src="assets/images/icon-check.svg" class="w-12px" *ngIf="step === 5" />
47+
<div class="w-12px d-inline-flex" *ngIf="step <= 4"></div>
48+
<span class="ms-2">{{ "app.tokenAuthenticate" | transloco }}</span>
3949
</li>
4050
<li class="nav-item m-2">
41-
<span class="ms-5">{{ "app.tokenAuthenticate1" | transloco }}</span>
51+
<img src="assets/images/icon-checked.svg" class="w-12px" *ngIf="step > 6" />
52+
<img src="assets/images/icon-check.svg" class="w-12px" *ngIf="step === 6" />
53+
<div class="w-12px d-inline-flex" *ngIf="step <= 5"></div>
54+
<span class="ms-4">{{ "app.tokenAuthenticate1" | transloco }}</span>
4255
</li>
4356
<li class="nav-item m-2">
44-
<span class="ms-5">{{ "app.tokenAuthenticate2" | transloco }}</span>
57+
<img src="assets/images/icon-checked.svg" class="w-12px" *ngIf="step > 7" />
58+
<img src="assets/images/icon-check.svg" class="w-12px" *ngIf="step === 7" />
59+
<div class="w-12px d-inline-flex" *ngIf="step <= 6"></div>
60+
<span class="ms-4">{{ "app.tokenAuthenticate2" | transloco }}</span>
4561
</li>
4662
<li class="nav-item m-2">
47-
<span class="ms-5">{{ "app.tokenAuthenticate3" | transloco }}</span>
63+
<img src="assets/images/icon-checked.svg" class="w-12px" *ngIf="step > 8" />
64+
<img src="assets/images/icon-check.svg" class="w-12px" *ngIf="step === 8" />
65+
<div class="w-12px d-inline-flex" *ngIf="step <= 7"></div>
66+
<span class="ms-4">{{ "app.tokenAuthenticate3" | transloco }}</span>
4867
</li>
4968
<li class="nav-item m-2">
50-
<span class="ms-4">{{ "app.bestMethod" | transloco }}</span>
69+
<img src="assets/images/icon-checked.svg" class="w-12px" *ngIf="step > 9" />
70+
<img src="assets/images/icon-check.svg" class="w-12px" *ngIf="step === 9" />
71+
<div class="w-12px d-inline-flex" *ngIf="step <= 8"></div>
72+
<span class="ms-2">{{ "app.bestMethod" | transloco }}</span>
5173
</li>
5274
<li class="nav-item m-2">
53-
<span class="ms-4">{{ "app.logout" | transloco }}</span>
75+
<img src="assets/images/icon-checked.svg" class="w-12px" *ngIf="step > 10" />
76+
<img src="assets/images/icon-check.svg" class="w-12px" *ngIf="step === 10" />
77+
<div class="w-12px d-inline-flex" *ngIf="step <= 9"></div>
78+
<span class="ms-2">{{ "app.logout" | transloco }}</span>
5479
</li>
5580
<li class="nav-item m-2">
56-
<span class="ms-4">{{ "app.finishTutorial" | transloco }}</span>
81+
<img src="assets/images/icon-checked.svg" class="w-12px" *ngIf="step > 11" />
82+
<img src="assets/images/icon-check.svg" class="w-12px" *ngIf="step === 11" />
83+
<div class="w-12px d-inline-flex" *ngIf="step <= 10"></div>
84+
<span class="ms-2">{{ "app.finishTutorial" | transloco }}</span>
5785
</li>
5886
</ul>
5987
</div>

frontend/src/app/app.component.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,7 @@ nav a {
1919
font-size: 12px;
2020
color: #c1c9d2;
2121
}
22+
23+
.border-start {
24+
border-color: #3c4258 !important;
25+
}

frontend/src/app/app.module.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { NgModule } from '@angular/core';
22
import { BrowserModule } from '@angular/platform-browser';
3-
import { HttpClientModule } from '@angular/common/http';
3+
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
44

55
import { TranslocoRootModule } from './shared/modules/transloco-root.module';
66

7+
import { HttpHeaderInterceptor } from './shared/interceptors/http-header.interceptor';
8+
79
import { AppRoutingModule } from './app-routing.module';
810

911
import { AppComponent } from './app.component';
@@ -21,6 +23,13 @@ import { AppComponent } from './app.component';
2123
bootstrap: [
2224
AppComponent,
2325
],
26+
providers: [
27+
{
28+
provide: HTTP_INTERCEPTORS,
29+
useClass: HttpHeaderInterceptor,
30+
multi: true,
31+
},
32+
],
2433
})
2534
export class AppModule {
2635
}

frontend/src/app/home/home.component.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ export class HomeComponent {
1212

1313
constructor(private router: Router,
1414
private stepService: StepService) {
15+
this.stepService.setStep(1);
1516
}
1617

1718
public nextStep(): void {
18-
this.stepService.nextStep(2);
19+
this.stepService.setStep(2);
1920
this.router.navigate(['/anatomy']);
2021
}
2122

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Injectable } from '@angular/core';
2+
import { HttpRequest, HttpHandler, HttpEvent, HttpInterceptor } from '@angular/common/http';
3+
import { Observable } from 'rxjs';
4+
5+
@Injectable()
6+
export class HttpHeaderInterceptor implements HttpInterceptor {
7+
8+
constructor() {
9+
}
10+
11+
public intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
12+
request = request.clone({
13+
setHeaders: {
14+
'content-type': 'application/json',
15+
},
16+
});
17+
18+
return next.handle(request);
19+
}
20+
21+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { Injectable } from '@angular/core';
2+
import { HttpClient, HttpHeaders } from '@angular/common/http';
3+
import { Observable } from 'rxjs';
4+
5+
import { environment } from '../../../environments/environment';
6+
7+
@Injectable({
8+
providedIn: 'root',
9+
})
10+
export class JwtService {
11+
12+
private url: string;
13+
14+
constructor(private http: HttpClient) {
15+
this.url = `${environment.server}/jwt`;
16+
}
17+
18+
public get(): Observable<any> {
19+
return this.http.get<any>(this.url);
20+
}
21+
22+
}

0 commit comments

Comments
 (0)