Outlook 加载项无法针对 ADFS 服务器进行身份验证
Outlook Add-In Fails to Authenticate Against ADFS Server
环境:
- 展望 2016
- Windows 服务器 2016
- 微软 Visual Studio 社区 2017
问题描述:
我正在开发一个 Outlook 加载项,它应该针对 ADFS 服务器进行身份验证。
仔细按照此处概述的步骤操作后:
https://tech.greenhouse.io/2016/08/01/create-adfs-instance-on-azure-virtual-machine.html
我能够通过 ADFS 在 Internet Explorer 和 Chrome 外部作为 ADFS 用户成功登录。
然而,当尝试使用相同的方法通过 Outlook 加载项登录时,我得到的页面显示以下内容:
登录
发生错误
发生错误。有关详细信息,请联系您的管理员。
错误详情
© 2016 微软
这是示例日志文件。
Outlook 加载项:
加载项已成功启动。
Outlook 功能区中的用户交互发生。
SAML SP 登录:https://validsslcertdomain.com/saml2/login/?idp=http://adfsserverinazurecloud.com/adfs/services/trust
SAML IDP Url: https://adfsserverinazurecloud.com/adfs/ls/?SAMLRequest=jZJNTxsxEIbv/RWWLzntejcSKrWyiwJR1AhKo2RBKrfBOymWvPbWYxPCr8ebpBQuUa8z7/vM5+TipTPsGT1pZ6tRmRcjhla5Vtvf1eiumWfno4v6y4SgM72cxvBkV/gnIgWWjJbkkKh49FY6IE3SQockg5Lr6Y8bOc4LCUToQ8LzD5b+tKf3LjjlDGfTv+4rZyl26Nfon7XCu9VNxZ9C6EkKETFrqSizAJAHHcButMFcuU4MtcYCFAnOZqlrbWGA/bO+y6HdUI5AIVKujIst9H0Or9EfQENamAGzmFVct9lr2M7nv+J18RDV9a5vtilDFHFhKRFDxcdF+TUri6w8b8pSFmfy7NsDZ8vjZJfa7nd8cg2PBxHJ702zzJY/1w1n98db8STg9f4wcl/Ys7nzHYTTyCGSut/spRJtmn/H6/9dZIcBWgggJuJD4fr4HreJvZgtndFqx6bGuO2VRwhY8Q0YQv7eIGeiPhA+ /1T9Bg==&中继状态=/
SAML WIA Url: https://adfsserverinazurecloud.com/adfs/ls/wia?SAMLRequest=jZJNTxsxEIbv/RWWLzntejcSKrWyiwJR1AhKo2RBKrfBOymWvPbWYxPCr8ebpBQuUa8z7/vM5+TipTPsGT1pZ6tRmRcjhla5Vtvf1eiumWfno4v6y4SgM72cxvBkV/gnIgWWjJbkkKh49FY6IE3SQockg5Lr6Y8bOc4LCUToQ8LzD5b+tKf3LjjlDGfTv+4rZyl26Nfon7XCu9VNxZ9C6EkKETFrqSizAJAHHcButMFcuU4MtcYCFAnOZqlrbWGA/bO+y6HdUI5AIVKujIst9H0Or9EfQENamAGzmFVct9lr2M7nv+J18RDV9a5vtilDFHFhKRFDxcdF+TUri6w8b8pSFmfy7NsDZ8vjZJfa7nd8cg2PBxHJ702zzJY/1w1n98db8STg9f4wcl/Ys7nzHYTTyCGSut/spRJtmn/H6/9dZIcBWgggJuJD4fr4HreJvZgtndFqx6bGuO2VRwhY8Q0YQv7eIGeiPhA +/1T9Bg==&RelayState=/&client-request-id=a1209b03-ffed-419c-4904-0080000000f4
ADFS 服务器:
错误编号:364
Encountered error during federation passive request.
Additional Data
Protocol Name:
Relying Party:
Exception details:
System.FormatException: Invalid length for a Base-64 char array or string.
at System.Convert.FromBase64_Decode(Char* startInputPtr, Int32 inputLength, Byte* startDestPtr, Int32 destLength)
at System.Convert.FromBase64CharPtr(Char* inputPtr, Int32 inputLength)
at System.Convert.FromBase64String(String s)
at Microsoft.IdentityServer.Protocols.Saml.HttpSamlBindingSerializer.DecodeMessageInternal(String message)
at Microsoft.IdentityServer.Protocols.Saml.HttpSamlBindingSerializer.ReadProtocolMessage(String encodedSamlMessage)
at Microsoft.IdentityServer.Protocols.Saml.HttpSamlBindingSerializer.CreateFromNameValueCollection(Uri baseUrl, NameValueCollection collection)
at Microsoft.IdentityServer.Protocols.Saml.HttpRedirectSamlBindingSerializer.ReadMessage(Uri requestUrl, NameValueCollection form)
at Microsoft.IdentityServer.Web.Protocols.Saml.HttpSamlMessageFactory.CreateMessage(WrappedHttpListenerRequest httpRequest)
at Microsoft.IdentityServer.Web.Protocols.Saml.SamlContextFactory.CreateProtocolContextFromRequest(WrappedHttpListenerRequest request, ProtocolContext& protocolContext)
at Microsoft.IdentityServer.Web.Protocols.Saml.SamlProtocolHandler.CreateProtocolContext(WrappedHttpListenerRequest request)
at Microsoft.IdentityServer.Web.PassiveProtocolListener.GetProtocolHandler(WrappedHttpListenerRequest request, ProtocolContext& protocolContext, PassiveProtocolHandler& protocolHandler)
at Microsoft.IdentityServer.Web.PassiveProtocolListener.OnGetContext(WrappedHttpListenerContext context)
这是加载项的示例代码:
// String definitions
string samlAcs = Properties.Settings.Default.samlAcs;
string samlIdp = Properties.Settings.Default.samlIdp;
string serverUrl = Properties.Settings.Default.serverUrl;
string loginUrl = serverUrl + "/saml2/login/?idp=" + samlIdp;
var acsUrl = serverUrl + samlAcs;
string wiaHtmlBody = "";
HttpResponseMessage response;
try
{
response = await client.GetAsync(loginUrl);
...
try
{
response = await client.GetAsync(response.Headers.Location);
...
var wiaUrl = response.Headers.Location.ToString();
if (wiaUrl[0] == '/') wiaUrl = serverUrl + wiaUrl;
try
{
response = await client.GetAsync(wiaUrl);
response.EnsureSuccessStatusCode();
wiaHtmlBody = await response.Content.ReadAsStringAsync();
...
var wiaDoc = new XmlDocument();
try
{
wiaDoc.Load(new StringReader(wiaHtmlBody));
var samlNode = wiaDoc.DocumentElement.SelectSingleNode("//input[@name='SAMLResponse']");
string samlResponse = samlNode.Attributes["value"].Value;
...
它在期望来自服务器的 XML 文档时抛出异常:
异常:System.NullReferenceException:对象引用未设置为对象的实例。
类似问题:
https://serverfault.com/questions/753149/ad-fs-3-0-event-id-364-while-creating-mfa-and-sso
问题:
我必须采取什么步骤来解决这个问题?
提前致谢。
似乎 wiaUrl
未被 URL 编码,因为您在从 response.Headers.Location
检索它时将其转换为字符串。这可以解释为什么 base-64 解码器失败,因为 ADFS 首先尝试 URL-解码 SAML 请求消息。
换句话说,您必须将 URL 编码字符串传递给 client.GetAsync(wiaUrl)
或 URI
对象。
环境:
- 展望 2016
- Windows 服务器 2016
- 微软 Visual Studio 社区 2017
问题描述:
我正在开发一个 Outlook 加载项,它应该针对 ADFS 服务器进行身份验证。
仔细按照此处概述的步骤操作后: https://tech.greenhouse.io/2016/08/01/create-adfs-instance-on-azure-virtual-machine.html
我能够通过 ADFS 在 Internet Explorer 和 Chrome 外部作为 ADFS 用户成功登录。
然而,当尝试使用相同的方法通过 Outlook 加载项登录时,我得到的页面显示以下内容:
登录 发生错误 发生错误。有关详细信息,请联系您的管理员。 错误详情 © 2016 微软
这是示例日志文件。
Outlook 加载项:
加载项已成功启动。 Outlook 功能区中的用户交互发生。 SAML SP 登录:https://validsslcertdomain.com/saml2/login/?idp=http://adfsserverinazurecloud.com/adfs/services/trust SAML IDP Url: https://adfsserverinazurecloud.com/adfs/ls/?SAMLRequest=jZJNTxsxEIbv/RWWLzntejcSKrWyiwJR1AhKo2RBKrfBOymWvPbWYxPCr8ebpBQuUa8z7/vM5+TipTPsGT1pZ6tRmRcjhla5Vtvf1eiumWfno4v6y4SgM72cxvBkV/gnIgWWjJbkkKh49FY6IE3SQockg5Lr6Y8bOc4LCUToQ8LzD5b+tKf3LjjlDGfTv+4rZyl26Nfon7XCu9VNxZ9C6EkKETFrqSizAJAHHcButMFcuU4MtcYCFAnOZqlrbWGA/bO+y6HdUI5AIVKujIst9H0Or9EfQENamAGzmFVct9lr2M7nv+J18RDV9a5vtilDFHFhKRFDxcdF+TUri6w8b8pSFmfy7NsDZ8vjZJfa7nd8cg2PBxHJ702zzJY/1w1n98db8STg9f4wcl/Ys7nzHYTTyCGSut/spRJtmn/H6/9dZIcBWgggJuJD4fr4HreJvZgtndFqx6bGuO2VRwhY8Q0YQv7eIGeiPhA+ /1T9Bg==&中继状态=/ SAML WIA Url: https://adfsserverinazurecloud.com/adfs/ls/wia?SAMLRequest=jZJNTxsxEIbv/RWWLzntejcSKrWyiwJR1AhKo2RBKrfBOymWvPbWYxPCr8ebpBQuUa8z7/vM5+TipTPsGT1pZ6tRmRcjhla5Vtvf1eiumWfno4v6y4SgM72cxvBkV/gnIgWWjJbkkKh49FY6IE3SQockg5Lr6Y8bOc4LCUToQ8LzD5b+tKf3LjjlDGfTv+4rZyl26Nfon7XCu9VNxZ9C6EkKETFrqSizAJAHHcButMFcuU4MtcYCFAnOZqlrbWGA/bO+y6HdUI5AIVKujIst9H0Or9EfQENamAGzmFVct9lr2M7nv+J18RDV9a5vtilDFHFhKRFDxcdF+TUri6w8b8pSFmfy7NsDZ8vjZJfa7nd8cg2PBxHJ702zzJY/1w1n98db8STg9f4wcl/Ys7nzHYTTyCGSut/spRJtmn/H6/9dZIcBWgggJuJD4fr4HreJvZgtndFqx6bGuO2VRwhY8Q0YQv7eIGeiPhA +/1T9Bg==&RelayState=/&client-request-id=a1209b03-ffed-419c-4904-0080000000f4
ADFS 服务器:
错误编号:364
Encountered error during federation passive request.
Additional Data
Protocol Name:
Relying Party:
Exception details:
System.FormatException: Invalid length for a Base-64 char array or string.
at System.Convert.FromBase64_Decode(Char* startInputPtr, Int32 inputLength, Byte* startDestPtr, Int32 destLength)
at System.Convert.FromBase64CharPtr(Char* inputPtr, Int32 inputLength)
at System.Convert.FromBase64String(String s)
at Microsoft.IdentityServer.Protocols.Saml.HttpSamlBindingSerializer.DecodeMessageInternal(String message)
at Microsoft.IdentityServer.Protocols.Saml.HttpSamlBindingSerializer.ReadProtocolMessage(String encodedSamlMessage)
at Microsoft.IdentityServer.Protocols.Saml.HttpSamlBindingSerializer.CreateFromNameValueCollection(Uri baseUrl, NameValueCollection collection)
at Microsoft.IdentityServer.Protocols.Saml.HttpRedirectSamlBindingSerializer.ReadMessage(Uri requestUrl, NameValueCollection form)
at Microsoft.IdentityServer.Web.Protocols.Saml.HttpSamlMessageFactory.CreateMessage(WrappedHttpListenerRequest httpRequest)
at Microsoft.IdentityServer.Web.Protocols.Saml.SamlContextFactory.CreateProtocolContextFromRequest(WrappedHttpListenerRequest request, ProtocolContext& protocolContext)
at Microsoft.IdentityServer.Web.Protocols.Saml.SamlProtocolHandler.CreateProtocolContext(WrappedHttpListenerRequest request)
at Microsoft.IdentityServer.Web.PassiveProtocolListener.GetProtocolHandler(WrappedHttpListenerRequest request, ProtocolContext& protocolContext, PassiveProtocolHandler& protocolHandler)
at Microsoft.IdentityServer.Web.PassiveProtocolListener.OnGetContext(WrappedHttpListenerContext context)
这是加载项的示例代码:
// String definitions
string samlAcs = Properties.Settings.Default.samlAcs;
string samlIdp = Properties.Settings.Default.samlIdp;
string serverUrl = Properties.Settings.Default.serverUrl;
string loginUrl = serverUrl + "/saml2/login/?idp=" + samlIdp;
var acsUrl = serverUrl + samlAcs;
string wiaHtmlBody = "";
HttpResponseMessage response;
try
{
response = await client.GetAsync(loginUrl);
...
try
{
response = await client.GetAsync(response.Headers.Location);
...
var wiaUrl = response.Headers.Location.ToString();
if (wiaUrl[0] == '/') wiaUrl = serverUrl + wiaUrl;
try
{
response = await client.GetAsync(wiaUrl);
response.EnsureSuccessStatusCode();
wiaHtmlBody = await response.Content.ReadAsStringAsync();
...
var wiaDoc = new XmlDocument();
try
{
wiaDoc.Load(new StringReader(wiaHtmlBody));
var samlNode = wiaDoc.DocumentElement.SelectSingleNode("//input[@name='SAMLResponse']");
string samlResponse = samlNode.Attributes["value"].Value;
...
它在期望来自服务器的 XML 文档时抛出异常:
异常:System.NullReferenceException:对象引用未设置为对象的实例。
类似问题: https://serverfault.com/questions/753149/ad-fs-3-0-event-id-364-while-creating-mfa-and-sso
问题: 我必须采取什么步骤来解决这个问题?
提前致谢。
似乎 wiaUrl
未被 URL 编码,因为您在从 response.Headers.Location
检索它时将其转换为字符串。这可以解释为什么 base-64 解码器失败,因为 ADFS 首先尝试 URL-解码 SAML 请求消息。
换句话说,您必须将 URL 编码字符串传递给 client.GetAsync(wiaUrl)
或 URI
对象。