[C#] 使用 Google 帳號登入 - 簡單實現從授權到用戶資料取得

  • 9367
  • 0
  • 2025-11-18

最近因為朋友在問我如何 透過 Google 登入,並且取得用戶的資料,上網查一下,其實是有套件

但是因為對方需求,相關套件不方便入手或無法滿足特定需求,直接使用 C# 來實作 OAuth 機制統合是一個好方式。

今天筆記一下如何 透過純 OAuth 來做到,在 .NET 8 + ASP.NET  中實作 Google OAuth2 驗證。

OAuth2 流程概述

OAuth2 是一種安全的授權協定,通常用於認證與認識網站用戶。此次實作使用的流程如下:

1.在 Google Cloud Developer 後台拿到開發資訊,這一步最難,不得不說 那邊非常複雜,我分享兩張圖

你自己想辦法,找到這兩個值吧 用戶端編號 client_id,跟用戶端密碼  client_secret





 

2.讓用戶前往 Google OAuth2 的授權頁面。


        
        public IActionResult OnPostGooogleAuth()
        {


            //跳轉先去拿到code
            return new RedirectResult("https://accounts.google.com/o/oauth2/v2/auth?" +
                "response_type=code" +
                "&client_id=" + clientId+
                "&redirect_uri=" + HttpUtility.UrlEncode(redirectUrl) +
                "&include_granted_scopes=true"+
                "&scope=https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile openid" +
                "&state=donmaid" +
                "" + DateTime.Now.ToString("yyMMddHHmmss"));


        }
        

3.用戶授權後你會在 redirect_url 收到一個用戶 code。


       public void OnGet()
        {
        
            if (!string.IsNullOrEmpty(Request.Query["code"]))
            {
                GoogleAccessToken = Request.Query["code"];
            }

            if (!string.IsNullOrEmpty(Request.Query["state"]))
            {
                InnerUserId = Request.Query["state"];
            }
        }
      

4.用戶 code 換取認證的 access token。

   

        /// <summary>
        /// 透過 user code 拿到 access token
        /// </summary>
        /// <param name="clientId"></param>
        /// <param name="cluentSecret"></param>
        /// <param name="userCode"></param>
        /// <returns></returns>
        public string GetAccessTokenByCode(string clientId, string clientSecret, string userCode) {
            var client = new RestClient("https://accounts.google.com/o/oauth2/token");

            var request = new RestRequest(new Uri("https://accounts.google.com/o/oauth2/token"), Method.Post);

            request.AddHeader("Content-Type", "application/x-www-form-urlencoded");


            request.AddParameter("client_id", clientId);
            request.AddParameter("client_secret", clientSecret);
            request.AddParameter("grant_type", "authorization_code");
            request.AddParameter("code", userCode);
            request.AddParameter("redirect_uri", redirectUrl);

            try
            {

                var response = client.ExecuteAsync(request).Result;

                if (response.IsSuccessful)
                {
                    return response.Content;
                }
                else
                {
                    return ($"Error: {response.StatusCode} - {response.ErrorMessage}");
                }
            }
            catch (Exception ex)
            {
                return ("Exception occurred: " + ex.Message);
            }

        }


        //Response:
        /*
        {"access_token": "access_token_code", "expires_in": 3597, 
         "scope": "openid https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile",
         "token_type": "Bearer", "id_token": "id_token" }
        /*


5.通過 access token 取得用戶資料。

 	/// <summary>
    /// 透過 user token 拿到 user profile
    /// </summary>
    /// <param name="accesstoken"></param>
    /// <returns></returns>
    public string GetGooogleUserInfoByAccesstoken( string accesstoken)
    {


        var client = new RestClient("https://www.googleapis.com/oauth2/v3/userinfo?access_token="+accesstoken);

        var request = new RestRequest(new Uri("https://www.googleapis.com/oauth2/v3/userinfo?access_token=" + accesstoken), Method.Get);


        try
        {

            var response = client.ExecuteAsync(request).Result;

            if (response.IsSuccessful)
            {
                return response.Content;
            }
            else
            {
                return ($"Error: {response.StatusCode} - {response.ErrorMessage}");
            }
        }
        catch (Exception ex)
        {
            return ("Exception occurred: " + ex.Message);
        }


    }
    
    
    
    //Result
    /*
    
    
    { "sub": "110525762531932290727", "name": "Hsu DMA", "given_name": "Hsu",
      "family_name": "DMA", "picture": 
      "https://lh3.googleusercontent.com/a/ACg8ocJRBsgW_uCQGHXATIm9ODBqmNrE9gpbE7dg1qg_Od0XdfJCOL5q\u003ds96-c",
      "email": "sample@gmail.com", "email_verified": true }
    
    
    */

就簡單筆記一下,方便之後自己 copy paste.

--

本文原文首發於我的個人部落格:使用 Google 帳號登入 - 簡單實現從授權到用戶資料取得

---

The bug existed in all possible states.
Until I ran the code.