asp.net程序通过Microsoft Azure令牌授予流获取UserInfo终结点实现单点登录--授权代码授予(OIDC协议)
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) 才能捕捉到真实异常详细描述,如下代码:
点击查看WebException 代码
` 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的安全状况
在请求前增加如下代码(在 HttpWebRequest webReq = (HttpWebRequest)WebRequest.Create(new Uri(postUrl));之前):
点击查看代码
`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去掉即可;