[料理佳餚] 在 ASP.NET Core 整合 Microsoft 做為網站的第三方登入

第三方登入系列文章的第四篇「在 ASP.NET Core 整合 Microsoft 做第三方登入」,Microsoft 是老牌的大廠,旗下的 Windows、Office、Azure、...等產品,都已經融入了我們的生活當中,Microsoft 也有提供 OAuth 2.0 授權平台,整個整合的過程,就記錄在這篇文章當中。

其他的第三方登入解決方案可以參考下面的連結:

註冊應用程式

首先,先讓 Microsoft 認識我們的應用程式,我們到 Azure 入口網站應用程式註冊的頁面中,註冊我們的應用程式。

點擊「新增註冊」,填入我們想要的「名稱」,下面的「支援的帳戶類型」選擇任何組織目錄中的帳戶 (任何 Azure AD 目錄 - 多租用戶) 和個人 Microsoft 帳戶 (例如 Skype、Xbox),這個選項所支援的 Microsoft 帳戶類型是最廣的,接著「重新導向 URI」如果我們已經知道 Web Api 的網址,可以先填入,不知道也沒關係,之後可以回來修改,最後點擊「註冊」。

應用程式註冊完成後,在「概觀」的頁籤當中,我們會需要應用程式 (用戶端) 識別碼這個資訊,請複製下來備用。

除此之外,還需要「用戶端密碼」,在應用程式的管理頁面中,點選「憑證及秘密」,點擊「新增用戶端密碼」,輸入「描述」後,點擊「新增」。

用戶端密碼新增完成後,將「」複製下來備用。

比起其他平台,Microsoft 的應用程式註冊流程算是很簡潔,一個按鈕、兩三個輸入框,就能註冊成功了,節省不少整合的時間。

準備重新導向 URI

往下進入程式開發的環節,使用者完成授權後,Microsoft 會將 code 回傳到我們設定的重新導向 URI,我們要拿著這個 code 發送 POST 去跟 Microsoft 交換 Access Token,交換 Access Token 的 URL 及參數如下:

  1. AccessTokenUrl:https://login.microsoftonline.com/common/oauth2/v2.0/token
  2. grant_type:填入 "authorization_code"
  3. code:即我們拿到的 code
  4. redirect_uri:即重新導向 URI
  5. client_id:即應用程式 (用戶端) 識別碼
  6. client_secret:即用戶端密碼

重新導向 URI 的程式碼如下:

[HttpGet("callback")]
public async Task<IActionResult> Callback()
{
    if (!this.Request.Query.TryGetValue("code", out var code))
    {
        return this.StatusCode(400);
    }

    var (accessToken, idToken) = await this.ExchangeAccessToken(code);

    if (accessToken == null)
    {
        return this.StatusCode(400);
    }

    // TODO: Save AccessToken and IdToken

    // TODO: User Login

    return this.Redirect("/");
}

private async Task<(string, string)> ExchangeAccessToken(string code)
{
    var client = this.httpClientFactory.CreateClient();

    var request = new HttpRequestMessage(HttpMethod.Post, "AccessTokenUrl");

    request.Content = new FormUrlEncodedContent(
        new Dictionary<string, string>
        {
            ["grant_type"] = "authorization_code",
            ["code"] = code,
            ["redirect_uri"] = "RedirectURI",
            ["client_id"] = "ClientId",
            ["client_secret"] = "ClientSecret"
        });

    var response = await client.SendAsync(request);

    if (response.StatusCode != HttpStatusCode.OK) return (null, null);

    var content = await response.Content.ReadAsStringAsync();

    var result = JsonNode.Parse(content);

    return (result["access_token"].GetValue<string>(), result["id_token"].GetValue<string>());
}

授權網址

最後我們要來兜授權網址,使用者點擊授權網址之後,就開始登入的流程,而 Microsoft 的授權網址是 https://login.microsoftonline.com/common/oauth2/v2.0/authorize,所需參數如下:

  1. response_type:填入 "code"
  2. client_id:即應用程式 (用戶端) 識別碼
  3. redirect_uri:即重新導向 URI
  4. state:隨機產生的一段唯一的字串,主要是可以用來避免 CSRF(Cross Site Request Forgery)
  5. scope:想請使用者授權給我們的資料範圍

由上述參數所兜出來的網址如下:

https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=xxx&redirect_uri=http%3A%2F%2Flocalhost%3A5101%2Fmicrosoft%2Flogin%2Fcallback&state=12345abcde&response_type=code&scope=profile%20openid%20email

登入的流程大致如下圖:

當使用者瀏覽授權網址之後,就會導到 Microsoft 的登入授權畫面,使用者授權後,導回到我們系統,拿到使用者資料就算是整合成功了。

整合了這麼些個 OAuth 2.0 的平台之後,相較於其他平台,Microsoft 的文件是我認為相對清楚的,取得所需要的資訊不用翻箱倒櫃,整個整合起來沒有花太多時間,一路上算是順暢,以上,整合 Microsoft 第三方登入的步驟就分享給大家,希望大家都能整合成功。

參考資料

相關資源

C# 指南
ASP.NET 教學
ASP.NET MVC 指引
Azure SQL Database 教學
SQL Server 教學
Xamarin.Forms 教學