解碼 id_token


簡介

id_token是一個特殊的token,在Microsoft Graph的認證和授權過程中頒發,它包含了已認證用戶的一些信息。本文將介紹如何通過實例理解id_token,並且演示了如何解碼。

准備環境

本文假設你已經知道如何在Azure AD中創建應用程序注冊,並且在本地創建一個最簡單的網站應用程序,下面這個是用asp.net core 創建的一個例子

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Diagnostics;
using System.Text;
using System.IO;

namespace webconsole
{
    public class Startup
    {
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
        }

        // 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();
            }

            app.Run(async (context) =>
            {
                
                var sb = new StringBuilder();

                foreach (var item in context.Request.Query)
                {
                    sb.AppendLine($"{item.Key}={item.Value}");
                }

                var reader = new StreamReader(context.Request.Body);
                sb.AppendLine(reader.ReadToEnd());
                

                await context.Response.WriteAsync(sb.ToString());
            });
        }
    }
}

通過dotnet run命令可以將這個應用程序運行起來。

如何獲取id_token

id_token是一個特殊的token,在Microsoft Graph的認證和授權過程中頒發,它包含了已認證用戶的一些信息。認證的協議,我們可以統一使用OpenId Connect(實際上,這是基於OAuth 的一個簡單版本),授權的協議,則是采用OAuth。

如果只是需要進行身份認證,使用OpenId Connect,但需要注意的是,這種方式主要適合在Web應用中,有用戶交互的情況下,你可以通過在瀏覽器中輸入下面的地址請求用戶身份認證

https://login.microsoftonline.com/common/oauth2/authorize?client_id=`611993e2-bf37-4895-841d-9737076cdb45`&response_type=`id_token`&redirect_uri=`http://localhost:5000`&response_mode=`form_post`&scope=`openid`*&state=`12345`&nonce=`7362CAEA-9CA5-4B43-9BA3-34D7C303EBA7`

完成身份認證后,正常情況下在瀏覽器中可以看到如下的結果

頁面上已經可以看到id_token的信息。這是一串Base64編碼的文本,如下所示

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IkZTaW11RnJGTm9DMHNKWEdtdjEzbk5aY2VEYyIsImtpZCI6IkZTaW11RnJGTm9DMHNKWEdtdjEzbk5aY2VEYyJ9.eyJhdWQiOiI2MTE5OTNlMi1iZjM3LTQ4OTUtODQxZC05NzM3MDc2Y2RiNDUiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC81OTcyM2Y2Yi0yZDE0LTQ5ZmUtODI3YS04ZDA0ZjlmZTdhNjgvIiwiaWF0IjoxNTIxNjk0ODg5LCJuYmYiOjE1MjE2OTQ4ODksImV4cCI6MTUyMTY5ODc4OSwiYWlvIjoiWTJOZ1lMQzlKLzYzek9JNFQzekFGYyt6ejkvRnZVMElpWjNYb1pEaXREbjQ4ZmJyRElJQSIsImFtciI6WyJwd2QiXSwiZmFtaWx5X25hbWUiOiLpmYgiLCJnaXZlbl9uYW1lIjoi5biM56ugIiwiaXBhZGRyIjoiMTY3LjIyMC4yNTUuNTIiLCJuYW1lIjoi6ZmIIOW4jOeroCIsIm5vbmNlIjoiNzM2MkNBRUEtOUNBNS00QjQzLTlCQTMtMzREN0MzMDNFQkE3Iiwib2lkIjoiMmM4ZGQxMTQtZDVjYS00Nzc0LWJmMmMtNGI1NWVmMjdkNTYwIiwic3ViIjoiMmh0QlREcEZYeHh6OTBZUHRjNzRWUkktQUoydFB6bEVwU0lSY2U3RVRUTSIsInRpZCI6IjU5NzIzZjZiLTJkMTQtNDlmZS04MjdhLThkMDRmOWZlN2E2OCIsInVuaXF1ZV9uYW1lIjoiYXJlc0BvZmZpY2UzNjVkZXZsYWJzLm9ubWljcm9zb2Z0LmNvbSIsInVwbiI6ImFyZXNAb2ZmaWNlMzY1ZGV2bGFicy5vbm1pY3Jvc29mdC5jb20iLCJ1dGkiOiJRYXJBaDNKdV9rMlp2Vko3X0o4QkFBIiwidmVyIjoiMS4wIn0.AH1PI9pUMuI9J0DNOp6LVHW3yibf-b8hD3v6dSs2Pn-eGU2fi3HOY4ZU_fGSltTiVfDL-MRRispinNuhUTh3Aa9Gw936lbVs7N6zpN_SsCxIzdzq3quYxRtHoB84eXqzs7FDy53TDXtmtr89hI9wKtV2QI2pw7rBTlhuuQOxdl0638RB-eGMCtDWVj0SvK63FafazZBWdW8YSeJjf5x2XgZoNWwArGn-U5GcyTjMSywyOXJ6Ff5HssqjzuLQCtqXTL1Ouscx-M1DUyfYN-mlwHwRd3UQgUCkPgbaDebsXaz0lGXCOC61cwfkRWGjbtVLqn6DQNDlXwvggB3MTiT1TQ

