asp.net程序通过Microsoft Azure令牌授予流获取UserInfo终结点实现单点登录--授权代码授予

发布时间 2023-04-17 16:14:11作者: 黑星2010

1. Microsoft Azure令牌授予流
令牌授予流种类如下:

本章节采用两种:授权代码授予;

2. 授权代码授予的实现
流程:重定向到authorize--->拿到code--->通过code换取access_token--->通过access_token获取UserInfo

2.1. 重定向到authorize
重定向地址:
https://login.microsoftonline.com/40cfad67-3660-44d8-9f4XXXXXXXXXXXX/oauth2/v2.0/authorize?client_id=6c506942-6837-42ab-XXXXXXXXXXX&redirect_uri=http://localhost:XXXXX/OidcCallback.aspx&response_type=code id_token&scope=openid profile&nonce=xyz&state=abc&grant_type=authorization_code

2.2. 拿到code
回调页面OidcCallback.aspx中,通过Request.QueryString["code"]能取到授权码code值;
注意:回调时,url类似:OidcCallback.aspx#code=XXXXXXXXXXXXX,其中#是锚点,跟?的意思不一样,必须处理成?后才可以通过QueryString来取值;

2.3. 通过code换取access_token
post接口:
https://login.microsoftonline.com/40cfad67-3660-44d8-9f49f4XXXXXXXXXXXX/oauth2/v2.0/token

参数:

client_id=6731de76-14a6-49ae-97bc-6eba691xxxxxxxxxx
&code=OAAABAAAAiL9Kn2Z27UubvWFPbm0gLWQJVzCTE9UkP3pSx1a ...
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&grant_type=authorization_code 
&client_secret=JqQX2PNo9bpM0uEihUPzyrh

成功的响应:

{
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1Q...",
    "token_type": "Bearer",
    "expires_in": 3599,
    "scope": "https%3A%2F%2Fgraph.microsoft.com%2Fmail.read",
    "refresh_token": "AwABAAAAvPM1KaPlrEqdFSBzjqfTGAMxZGUTdM0t4B4...",
    "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJhdWQiOiIyZDRkMTFhMi1mODE0LTQ2YTctOD...",
}

2.4. 通过access_token获取UserInfo
GET接口:
https://graph.microsoft.com/oidc/userinfo

参数:
请求header中增加Authorization,值为Bearer access_token
比如:
HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(new Uri(getUrl));
webReq.Headers.Add("Authorization", "Bearer " + token);

成功的响应:

{
    "sub": "OLu859SGc2Sr9ZsqbkG-QbeLgJlb41KcdiPoLYNpSFA",
    "name": "Mikah Ollenburg",  scope.
    "family_name": " Ollenburg",
    "given_name": "Mikah",
    "picture": "https://graph.microsoft.com/v1.0/me/photo/$value",
    "email": "mikoll@contoso.com"  
}

其中sub就是用户的唯一标志,name是用户的显示名称(可能重复...)

通过code换取access_token 时出现的异常::

异常1:
http 400的异常,很诡异
必须try catch (WebException wex) 才能捕捉到真实异常详细描述,如下代码:

点击查看代码
 `  using (HttpWebResponse response = (HttpWebResponse)wex.Response)
                {
                    using (Stream myResponseStream = response.GetResponseStream())
                    {
                        using (StreamReader myStreamReader = new StreamReader(myResponseStream, dataEncode))
                        {
                            responseContent = myStreamReader.ReadToEnd().ToString();
                        }
                    }
                }`

异常2:
AADSTS1002016:您正在使用已弃用的TLS版本1.0、1.1和/或3DES加密算法,以改进Azure AD的安全状况
在请求前增加如下代码:

点击查看代码
`if (postUrl.StartsWith("https", StringComparison.OrdinalIgnoreCase))
		 {
			 SetCertificatePolicy();
		 } 
 
private static void SetCertificatePolicy()
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
ServicePointManager.ServerCertificateValidationCallback
					 += RemoteCertificateValidate;
}
 
private static bool RemoteCertificateValidate(object sender, X509Certificate cert,
X509Chain chain, SslPolicyErrors error)
{
return true;

} `

异常3:
AADSTS65001: The user or administrator has not consented to use the application wi
办法:将请求参数中的Scope去掉即可;