简介

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

解码 id_token的更多相关文章

  1. linux字符串url编码与解码

    编码的两种方式 echo '手机' | tr -d '\n' | xxd -plain | sed 's/\(..\)/%\1/g' echo '手机' |tr -d '\n' |od -An -tx ...

  2. URI编码解码和base64

    概述 对于uri的编解码,在js中有3对函数,分别是escape/unescape,encodeURI/decodeURI,encodeURIComponent/decodeURIComponent. ...

  3. FFmpeg学习2:解码数据结构及函数总结

    在上一篇文章中,对FFmpeg的视频解码过程做了一个总结.由于才接触FFmpeg,还是挺陌生的,这里就解码过程再做一个总结. 本文的总结分为以下两个部分: 数据读取,主要关注在解码过程中所用到的FFm ...

  4. Unicode转义(\uXXXX)的编码和解码

    在涉及Web前端开发时, 有时会遇到\uXXXX格式表示的字符, 其中XXXX是16进制数字的字符串表示形式, 在js中这个叫Unicode转义字符, 和\n \r同属于转义字符. 在其他语言中也有类 ...

  5. C# base 64图片编码解码

    使用WinForm实现了图片base64编码解码的 效果图: 示例base 64编码字符串: /9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKD ...

  6. java编码原理,java编码和解码问题

    java的编码方式原理 java的JVM的缺省编码方式由系统的“本地语言环境”设置确定,和操作系统的类型无关 . 在JAVA源文件-->JAVAC-->Class-->Java--& ...

  7. [LeetCode] Decode String 解码字符串

    Given an encoded string, return it's decoded string. The encoding rule is: k[encoded_string], where ...

  8. [LeetCode] Encode and Decode Strings 加码解码字符串

    Design an algorithm to encode a list of strings to a string. The encoded string is then sent over th ...

  9. [LeetCode] Decode Ways 解码方法

    A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' - ...

随机推荐

  1. 'An instance 0x155e74a0 of class UIWebView was deallocated while key value observers were still registered with it.

    在iOS和html混编的时候,当用iOS原生的navigation导航pop回去的时候,出现 *** Terminating app due to uncaught exception 'NSInte ...

  2. Python编程练习:简单的闹钟提醒

    问题详情:当前时间为下午2点,你在手机上设置了一个闹钟提醒,10000秒后触发该闹钟,请问闹钟铃声响起时的具体时间?请用print打印出时间 源码: a = 10000 h,m,s=2,0,0 if ...

  3. 40个Java多线程面试问题

    1. 多线程有什么用? 一个可能在很多人看来很扯淡的一个问题:我会用多线程就好了,还管它有什么用?在我看来,这个回答更扯淡.所谓"知其然知其所以然","会用"只 ...

  4. 在谷歌安装扩展程序Axure RP Extension for Chrome后,经常无故损坏,无法使用

    最近因为要看需求给的原型图,但需求只给了html格式的文件,没有给可以在Axure软件里看的格式, 所以在谷歌安装了一个Axure RP Extension for Chrome扩展程序在谷歌浏览器看 ...

  5. SpringMVC框架一:搭建测试

    这里做一个Demo:展示商品列表 新建Dynamic Web Project: 导入jar包,放在lib下: 放入Lib文件夹之后,会自动build path 接下来配置web.xml: <?x ...

  6. iview导航菜单updateOpened和updateActiveName的使用

    先看官方文档: iview导航菜单 这里主要遇到的问题有两个: 1. 点击回到首页(B按钮)时需要取消选中当前选中的菜单项(全部不选中),这里用到的是 updateActiveName方法 2. 点击 ...

  7. 原生JS实现弹幕效果

    纯属无聊写的,可能有很多问题,欢迎批评指教. 效果图:图一是预设的一些弹幕,图二是自己发射的弹幕,效果是一样的.   首先是弹幕的位置,是要从最右滑到最左,为了防止随机高度弹幕会覆盖的问题,设置了通道 ...

  8. Ubuntu下将python从2.7升级到3.5

    在ubuntu 的终端中用代码下载最新的Python sudo apt-get install python3 系统会提示输入Linux 的密码,输入密码后下载 刚才下载的Python程序被安装在us ...

  9. HPE服务器做raid5阵列

    HPE服务器做阵列的详细步骤: 注意:HPE服务器加硬盘需要安装配套的扩展笼~~~ 1.首先服务器开机,出现下图界面按F10. 2.然后在下图中选择HPE interlligent Provision ...

  10. mysql 开发进阶篇系列 42 逻辑备份与恢复(mysqldump 的完全恢复)

    一.概述 在作何数据库里,备份与恢复都是非常重要的.好的备份方法和备份策略将会使得数据库中的数据更加高效和安全.对于DBA来说,进行备份或恢复操作时要考虑的因素大概有如下: (1) 确定要备份的表的存 ...