From 83de20bb6ca0669599e93eb74f79b7510831a2fb Mon Sep 17 00:00:00 2001 From: Halil ibrahim Kalkan Date: Sun, 17 Feb 2019 15:31:17 +0300 Subject: [PATCH] Added Authentication Server to the Microservice-Demo document --- docs/en/Samples/Microservice-Demo.md | 107 +++++++++++++++--- .../microservice-sample-authserver-home.png | Bin 0 -> 15896 bytes .../microservice-sample-authserver-login.png | Bin 0 -> 12713 bytes 3 files changed, 89 insertions(+), 18 deletions(-) create mode 100644 docs/en/images/microservice-sample-authserver-home.png create mode 100644 docs/en/images/microservice-sample-authserver-login.png diff --git a/docs/en/Samples/Microservice-Demo.md b/docs/en/Samples/Microservice-Demo.md index 7bbe9d4609..514e4c35d6 100644 --- a/docs/en/Samples/Microservice-Demo.md +++ b/docs/en/Samples/Microservice-Demo.md @@ -34,7 +34,7 @@ You can get the source code from [the GitHub repository](https://github.com/abpf This sample is still in development, not completed yet. -## How To Run? +## Running the Solution You can either run from the **source code** or from the pre-configured **docker-compose** file. @@ -124,21 +124,22 @@ Run the projects with the following order (right click to each project, set as s * BackendAdminApp.Host * PublicWebSite.Host -## Exploring the Solution +## A Brief Overview of the Solution The Visual Studio solution consists of multiple projects each have different roles in the system: ![microservice-sample-solution](../images/microservice-sample-solution.png) -#### Microservices +### Applications -Microservices have no UI, but exposes some REST APIs. +These are the actual applications those have user interfaces to interact to the users and use the system. -* **IdentityService.Host**: Host the ABP Identity module which is used to manage users & roles. It has no additional service, but only hosts the Identity module's API. -* **BloggingService.Host**: Host the ABP Blogging module which is used to manage blog & posts (a typical blog application). It has no additional service, but only hosts the Blogging module's API. -* **ProductService.Host**: Hosts the Product module (that is inside the solution) which is used to manage products. It also contains the EF Core migrations to create/update the Product Management database schema. +- **AuthServer.Host**: Host the IdentityServer4 to provide an authentication service to other services and applications. It is a single-sign server and contains the login page. +- **BackendAdminApp.Host**: This is a backend admin application that host UI for Identity and Product management modules. +- **PubicWebSite.Host**: As public web site that contains a simple product list page and blog module UI. +- **ConsoleClientDemo**: A simple console application to demonstrate the usage of services from a C# application. -#### Gateways / BFFs (Backend for Frontend) +### Gateways / BFFs (Backend for Frontend) Gateways are used to provide a single entry point to the applications. It can also used for rate limiting, load balancing... etc. Used the [Ocelot](https://github.com/ThreeMammals/Ocelot) library. @@ -146,28 +147,98 @@ Gateways are used to provide a single entry point to the applications. It can al * **PublicWebSiteGateway.Host**: Used by the PublicWebSite.Host application as backend. * **InternalGateway.Host**: Used for inter-service communication (the communication between microservices). -#### Applications +### Microservices -These are the actual applications those have user interfaces to interact to the users. +Microservices have no UI, but exposes some REST APIs. -* **AuthServer.Host**: Host the IdentityServer4 to provide an authentication service to other services and applications. It is a single-sign on server and contains the login page. -* **BackendAdminApp.Host**: This is a backend admin application that host UI for Identity and Product management modules. -* **PubicWebSite.Host**: As public web site that contains a simple product list page and blog module UI. -* **ConsoleClientDemo**: A simple console application to demonstrate the usage of services from a C# application. +- **IdentityService.Host**: Host the ABP Identity module which is used to manage users & roles. It has no additional service, but only hosts the Identity module's API. +- **BloggingService.Host**: Host the ABP Blogging module which is used to manage blog & posts (a typical blog application). It has no additional service, but only hosts the Blogging module's API. +- **ProductService.Host**: Hosts the Product module (that is inside the solution) which is used to manage products. It also contains the EF Core migrations to create/update the Product Management database schema. -#### Modules +### Modules * **Product**: A layered module that is developed with the [module development best practices](../Best-Practices/Index.md). It can be embedded into a monolithic application or can be hosted as a microservice by separately deploying API and UI (as done in this demo solution). -#### Databases +### Databases This solution is using multiple databases: * **MsDemo_Identity**: An SQL database. Used **SQL Server** by default, but can be any DBMS supported by the EF Core. Shared by AuthServer and IdentityService. Also audit logs, permissions and settings are stored in this database (while they could easily have their own databases, shared the same database to keep it simple). -* **MsDemo_Productmanagement**: An SQL database. Again, used **SQL Server** by default, but can be any DBMS supported by the EF Core. Used by the ProductService as a dedicated database. +* **MsDemo_ProductManagement**: An SQL database. Again, used **SQL Server** by default, but can be any DBMS supported by the EF Core. Used by the ProductService as a dedicated database. * **MsDemo_Blogging**: A **MongoDB** database. Used by the BloggingService. * **Elasticsearch**: Used to write logs over Serilog. +## Applications + +### Authentication Server (AuthServer.Host) + +This project is used by all other services and applications for authentication & single sign on. Mainly, uses **IdentityServer4** to provide these services. It uses some of the [pre-build ABP modules](../Modules/Index) like *Identity*, *Audit Logging* and *Permission Management*. + +#### Database & EF Core Configuration + +This application uses a SQL database (named it as **MsDemo_Identity**) and maintains its schema via **Entity Framework Core migrations.** + +It has a DbContext named **AuthServerDbContext** and defined as shown below: + +````csharp +public class AuthServerDbContext : AbpDbContext +{ + public AuthServerDbContext(DbContextOptions options) + : base(options) + { + + } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + base.OnModelCreating(modelBuilder); + + modelBuilder.ConfigureIdentity(); + modelBuilder.ConfigureIdentityServer(); + modelBuilder.ConfigureAuditLogging(); + modelBuilder.ConfigurePermissionManagement(); + modelBuilder.ConfigureSettingManagement(); + } +} +```` + +In the **OnModelCreating**, you see **ConfigureX()** method calls. A module with a database schema generally declares such an extension method to configure EF Core mappings for its own entities. This is a flexible approach where you can arrange your databases and modules inside them; You can use a different database for each module, or combine some of them in a shared database. In the AuthServer project, we decided to combine multiple module schemas in a single EF Core DbContext, in a single physical database. These modules are Identity, IdentityServer, AuditLogging, PermissionManagement and SettingManagement modules. + +#### User Interface + +AuthServer has a simple home page that shows the current user info if the current user has logged in: + +![microservice-sample-authserver-home](../images/microservice-sample-authserver-home.png) + +It also provides Login & Register pages: + +![microservice-sample-authserver-login](../images/microservice-sample-authserver-login.png) + +These pages are not included in the project itself. Instead, AuthServer project uses the prebuilt ABP [account module](https://github.com/abpframework/abp/tree/master/modules/account) with IdentityServer extension. That means it can also act as an OpenId Connect server with necessary UI and logic. + +#### Other Dependencies + +* **RabbitMQ** for messaging to other services. +* **Redis** for distributed/shared caching. + +### Backend Admin Application (BackendAdminApp.Host) + +TODO + +## Microservices + ### Identity Service -TODO... \ No newline at end of file +TODO + +## Infrastructure + +TODO + +### Messaging + +### Caching + +### Logging + +### Correlation Id \ No newline at end of file diff --git a/docs/en/images/microservice-sample-authserver-home.png b/docs/en/images/microservice-sample-authserver-home.png new file mode 100644 index 0000000000000000000000000000000000000000..7ae62ad6d5e0946480a1eeaa3f3e77eea05fa85f GIT binary patch literal 15896 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�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 L%Lr8q=mq=_z{tee literal 0 HcmV?d00001 diff --git a/docs/en/images/microservice-sample-authserver-login.png b/docs/en/images/microservice-sample-authserver-login.png new file mode 100644 index 0000000000000000000000000000000000000000..f6e8dfaa9f3ce2c3c25a8cca66d669225a49bac6 GIT binary patch literal 12713 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