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

  1. สร้าง Azure App Service
  2. กำหนดวิธี Authen เป็น Azure Active Directory
  3. สร้าง user Azure Active Directory
  4. อ่านค่า userid จาก .auth/me

1.สร้าง Azure App Service

ไปที่ Portal เลือกเมนู Create a resource > Web > Web App

ตั้งชื่อ jackwebapp แล้วจะได้ url เป็น jackwebapp.azurewebsites.net

2. กำหนดวิธี Authen เป็น Azure Active Directory

อยู่ที่ App Service ที่เราสร้าง (jackwebapp) เลือก Authentication / Authorization

แล้วกำหนดให้ App Service Authentication เป็น On

เลือก Authentication Providers เป็น Azure Active Directory

เลือก Management mode เป็น Express แล้วตั้งชื่อ Application เป็น Jack Web App แล้วกด OK

เลือก Action to take when request is not authenticated เป็น Log in with Azure Active Directory แล้วกด Save

3.สร้าง user Azure Active Directory

ที่ portal ไปที่ Azure Active Directory แล้วเลือก Users

กด New User

ตั้ง User name เช่น jack@phaisarnoutlook.onmicrosoft.com

เลือก Show Password เพือ่ใช้ในการ login แล้วกด Create

เข้าเว็บ https://jackwebapp.azurewebsites.net แล้วลงชื่อเข้าใช้ด้วย Username
jack@phaisarnoutlook.onmicrosoft.com

ในการ login ครั้งแรก หลังจากใส่ username & password เสร็จ จะให้ตั้ง password ใหม่

เสร็จแล้วก็จะขอ permission เลือก Accept

จะเข้าหน้าแรกได้ละ

ต่อมาก็เข้าที่ https://jackwebapp.azurewebsites.net/.auth/me เพื่อดู token

4.อ่านค่า userid จาก .auth/me

ทำการสร้าง webapp และ deploy ขึ้น App Service ตาม link นี้

ต่อไปแก้ไขโปรแกรมเพื่ออ่านค่า user_id จาก .auth/me

แก้ไขไฟล์ Program.cs

using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;

namespace WebAppCore
{
    public class Program
    {
        public static string user_id;

        public static void Main(string[] args)
        {
            CreateWebHostBuilder(args).Build().Run();
        }

        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }
}

แก้ไขไฟล์ Startup.cs

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Http;
using System.Security.Claims;
using System.Security.Principal;

namespace WebAppCore
{
    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.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.Use(async (context, next) =>
            {
                //Global.userid += "0";
                // Create a user on current thread from provided header
                if (context.Request.Headers.ContainsKey("X-MS-CLIENT-PRINCIPAL-ID"))
                {
                    //Global.userid += "1";
                    // Read headers from Azure
                    var azureAppServicePrincipalIdHeader = context.Request.Headers["X-MS-CLIENT-PRINCIPAL-ID"][0];
                    var azureAppServicePrincipalNameHeader = context.Request.Headers["X-MS-CLIENT-PRINCIPAL-NAME"][0];
                    #region extract claims via call /.auth/me
                    //invoke /.auth/me
                    var cookieContainer = new CookieContainer();
                    HttpClientHandler handler = new HttpClientHandler()
                    {
                        CookieContainer = cookieContainer
                    };
                    string uriString = $"{context.Request.Scheme}://{context.Request.Host}";
                    foreach (var c in context.Request.Cookies)
                    {
                        cookieContainer.Add(new Uri(uriString), new Cookie(c.Key, c.Value));
                    }
                    string jsonResult = string.Empty;
                    using (HttpClient client = new HttpClient(handler))
                    {
                        var res = await client.GetAsync($"{uriString}/.auth/me");
                        jsonResult = await res.Content.ReadAsStringAsync();
                    }
                    //parse json
                    var obj = JArray.Parse(jsonResult);
                    string user_id = obj[0]["user_id"].Value<string>(); //user_id
                    string provider_name = obj[0]["provider_name"].Value<string>();
                    Program.user_id = user_id;
                    // Create claims id
                    List<Claim> claims = new List<Claim>();
                    foreach (var claim in obj[0]["user_claims"])
                    {
                        claims.Add(new Claim(claim["typ"].ToString(), claim["val"].ToString()));
                    }
                    // Set user in current context as claims principal
                    var identity = new GenericIdentity(azureAppServicePrincipalIdHeader);
                    identity.AddClaims(claims);
                    #endregion
                    // Set current thread user to identity
                    context.User = new GenericPrincipal(identity, null);
                };
                await next.Invoke();
            });
            
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                app.UseHsts();
            }

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

            app.UseMvc();
        }
    }
}

แสดงค่า user_id ที่ About.cshtml.cs

using Microsoft.AspNetCore.Mvc.RazorPages;

namespace WebAppCore.Pages
{
    public class AboutModel : PageModel
    {
        public string Message { get; set; }

        public void OnGet()
        {
            Message = Program.user_id;
        }
    }
}

อัพโค๊ดขึ้นอีกที ก็จะเห็น user_id ของ user ที่ login เข้ามาละ