Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 219be2c

Browse files
committed
first commit
1 parent 7b7d3ec commit 219be2c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1150
-505
lines changed

‎README.md‎

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,67 @@
1-
# Angular16RefreshToken
1+
# Angular 16 JWT Refresh Token example with Http Interceptor
22

3-
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 16.0.2.
3+
Implementing Angular 16 Refresh Token before Expiration with Http Interceptor and JWT.
4+
You can take a look at following flow to have an overview of Requests and Responses that Angular 16 Client will make or receive.
45

5-
## Development server
6+
## Angular JWT Refresh Token Flow
7+
![angular-16-refresh-token-jwt-example](angular-16-refresh-token-jwt-example.png)
68

7-
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files.
9+
For more detail, please visit:
10+
> [Angular 16 Refresh Token with Interceptor and JWT example](https://www.bezkoder.com/angular-16-refresh-token/)
811
9-
## Code scaffolding
12+
> [Angular 16 JWT Authentication & Authorization with Web API example](https://www.bezkoder.com/angular-16-jwt-auth/)
1013
11-
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
14+
## Fullstack
15+
> [Angular 16 + Spring Boot: JWT Authentication and Authorization example](https://www.bezkoder.com/angular-16-spring-boot-jwt-auth/)
1216
13-
## Build
17+
> [Angular 16 + Node.js Express: JWT Authentication and Authorization example](https://www.bezkoder.com/node-js-angular-16-jwt-auth/)
1418
15-
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.
19+
Run `ng serve --port 8081` for a dev server. Navigate to `http://localhost:8081/`.
1620

17-
## Running unit tests
21+
## More practice
22+
> [Angular 16 CRUD example with Web API](https://www.bezkoder.com/angular-16-crud-example/)
1823
19-
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
24+
> [Angular 16 Pagination example](https://www.bezkoder.com/angular-16-pagination-ngx/)
2025
21-
## Running end-to-end tests
26+
> [Angular 16 File upload example with Progress bar](https://www.bezkoder.com/angular-16-file-upload/)
2227
23-
Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.
28+
Fullstack with Node:
29+
> [Angular 16 + Node Express + MySQL example](https://www.bezkoder.com/angular-16-node-js-express-mysql/)
2430
25-
## Further help
31+
> [Angular 16 + Node Express + PostgreSQL example](https://www.bezkoder.com/angular-16-node-js-express-postgresql/)
2632
27-
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
33+
> [Angular 16 + Node Express + MongoDB example](https://www.bezkoder.com/angular-16-node-js-express-mongodb/)
34+
35+
> [Angular 16 + Node Express: File upload example](https://www.bezkoder.com/angular-16-node-express-file-upload/)
36+
37+
Fullstack with Spring Boot:
38+
> [Angular 16 + Spring Boot example](https://www.bezkoder.com/spring-boot-angular-16-crud/)
39+
40+
> [Angular 16 + Spring Boot + MySQL example](https://www.bezkoder.com/spring-boot-angular-16-mysql/)
41+
42+
> [Angular 16 + Spring Boot + PostgreSQL example](https://www.bezkoder.com/spring-boot-angular-16-postgresql/)
43+
44+
> [Angular 16 + Spring Boot + MongoDB example](https://www.bezkoder.com/spring-boot-angular-16-mongodb/)
45+
46+
> [Angular 16 + Spring Boot: File upload example](https://www.bezkoder.com/angular-16-spring-boot-file-upload/)
47+
48+
Fullstack with Django:
49+
> [Angular + Django example](https://www.bezkoder.com/django-angular-13-crud-rest-framework/)
50+
51+
> [Angular + Django + MySQL](https://www.bezkoder.com/django-angular-mysql/)
52+
53+
> [Angular + Django + PostgreSQL](https://www.bezkoder.com/django-angular-postgresql/)
54+
55+
> [Angular + Django + MongoDB](https://www.bezkoder.com/django-angular-mongodb/)
56+
57+
Serverless with Firebase:
58+
> [Angular 16 Firebase CRUD with Realtime DataBase](https://www.bezkoder.com/angular-16-firebase-crud/)
59+
60+
> [Angular 16 Firestore CRUD example](https://www.bezkoder.com/angular-16-firestore-crud/)
61+
62+
> [Angular 16 Firebase Storage: File Upload/Display/Delete example](https://www.bezkoder.com/angular-16-firebase-storage/)
63+
64+
Integration (run back-end & front-end on same server/port)
65+
> [How to integrate Angular with Node Restful Services](https://www.bezkoder.com/integrate-angular-12-node-js/)
66+
67+
> [How to Integrate Angular with Spring Boot Rest API](https://www.bezkoder.com/integrate-angular-12-spring-boot/)
33.8 KB
Loading[フレーム]

‎package-lock.json‎

Lines changed: 37 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: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"@angular/platform-browser": "^16.0.0",
1919
"@angular/platform-browser-dynamic": "^16.0.0",
2020
"@angular/router": "^16.0.0",
21+
"bootstrap": "^4.6.2",
2122
"rxjs": "~7.8.0",
2223
"tslib": "^2.3.0",
2324
"zone.js": "~0.13.0"

‎src/app/_helpers/http.interceptor.ts‎

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import { Injectable } from '@angular/core';
2+
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HTTP_INTERCEPTORS, HttpErrorResponse } from '@angular/common/http';
3+
4+
import { StorageService } from '../_services/storage.service';
5+
import { AuthService } from '../_services/auth.service';
6+
7+
import { Observable, throwError } from 'rxjs';
8+
import { catchError, switchMap } from 'rxjs/operators';
9+
10+
import { EventData } from '../_shared/event.class';
11+
import { EventBusService } from '../_shared/event-bus.service';
12+
13+
@Injectable()
14+
export class HttpRequestInterceptor implements HttpInterceptor {
15+
private isRefreshing = false;
16+
17+
constructor(
18+
private storageService: StorageService,
19+
private authService: AuthService,
20+
private eventBusService: EventBusService
21+
) {}
22+
23+
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
24+
req = req.clone({
25+
withCredentials: true,
26+
});
27+
28+
return next.handle(req).pipe(
29+
catchError((error) => {
30+
if (
31+
error instanceof HttpErrorResponse &&
32+
!req.url.includes('auth/signin') &&
33+
error.status === 401
34+
) {
35+
return this.handle401Error(req, next);
36+
}
37+
38+
return throwError(() => error);
39+
})
40+
);
41+
}
42+
43+
private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
44+
if (!this.isRefreshing) {
45+
this.isRefreshing = true;
46+
47+
if (this.storageService.isLoggedIn()) {
48+
return this.authService.refreshToken().pipe(
49+
switchMap(() => {
50+
this.isRefreshing = false;
51+
52+
return next.handle(request);
53+
}),
54+
catchError((error) => {
55+
this.isRefreshing = false;
56+
57+
if (error.status == '403') {
58+
this.eventBusService.emit(new EventData('logout', null));
59+
}
60+
61+
return throwError(() => error);
62+
})
63+
);
64+
}
65+
}
66+
67+
return next.handle(request);
68+
}
69+
}
70+
71+
export const httpInterceptorProviders = [
72+
{ provide: HTTP_INTERCEPTORS, useClass: HttpRequestInterceptor, multi: true },
73+
];
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 { AuthService } from './auth.service';
4+
5+
describe('AuthService', () => {
6+
let service: AuthService;
7+
8+
beforeEach(() => {
9+
TestBed.configureTestingModule({});
10+
service = TestBed.inject(AuthService);
11+
});
12+
13+
it('should be created', () => {
14+
expect(service).toBeTruthy();
15+
});
16+
});

‎src/app/_services/auth.service.ts‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { Injectable } from '@angular/core';
2+
import { HttpClient, HttpHeaders } from '@angular/common/http';
3+
import { Observable } from 'rxjs';
4+
5+
const AUTH_API = 'http://localhost:8080/api/auth/';
6+
7+
const httpOptions = {
8+
headers: new HttpHeaders({ 'Content-Type': 'application/json' })
9+
};
10+
11+
@Injectable({
12+
providedIn: 'root',
13+
})
14+
export class AuthService {
15+
constructor(private http: HttpClient) {}
16+
17+
login(username: string, password: string): Observable<any> {
18+
return this.http.post(
19+
AUTH_API + 'signin',
20+
{
21+
username,
22+
password,
23+
},
24+
httpOptions
25+
);
26+
}
27+
28+
register(username: string, email: string, password: string): Observable<any> {
29+
return this.http.post(
30+
AUTH_API + 'signup',
31+
{
32+
username,
33+
email,
34+
password,
35+
},
36+
httpOptions
37+
);
38+
}
39+
40+
logout(): Observable<any> {
41+
return this.http.post(AUTH_API + 'signout', { }, httpOptions);
42+
}
43+
44+
refreshToken() {
45+
return this.http.post(AUTH_API + 'refreshtoken', { }, httpOptions);
46+
}
47+
}
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 { StorageService } from './storage.service';
4+
5+
describe('StorageService', () => {
6+
let service: StorageService;
7+
8+
beforeEach(() => {
9+
TestBed.configureTestingModule({});
10+
service = TestBed.inject(StorageService);
11+
});
12+
13+
it('should be created', () => {
14+
expect(service).toBeTruthy();
15+
});
16+
});

‎src/app/_services/storage.service.ts‎

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { Injectable } from '@angular/core';
2+
3+
const USER_KEY = 'auth-user';
4+
5+
@Injectable({
6+
providedIn: 'root'
7+
})
8+
export class StorageService {
9+
constructor() {}
10+
11+
clean(): void {
12+
window.sessionStorage.clear();
13+
}
14+
15+
public saveUser(user: any): void {
16+
window.sessionStorage.removeItem(USER_KEY);
17+
window.sessionStorage.setItem(USER_KEY, JSON.stringify(user));
18+
}
19+
20+
public getUser(): any {
21+
const user = window.sessionStorage.getItem(USER_KEY);
22+
if (user) {
23+
return JSON.parse(user);
24+
}
25+
26+
return {};
27+
}
28+
29+
public isLoggedIn(): boolean {
30+
const user = window.sessionStorage.getItem(USER_KEY);
31+
if (user) {
32+
return true;
33+
}
34+
35+
return false;
36+
}
37+
}
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 { UserService } from './user.service';
4+
5+
describe('UserService', () => {
6+
let service: UserService;
7+
8+
beforeEach(() => {
9+
TestBed.configureTestingModule({});
10+
service = TestBed.inject(UserService);
11+
});
12+
13+
it('should be created', () => {
14+
expect(service).toBeTruthy();
15+
});
16+
});

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /