In this article, I will explain how to write simple authentication without the help of ready-made solutions for this task. It can be useful for beginners who want to write their own AAA (Authentication, Authorization, and Accounting). Client repository on Angular and Server repository on Spring .
In this article I will make excerpts of the client-side code on the Angular.
In this section, I will describe some aspects of developing a client, whose code can be reworked to interact with your server through the REST API.
Let's look at the project structure:
. ├── auth # │ ├── actions │ │ └── auth.ts │ ├── auth-routing.module.ts │ ├── auth.module.ts │ ├── components │ │ ├── signin.component.ts │ │ └── signup.component.ts │ ├── containers │ │ ├── signin-page.component.ts │ │ └── signup-page.component.ts │ └── services │ └── auth.service.ts └── core # ├── components │ └── index.component.ts ├── containers │ ├── app.component.ts │ └── not-found-page.ts ├── core-routing.module.ts ├── core.module.ts ├── models │ ├── answer-message.ts │ ├── answer.ts # │ ├── notify-type.enum.ts │ ├── ping-payload.ts # │ └── pong-payload.ts # ├── reducers │ └── reducer.reducer.ts └── services ├── cookies.service.ts ├── ping.service.ts # ├── security.service.ts # , API ├── services.module.ts └── utils.service.ts
In order to communicate with the server, we will use the @angular/common/http/HttpClient
with the following hierarchy:
api-base ├── api-security.service └──── security.service
In them we have API
calls for authentication.
Further, the responses from the security.service
service are passed down the hierarchy to the auth.service
service, it stores the user's state in the Store
and Cookies
. Cookies
are used to restore the status of an authenticated user after reloading the page. And in case of errors, they are processed by outputting a message to the console and then passed up the hierarchy.
I will give an example of the authentication method:
authorize(credentials: UserCredentials): Observable<AuthUser | Failure> { return this.securityService.authorize(credentials) // HTTP .pipe( tap(authUser => this.setAuthUserState(authUser)), // catchError(error => { // return this.errorHandler.handleAuthError(error); }) ) }
To send requests to the server, a wrapper is used to HttpClient
- ping.service
, in which the ping
API
method of API
server in Spring is called.
To send data about an authenticated user, an HTTP request breaker is used, which puts AccessToken and UserSession headers.
I will give an example code:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { return this.authService.getLoggedUser() // .pipe( map(authUser => { // let clonedRequest = req.clone(); let isLoggedIn = UtilsService.isLoggedIn(authUser); if (isLoggedIn) { clonedRequest = clonedRequest.clone( { headers: clonedRequest.headers .append(AppConstants.ACCESS_TOKEN_HEADER, authUser.accessToken) .append(AppConstants.USER_SESSION_HEADER, authUser.userSession) } ); } return next.handle(clonedRequest); }), switchMap(value => { return value; }), ); }
The sequence diagram (Sequence Diagram) "Diagram of the sequence of interaction with the server" shows the process of performing requests to the server. After loading the page, the client sends an authentication request (here we consider the case with the passed authentication without errors). Further, after receiving this request, the server issues a token. It is necessary to clarify that the token is not just issued, but after authorization, which is not shown to simplify the scheme. Details on authorization can be found in the related article. Then, after generating the token on the server, the answer is returned to the client. The client saves this token and ping
the server. The server checks the incoming token, processes the ping
request data and generates a new token. In our example, it simply returns the string "${data.getPing()} from ${authUser.getUsername()} and PONG from server"
. After receiving a response from the server, the client saves the token and executes the next request with this new token.
If the token is lost or the client does not correctly save it, then this and the following requests will not pass until the user is authorized again.
In this article, we looked at how to make a simple authentication client using Angular, which simplifies working with this bundle.
Source: https://habr.com/ru/post/354860/
All Articles