解碼 id_token

你可能會說,這個id_token怎么完全看不懂呢?其實這是一個JSON的字符串,但是用Base64編碼過的,而且分為三個部分(頭部,聲明,簽名),用句點(.)分開的。

有一個最快的方法可以解碼 id_token,就是通過jwt.ms 這個網站來查看用戶信息

那么,如果要在我們的應用程序中進行解碼,應該怎么做呢?其實正常情況下,使用下面的方式就可以實現

var id_token= "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IkZTaW11RnJGTm9DMHNKWEdtdjEzbk5aY2VEYyIsImtpZCI6IkZTaW11RnJGTm9DMHNKWEdtdjEzbk5aY2VEYyJ9.eyJhdWQiOiI2MTE5OTNlMi1iZjM3LTQ4OTUtODQxZC05NzM3MDc2Y2RiNDUiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC81OTcyM2Y2Yi0yZDE0LTQ5ZmUtODI3YS04ZDA0ZjlmZTdhNjgvIiwiaWF0IjoxNTIxNjk0ODg5LCJuYmYiOjE1MjE2OTQ4ODksImV4cCI6MTUyMTY5ODc4OSwiYWlvIjoiWTJOZ1lMQzlKLzYzek9JNFQzekFGYyt6ejkvRnZVMElpWjNYb1pEaXREbjQ4ZmJyRElJQSIsImFtciI6WyJwd2QiXSwiZmFtaWx5X25hbWUiOiLpmYgiLCJnaXZlbl9uYW1lIjoi5biM56ugIiwiaXBhZGRyIjoiMTY3LjIyMC4yNTUuNTIiLCJuYW1lIjoi6ZmIIOW4jOeroCIsIm5vbmNlIjoiNzM2MkNBRUEtOUNBNS00QjQzLTlCQTMtMzREN0MzMDNFQkE3Iiwib2lkIjoiMmM4ZGQxMTQtZDVjYS00Nzc0LWJmMmMtNGI1NWVmMjdkNTYwIiwic3ViIjoiMmh0QlREcEZYeHh6OTBZUHRjNzRWUkktQUoydFB6bEVwU0lSY2U3RVRUTSIsInRpZCI6IjU5NzIzZjZiLTJkMTQtNDlmZS04MjdhLThkMDRmOWZlN2E2OCIsInVuaXF1ZV9uYW1lIjoiYXJlc0BvZmZpY2UzNjVkZXZsYWJzLm9ubWljcm9zb2Z0LmNvbSIsInVwbiI6ImFyZXNAb2ZmaWNlMzY1ZGV2bGFicy5vbm1pY3Jvc29mdC5jb20iLCJ1dGkiOiJRYXJBaDNKdV9rMlp2Vko3X0o4QkFBIiwidmVyIjoiMS4wIn0.AH1PI9pUMuI9J0DNOp6LVHW3yibf-b8hD3v6dSs2Pn-eGU2fi3HOY4ZU_fGSltTiVfDL-MRRispinNuhUTh3Aa9Gw936lbVs7N6zpN_SsCxIzdzq3quYxRtHoB84eXqzs7FDy53TDXtmtr89hI9wKtV2QI2pw7rBTlhuuQOxdl0638RB-eGMCtDWVj0SvK63FafazZBWdW8YSeJjf5x2XgZoNWwArGn-U5GcyTjMSywyOXJ6Ff5HssqjzuLQCtqXTL1Ouscx-M1DUyfYN-mlwHwRd3UQgUCkPgbaDebsXaz0lGXCOC61cwfkRWGjbtVLqn6DQNDlXwvggB3MTiT1TQ";


