An Introduction of a Microservices with ASP.net core 3x(Part-2)

Before you proceed...

We want to start writing code and deploying our Microservices to Amazon Web Services. So you will need to have a few things prepared.

**Step1:** Have a Source Control system ready. The easiest way of having a source control system is to sign up with GitHub at https://github.com with a free account.

**Step2:** Install .NET Core SDK. It can be any .NET Core SDK as long as it is not .Net Core 3.0 or 3.1
Install Visual Studio 2017 or higher

**Step3:** Create a free account at AWS  ( https://aws.amazon.com/free ). You will need this account to deploy your Microservices.

If you did not reach out Part-1 then please go through the below link.
(Introduction about the Microservices architecture and Monolithic application/architecture and problems.)
An Introduction of a Microservices with ASP.net core 3x(Part-1)
https://qiita.com/alokrawat050/items/66a512dc840827107260

In this part, we will do the sign-up, confirm the email, and will play with AWS settings.
Let's Create a project file and will do AWS Cognito setting part:

**Step 1: Open you vs code and create a .net core application.**
![Screen Shot 2020-03-07 at 15.27.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/58f06c1e-0ca4-9c5b-0bbf-b4b7da9d4fae.png)
<:-------------------------------------------**1**-----------------------------------------:>
![Screen Shot 2020-03-07 at 15.30.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/bafc08ac-750a-7aa6-ed45-aefa9bbcbe41.png)
<:-------------------------------------------**2**-----------------------------------------:>
![Screen Shot 2020-03-07 at 15.32.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/f7a48816-2d6a-ec1d-d2b9-2bdf055c1e5a.png)
<:-------------------------------------------**3**-----------------------------------------:>
![Screen Shot 2020-03-07 at 15.34.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/6ffc2098-f459-80ba-7bb4-33453033a51b.png)

**Step 2: Add a few AWS Packages in the project**
Go to the "**Project**" -> "**Manage NuGet Pacakges...**"
![Screen Shot 2020-03-07 at 15.51.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/31ae8afe-1877-4abf-1b2d-582f460b9885.png)

then search "**Amazon.AspNetCore.Identity.Cognito**"
![Screen Shot 2020-03-07 at 15.51.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/b78ca250-bc44-3e0a-4483-388bf2069911.png)

then search "**Amazon.Extensions.CognitoAuthentication**"
![Screen Shot 2020-03-07 at 15.54.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/d50ccd5f-383e-1ffa-7e16-131144ca2fcf.png)


**Step 3: Create a new User in AWS**
here I already created a new user called "**ad_word_user**"
![user_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/21f96b2a-5c25-0d95-348c-ad5bbd0ce4d2.png)
<:-------------------------------------------**1**-----------------------------------------:>
![user_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/38576ecc-14c9-909e-affa-750cb831dfd3.png)
<:-------------------------------------------**2**-----------------------------------------:>
![user_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/1b68a522-8ab7-29d5-a6d6-ac4aad11dfe5.png)

now set a new permission, **AmazonCognitoDeveloperAuthenticatedIdentities**
![user_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/dba5521e-50f9-de45-bacf-d5af122b5647.png)

**Step 4: Setup AWS Cognito**
Search **Cognito** from your dashboard.
![cognito_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/cb55c4f3-5429-c22a-b428-6b89b617994d.png)
<:-------------------------------------------**3**-----------------------------------------:>
![cognito_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/7891fa52-d541-b1d1-84fe-59cf2ab37dd0.png)
<:-------------------------------------------**4**-----------------------------------------:>
![cognito_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/2d6ef411-7d06-0e3f-39fa-43d9d0d67be6.png)
<:-------------------------------------------**5**-----------------------------------------:>
![cognito_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/645d35fd-d2ec-8bd6-7bf8-13a948b92b42.png)
<:-------------------------------------------**6**-----------------------------------------:>
![cognito_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/2039cd97-a8cf-05e2-2a9c-68e25929af12.png)
<:-------------------------------------------**7**-----------------------------------------:>
![cognito_6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/e8e74587-30f8-3f32-b7b3-326b8d638013.png)
<:-------------------------------------------**8**-----------------------------------------:>
![cognito_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/7d223f62-6b17-def5-a132-40fc5e72a0f2.png)
<:-------------------------------------------**9**-----------------------------------------:>
![cognito_8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/8a3c58d4-757a-3212-3d8f-2bd98ecb1d7b.png)
<:-------------------------------------------**10**-----------------------------------------:>
![cognito_9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/826aa013-daa2-7c93-7f36-cfb0194e5296.png)
<:-------------------------------------------**11**-----------------------------------------:>
![cognito_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/201d0a03-4110-0c6a-d188-3c14aab5aa7d.png)
<:-------------------------------------------**12**-----------------------------------------:>
![cognito_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/159806b2-42db-b2f1-add7-802246967ef0.png)
<:-------------------------------------------**13**-----------------------------------------:>
![cognito_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/5150f833-1231-e962-60fd-6e423802f1d3.png)


**Step 5: Create a New App Client**
Create a new app client and copy the **app_client_id** and **app_client_secret**
![app_cognito_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/5626baf0-6866-725f-e7ae-a81f36b50e8a.png)
<:-------------------------------------------**1**-----------------------------------------:>
![app_cognito_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/f448eef7-b650-6fbf-764d-1a62395ed836.png)
<:-------------------------------------------**2**-----------------------------------------:>
![app_cognito_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/7ad6533d-fc61-88ff-91be-8328e096d487.png)


**Step 6: SetUp app client ID and client secret**
Open the file **appsettings.json** and copy the below code and paste in your file.

```
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "AWS": {
    "Region": "<YOUR_REGION>",
    "UserPoolClientId": "<YOUR_CLIENT_ID>",
    "UserPoolClientSecret": "<YOUR_CLIENT_SECRET>",
    "UserPoolId": "<YOUR_POOL_ID>"
  }
}

```

**UserPoolId**,
![user_pool_id.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/24d25379-1f7e-32e9-631e-c4921123d58a.png)

**Step 7: Create Below files in the following directories:**
■. in the **Controllers** directory, create a **Accounts.cs** controller.

```
   right-click on Controllers directory
   add -> new file
   ASP.NET Core -> MVC Controller Class 
```

■. in the **Models** directory, create a new directory, called **Accounts** and inside the newly created directory, create two model files, **ConfirmModel.cs** and **SignupModel.cs**

```
   right-click on Models directory
   add -> new folder -> [Accounts]

   then right-click on the newly created directory, called Accounts
   add -> new class
   General -> Empty Class
```

■. in the **Views** directory, create a new directory, called **Accounts** and inside the newly created directory, create two model files, **Confirm.cshtml** and **Signup.cshtml**

```
   right-click on Views directory
   add -> new folder -> [Accounts]

   then right-click on newly created directory, called Accounts
   add -> new file
   ASP.NET Core -> Razor Page
```

**Step 8: Code:**
in the **Accounts.cs** file,

```
using System.Threading.Tasks;
using Amazon.AspNetCore.Identity.Cognito;
using Amazon.Extensions.CognitoAuthentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using WebAdWord.Models.Accounts;
```

```
public class Accounts : Controller
    {
        private readonly SignInManager<CognitoUser> _signInManager;
        private readonly UserManager<CognitoUser> _userManager;
        private readonly CognitoUserPool _pool;

        public Accounts(SignInManager<CognitoUser> signInManager, UserManager<CognitoUser> userManager, CognitoUserPool pool)
        {
            _signInManager = signInManager;
            _userManager = userManager;
            _pool = pool;
        }
    }
```

```
public async Task<IActionResult> Signup()
        {
            var model = new SignupModel();
            return View(model);
        }

[HttpPost]
        public async Task<IActionResult> Signup(SignupModel model)
        {
            if (ModelState.IsValid)
            {
                var user = _pool.GetUser(model.Email);
                if (user.Status != null)
                {
                    ModelState.AddModelError("UserExists", "User with this email alred exits");
                    return View(model);
                }

                user.Attributes.Add(CognitoAttribute.Name.AttributeName, model.Email);
                var createdUser = await _userManager.CreateAsync(user, model.Password).ConfigureAwait(false);

                if (createdUser.Succeeded)
                {
                    RedirectToAction("Confirm");
                }
            }
            return View();
        }
```

```
[HttpGet]
        public async Task<IActionResult> Confirm(ConfirmModel model)
        {            
            return View(model);
        }

        [HttpPost]
        [ActionName("Confirm")]
        public async Task<IActionResult> Confirm_Post(ConfirmModel model)
        {
            if (ModelState.IsValid)
            {
                var user = await _userManager.FindByEmailAsync(model.Email).ConfigureAwait(false);
                if (user == null)
                {
                    ModelState.AddModelError("NotFound", "A user with the given email address was not found.");
                    return View(model);
                }
                
                var result = await (_userManager as CognitoUserManager<CognitoUser>).ConfirmSignUpAsync(user, model.Code, true).ConfigureAwait(false);
                if (result.Succeeded)
                {
                    return RedirectToAction("Index", "Home");
                }
                else
                {
                    foreach(var item in result.Errors)
                    {
                        ModelState.AddModelError(item.Code, item.Description);
                    }

                    return View(model);
                }
            }

            return View(model);
        }
```

the above all codes belongs to the ⬇︎ 
**public class Accounts : Controller {
   --here--
}**


in the **Models/Accounts/SignupModel.cs** file,

```
using System.ComponentModel.DataAnnotations;

namespace WebAdWord.Models.Accounts
{
    public class SignupModel
    {
        [Required]
        [EmailAddress]
        [Display(Name ="Email")]
        public string Email{ get; set; }

        [Required]
        [DataType(DataType.Password)]
        [StringLength(8, ErrorMessage ="Password must be at least six characters long!")]
        [Display(Name ="Password")]
        public string Password { get; set; }

        [Required]
        [DataType(DataType.Password)]
        [Compare("Password", ErrorMessage ="Password and its confirmation do not match")]
        public string ConfirmPassword { get; set; }

        public SignupModel()
        {
        }
    }
}
```

in the **Models/Accounts/ConfirmModel.cs** file,

```
using System.ComponentModel.DataAnnotations;

namespace WebAdWord.Models.Accounts
{
    public class ConfirmModel
    {
        [Required(ErrorMessage = "Email is required.")]
        [Display(Name ="Email")]
        [EmailAddress]
        public string Email { get; set; }

        [Required(ErrorMessage ="Code is required.")]
        public string Code { get; set; }        
    }
}
```


in the **Views/Accounts/Signup.cshtml** file,

```
@{
    ViewData["Title"] = "SignUp Page";
}

@model WebAdWord.Models.Accounts.SignupModel;

<div class="row">
    <div class="col-md-4">
        <form method="post" asp-controller="Accounts" asp-action="Signup">
            <h4>Create a new account</h4>
            <hr />
            <div asp-validation-summary="All" class="text-danger">

            </div>

            <div class="form-group">
                <label asp-for="Email"></label>
                <input asp-for="Email" class="form-control" />
                <span asp-validation-for="Email" class="text-danger"></span>
            </div>

            <div class="form-group">
                <label asp-for="Password"></label>
                <input asp-for="Password" class="form-control" />
                <span asp-validation-for="Password" class="text-danger"></span>
            </div>

            <div class="form-group">
                <label asp-for="ConfirmPassword"></label>
                <input asp-for="ConfirmPassword" class="form-control" />
                <span asp-validation-for="ConfirmPassword" class="text-danger"></span>
            </div>
            
            <button type="submit" class="btn btn-default">Sign Up</button>
        </form>
    </div>
</div>
```

in the **Views/Accounts/Confirm.cshtml** file,

```
@{
    ViewData["Title"] = "Confirm Page";
}

@model WebAdWord.Models.Accounts.ConfirmModel;

<div class="row">
    <div class="col-md-4">
        <form method="post" asp-controller="Accounts" asp-action="Confirm">
            <h4>Confirm the new account</h4>
            <hr />
            <div asp-validation-summary="All" class="text-danger"></div>

            <div class="form-group">
                <label asp-for="Email"></label>
                <input asp-for="Email" />
                <span asp-validation-for="Email" class="text-danger"></span>
            </div>

            <div class="form-group">
                <label asp-for="Code"></label>
                <input asp-for="Code" />
                <span asp-validation-for="Code" class="text-danger"></span>
            </div>

            <button type="submit">Confirm</button>
        </form>
    </div>
</div>
```

**Step 9: Debug the Code:**
![Screen Shot 2020-05-11 at 21.57.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/b56c3e66-0c6c-23f7-301d-c24ec937e459.png)

After sign-up you will get a mail.
![Screen Shot 2020-05-11 at 21.59.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/37372658-c6e2-ba18-3e00-501c8e0e5383.png)

Copy the verification code and then access the below URL:
https://localhost:5001/Accounts/Confirm
![Screen Shot 2020-05-11 at 22.01.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/d8b19ae3-057d-c58f-056f-6fc68a175558.png)

After Successfully confirming you will redirect to the Home Page.
![Screen Shot 2020-05-11 at 22.01.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/8dcb5633-6dca-dcbd-29c7-2f35f98a20e1.png)


**Step 10: AWS Cognito Dashboard**
Here you can see that newly created user's display in the dashboard.
![Screen Shot 2020-03-13 at 17.32.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117479/aabbda85-cf55-d87d-1c6b-9f8462944ad5.png)


In the next part, we will implement login, forgot password, and reset password functionality.

If you encountered any error then please share it with me.
If this guide has been helpful for you and your team please share it with others!

**Thanks & Best Regards,
Alok Rawat**