Understanding the Composite Application
In this tutorial, we'll build a composite application that consists of two separate applications. This section will explain how this application works.
Introduction to the Application Functionality
The application we'll use is a simple web server that makes use of an authentication service. The web server and the authentication service are implemented as two different Go applications that interact using the HTTP protocol. We'll implement integration tests to validate the interaction between these two parts of the application.
Note: In this tutorial, we used the Gin framework to handle HTTP requests. You can use any framework (or none at all) for your application.
Application 1 (Web Application) Explanation
Application 1 is a public web application. This application exposes API end points that can be accessed from web, mobile and command line applications. This application is responsible for two things:
- Defining and handling HTTP end points and
- Authenticating requests against the authentication service (which will be our second application).
Apart from the /login
and /logout
requests, this application should handle all requests in the following manner:
- Check if the user is authenticated (against the authentication service),
- Serve the content if the user is authenticated, and
- Return an error if the user is not authenticated.
Since the web application uses the authentication service to authenticate users, it doesn't have to worry about things such as the user state.
Application 2 (Authentication Service) Explanation
Application 2 is an authentication service which performs the following tasks:
- Logs a user in if provided with the correct username and password,
- Authenticates a user request if provided with a valid username and token pair, and
- Logs a user out if provided with a valid username and token pair.
In production, the authentication service would typically interact with a database to perform a username/password validation. Additionally, it might also use another service like Redis or Memcached to store user sessions.
For the purpose of this tutorial, we'll hard-code the list of valid users and store the user sessions within the application itself.
Understanding the Interface Between the Two Applications
To understand the interface between the web application and the authentication service, let's consider the following three types of requests:
- A
/login
request, - A
/logout
request, and - Any other request.
The login Request
In a /login
request, the web application expects to receive two values: username
and password
. It then makes its own request to the authentication service at the /login
end point, forwarding these two values.
The authentication service validates the username/password pair. If the validation is successful, it generates a token and stores the username/token pair to authenticate future requests from the same user. It returns this token to the web application. In case of a validation failure, the service responds with an error.
If the authentication service responds with a session token, the web application sets the username and token in cookies for use with future requests. It also returns the token in its response to the original request. The requester can then rely on the cookies for future authentication.
A /logout Request
In a /logout
request, the web application expects to receive two values from cookies: username
and token
. It then makes its own request to the authentication service at the /logout
end point, forwarding these two values.
The authentication service checks whether this is a valid username/token pair. If it is, it removes the username/token pair from its list of authenticated users and responds with a successful status. If the pair is invalid, the authentication service responds with an authentication error.
Any Other Request
For any other request, the web application would expect at least the username
and token
values in addition to request specific values. Before serving these requests, the web application will send a request to the /authenticate
end point of the authentication service.
If the service indicates that authentication was successful, the web application will serve the request. If the service fails to authenticate the username/token pair, the web application will respond with an authentication error.
Note: This flow is applicable only to those requests which require authentication. For any request that doesn't require authentication, there wouldn't be any need to interact with the authentication service.