var token_parts = id_token.Split('.');

var header = Encoding.UTF8.GetString(Convert.FromBase64String(token_parts[0]));
var claims = Encoding.UTF8.GetString(Convert.FromBase64String(token_parts[1]));

Console.WriteLine(header);
Console.WriteLine(claims);

但是上述代碼,有時候會報錯,我發現可能是用戶信息中包含了中文的原因。但是可以通過一些第三方的庫來實現完美的解碼,例如Atom.Module.Base64Url這個package。下面是一個完整的例子:

using System;
using System.Text;
using Atom.Toolbox;

namespace ConsoleApp4
{
    class Program
    {
        static void Main(string[] args)
        {
            var id_token= "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IkZTaW11RnJGTm9DMHNKWEdtdjEzbk5aY2VEYyIsImtpZCI6IkZTaW11RnJGTm9DMHNKWEdtdjEzbk5aY2VEYyJ9.eyJhdWQiOiI2MTE5OTNlMi1iZjM3LTQ4OTUtODQxZC05NzM3MDc2Y2RiNDUiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC81OTcyM2Y2Yi0yZDE0LTQ5ZmUtODI3YS04ZDA0ZjlmZTdhNjgvIiwiaWF0IjoxNTIxNjk0ODg5LCJuYmYiOjE1MjE2OTQ4ODksImV4cCI6MTUyMTY5ODc4OSwiYWlvIjoiWTJOZ1lMQzlKLzYzek9JNFQzekFGYyt6ejkvRnZVMElpWjNYb1pEaXREbjQ4ZmJyRElJQSIsImFtciI6WyJwd2QiXSwiZmFtaWx5X25hbWUiOiLpmYgiLCJnaXZlbl9uYW1lIjoi5biM56ugIiwiaXBhZGRyIjoiMTY3LjIyMC4yNTUuNTIiLCJuYW1lIjoi6ZmIIOW4jOeroCIsIm5vbmNlIjoiNzM2MkNBRUEtOUNBNS00QjQzLTlCQTMtMzREN0MzMDNFQkE3Iiwib2lkIjoiMmM4ZGQxMTQtZDVjYS00Nzc0LWJmMmMtNGI1NWVmMjdkNTYwIiwic3ViIjoiMmh0QlREcEZYeHh6OTBZUHRjNzRWUkktQUoydFB6bEVwU0lSY2U3RVRUTSIsInRpZCI6IjU5NzIzZjZiLTJkMTQtNDlmZS04MjdhLThkMDRmOWZlN2E2OCIsInVuaXF1ZV9uYW1lIjoiYXJlc0BvZmZpY2UzNjVkZXZsYWJzLm9ubWljcm9zb2Z0LmNvbSIsInVwbiI6ImFyZXNAb2ZmaWNlMzY1ZGV2bGFicy5vbm1pY3Jvc29mdC5jb20iLCJ1dGkiOiJRYXJBaDNKdV9rMlp2Vko3X0o4QkFBIiwidmVyIjoiMS4wIn0.AH1PI9pUMuI9J0DNOp6LVHW3yibf-b8hD3v6dSs2Pn-eGU2fi3HOY4ZU_fGSltTiVfDL-MRRispinNuhUTh3Aa9Gw936lbVs7N6zpN_SsCxIzdzq3quYxRtHoB84eXqzs7FDy53TDXtmtr89hI9wKtV2QI2pw7rBTlhuuQOxdl0638RB-eGMCtDWVj0SvK63FafazZBWdW8YSeJjf5x2XgZoNWwArGn-U5GcyTjMSywyOXJ6Ff5HssqjzuLQCtqXTL1Ouscx-M1DUyfYN-mlwHwRd3UQgUCkPgbaDebsXaz0lGXCOC61cwfkRWGjbtVLqn6DQNDlXwvggB3MTiT1TQ";


            var token_parts = id_token.Split('.');

            var header = Encoding.UTF8.GetString(Base64Url.Decode(token_parts[0]));
            var claims = Encoding.UTF8.GetString(Base64Url.Decode(token_parts[1]));

            Console.WriteLine(header);
            Console.WriteLine(claims);



            Console.Read();

            
        }
    }
}



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM