เว็บแอพ Authen ด้วย Azure AD B2C

  1. สร้าง Azure Active Directory B2C tenant
  2. Register the app in Azure AD B2C
  3. สร้าง Policy (user flows)
  4. สร้าง ASP.NET Core Web Application
  5. ตรวจสอบ user

1.สร้าง Azure AD B2C tenant

สร้าง Azure Active Directory B2C tenant

2.Register the app in Azure AD B2C

ไปที่ Directory ของ B2C tenant

เลือกเมนู All services แล้วพิมพ์ Azure AD B2C

เลือก Azure AD B2C

เลือก Application แล้วเลือก Add

https://localhost:44355/signin-oidc ดูมาจากรูปล่าง

3.สร้าง Policy (user flows)

3.1 สร้าง Sign-up or sign-in policy ชื่อ B2C_1_SiUpIn

เลือกเมนู User flows (policies)

เลือก New user flow

เลือก Sign up and sign in

1.Name ใส่ SiUpIn

2.เลือก Email signup

3.Multifactor authentication เลือก Disabled

4. User attributes and claims เลือก Country และ Email

ถ้ากด Show more จะขึ้นมาให้เลือกเยอะเลย

กด Create

3.2 สร้าง Password reset ชื่อ B2C_1_SSPR

เลือก Password reset

1.Name ใส่ SSPR

2.เลือก Email signup

เสร็จแล้วกลับมาดูที่ User flows (policies) จะเห็น B2C_1_SiUpIn และ B2C_1_SSPR

4.สร้าง ASP.NET Core Web Application

สร้างโปรเจ็กส์แบบ Web Application .NET Core

ค่าต่างๆนี้สามารถแก้ไขได้ที่ไฟล์ appsettings.json

ถ้าเทียบระหว่างโปรเจ็กส์ Web Application .NET Core ที่สร้างขึ้นแบบไม่มี Authen เทียบกับ โปรเจกส์ที่สร้างแบบ Authen ด้วย B2C จะแตกต่างกันที่ไฟล์ appsettings.json, Startup.cs, Pages/Shared/_Layout.cshtml และมีเพิ่มไฟล์ Pages/Shared/_LoginPartial.cshtml

ไฟล์ appsettings.json

{
  "AzureAdB2C": {
    "Instance": "https://JackB2C2019.b2clogin.com/tfp/",
    "ClientId": "11112222-1111-1111-1111-111122223333",
    "CallbackPath": "/signin-oidc",
    "Domain": "JackB2C2019.onmicrosoft.com",
    "SignUpSignInPolicyId": "B2C_1_SiUpIn",
    "ResetPasswordPolicyId": "B2C_1_SSPR",
    "EditProfilePolicyId": ""
  },
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*"
}

ไฟล์ Startup.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.AzureADB2C.UI;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace WebApp1
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });

            services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme)
                .AddAzureADB2C(options => Configuration.Bind("AzureAdB2C", options));

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseCookiePolicy();

            app.UseAuthentication();

            app.UseMvc();
        }
    }
}

ไฟล์ Pages/Shared/_Layout.cshtml

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - WebApp1</title>

    <environment include="Development">
        <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.css" />
    </environment>
    <environment exclude="Development">
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css"
              asp-fallback-href="~/lib/bootstrap/dist/css/bootstrap.min.css"
              asp-fallback-test-class="sr-only" asp-fallback-test-property="position" asp-fallback-test-value="absolute"
              crossorigin="anonymous"
              integrity="sha256-eSi1q2PG6J7g7ib17yAaWMcrr5GrtohYChqibrV7PBE="/>
    </environment>
    <link rel="stylesheet" href="~/css/site.css" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">WebApp1</a>
                <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">
                    <partial name="_LoginPartial" />
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <partial name="_CookieConsentPartial" />
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            © 2019 - WebApp1 - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <environment include="Development">
        <script src="~/lib/jquery/dist/jquery.js"></script>
        <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.js"></script>
    </environment>
    <environment exclude="Development">
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"
                asp-fallback-src="~/lib/jquery/dist/jquery.min.js"
                asp-fallback-test="window.jQuery"
                crossorigin="anonymous"
                integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=">
        </script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/js/bootstrap.bundle.min.js"
                asp-fallback-src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"
                asp-fallback-test="window.jQuery && window.jQuery.fn && window.jQuery.fn.modal"
                crossorigin="anonymous"
                integrity="sha256-E/V4cWE4qvAeO5MOhjtGtqDzPndRO1LBk8lJ/PR7CA4=">
        </script>
    </environment>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @RenderSection("Scripts", required: false)
</body>
</html>

มีไฟล์เพิ่มมาคือไฟล์ Pages/Shared/_LoginPartial.cshtml

@using Microsoft.AspNetCore.Authentication.AzureADB2C.UI
@using Microsoft.Extensions.Options
@inject IOptionsMonitor<AzureADB2COptions> AzureADB2COptions

@{
    var options = AzureADB2COptions.Get(AzureADB2CDefaults.AuthenticationScheme);
}


<ul class="navbar-nav">
@if (User.Identity.IsAuthenticated)
{
        @if (!string.IsNullOrEmpty(options.EditProfilePolicyId))
        {
            <li class="nav-item">
                <a class="nav-link text-dark" asp-area="AzureADB2C" asp-controller="Account" asp-action="EditProfile">
                    <span class="nav-text text-dark">Hello @User.Identity.Name!</span>
                </a>
            </li>
        }
        else
        {
            <li class="nav-item">
                <span class="nav-text text-dark">Hello @User.Identity.Name!</span>
            </li>
        }
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="AzureADB2C" asp-controller="Account" asp-action="SignOut">Sign out</a>
        </li>
}
else
{
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="AzureADB2C" asp-controller="Account" asp-action="SignIn">Sign in</a>
        </li>
}
</ul>

5.ตรวจสอบ user

รันโปรแกรม

และสมัครเข้าใช้ด้วย email

กลับมาที่หน้า portal (Azure AD B2C) แล้วเลือก Users

จะเห็น user ที่เราสมัครใหม่ด้วย email เป็นชนิด Azure Active Directory