我正在尝试连接到一个sharepoint网站,该网站首先重定向到Microsoft登录页面/ office 365登录页面,然后一旦我输入我的公司电子邮件ID,然后将其重定向到我的公司ADFS登录页面,其中已存在电子邮件ID文本框和密码是必需的。我在这里尝试的是避免登录页面,即(第一个microsoft / 0ffice365登录页面,然后到我公司的sso登录页面)并直接打开sharepoint在线网站,没有任何重定向/提示登录信用。我正在尝试使用asp.net实现这一目标。
ADFS SSO: - https://sso.mycompany.com/adfs/services/trust/13/usernamemixed
RP信任网址: - https://login.microsoftonline.com/extSTS.srf
SharePoint在线网址: - https://mycompanyo365.sharepoint.com/sites/procC/SitePages/Index.aspx
在这里,我可以使用.net连接到我公司的ADFS,并从ADFS获取SAML令牌。但是当我将令牌传递给sharepoint网站时,我的响应状态为OK,但我没有收到FedAuth cookie。
步骤: -
页面加载具有用户信用并重定向到sharepoint站点。
protected void Page_Load(object sender, EventArgs e)
{
UserName = UserNmae;
password = Password;
ConnectAdfsToGetSamlToken();
Response.Redirect("https://Mycompanyo365.sharepoint.com/sites/ProcC/SitePages/Index.aspx", false);
}
连接ADFS并获取SAML令牌
#region Connect Adfs To Get SamlToken to pass in fedauth cookies
public void ConnectAdfsToGetSamlToken()
{
// STS endpoint...
WSTrustChannelFactory factory = new WSTrustChannelFactory(new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential), new EndpointAddress("https://sso.mycompany.com/adfs/services/trust/13/usernamemixed"));
factory.TrustVersion = TrustVersion.WSTrust13;
// Username and Password here...
factory.Credentials.UserName.UserName = UserName;
factory.Credentials.UserName.Password = password;
//Request creation with relaying party...
RequestSecurityToken rst = new RequestSecurityToken
{
RequestType = Microsoft.IdentityModel.Protocols.WSTrust.WSTrust13Constants.RequestTypes.Issue,
AppliesTo = new EndpointAddress("https://login.microsoftonline.com/extSTS.srf"),
KeyType = Microsoft.IdentityModel.Protocols.WSTrust.WSTrust13Constants.KeyTypes.Bearer,
};
IWSTrustChannelContract channel = factory.CreateChannel();
//Saml token created...
GenericXmlSecurityToken genericToken = channel.Issue(rst) as GenericXmlSecurityToken;
//cookie created...
Cookie fedauthcookiesdata = TransformSamlTokenToFedAuth(genericToken.TokenXml.OuterXml, "https://mycompanyo365.sharepoint.com/sites/ProcC/SitePages/Index.aspx");
//Cookie assigned...
Response.Cookies["FedAuth"].Domain = "mycompany.com";
Response.Cookies["FedAuth"].Expires = fedauthcookiesdata.Expires;
Response.Cookies["FedAuth"].HttpOnly = fedauthcookiesdata.HttpOnly;
Response.Cookies["FedAuth"].Name = fedauthcookiesdata.Name;
Response.Cookies["FedAuth"].Path = fedauthcookiesdata.Path;
Response.Cookies["FedAuth"].Secure = fedauthcookiesdata.Secure;
Response.Cookies["FedAuth"].Value = fedauthcookiesdata.Value;
}
#endregion
转移SMAL以获取FedAuth Cookie
#region Transform Saml Token To get FedAuth cookies
internal Cookie TransformSamlTokenToFedAuth(string samlToken, string samlSite)
{
samlToken = WrapInSoapMessage(samlToken, samlSite);
string samlServer = samlSite.EndsWith("/") ? samlSite : samlSite + "/";
Uri samlServerRoot = new Uri(samlServer);
var sharepointSite = new
{
Wctx = "https://mycompanyo365.sharepoint.com/sites/ProcC/SitePages/Index.aspx",
Wtrealm = "urn:federation:MicrosoftOnline",
Wreply = String.Format("{0}://{1}/_trust/", samlServerRoot.Scheme, samlServerRoot.Host)
};
string stringData = String.Format("wa=wsignin1.0&wctx={0}&wresult={1}", HttpUtility.UrlEncode(sharepointSite.Wctx), HttpUtility.UrlEncode(samlToken));
Cookie fedAuthCookieValue;
HttpWebRequest sharepointRequest = HttpWebRequest.Create("https://mycompanyo365.sharepoint.com/_trust/default.aspx/") as HttpWebRequest;
sharepointRequest.Method = "POST";
sharepointRequest.ContentType = "application/x-www-form-urlencoded";
sharepointRequest.CookieContainer = new CookieContainer();
sharepointRequest.AllowAutoRedirect = false; // This is important
Stream newStream = sharepointRequest.GetRequestStream();
byte[] data = Encoding.UTF8.GetBytes(stringData);
newStream.Write(data, 0, data.Length);
newStream.Close();
HttpWebResponse webResponse = sharepointRequest.GetResponse() as HttpWebResponse;
string[] strCookies = webResponse.Headers.GetValues(1);
fedAuthCookieValue = webResponse.Cookies["FedAuth"];
return fedAuthCookieValue;
}
#endregion
包装肥皂消息
#region wrap in soap message
/// <summary>
/// Wrap SAML token in RequestSecurityTokenResponse soap message
/// </summary>
/// <param name="stsResponse">SAML token obtained via active authentication to ADFS</param>
/// <param name="relyingPartyIdentifier">Identifier of the ADFS relying party that we're hitting</param>
/// <returns>RequestSecurityTokenResponse soap message</returns>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "System.Xml.XmlDocument.CreateTextNode(System.String)")]
private string WrapInSoapMessage(string stsResponse, string relyingPartyIdentifier)
{
try
{
XmlDocument samlAssertion = new XmlDocument();
samlAssertion.PreserveWhitespace = true;
samlAssertion.LoadXml(stsResponse);
//Select the book node with the matching attribute value.
String notBefore = samlAssertion.DocumentElement.FirstChild.Attributes["NotBefore"].Value;
String notOnOrAfter = samlAssertion.DocumentElement.FirstChild.Attributes["NotOnOrAfter"].Value;
XmlDocument soapMessage = new XmlDocument();
XmlElement soapEnvelope = soapMessage.CreateElement("t", "RequestSecurityTokenResponse", "http://schemas.xmlsoap.org/ws/2005/02/trust");
soapMessage.AppendChild(soapEnvelope);
XmlElement lifeTime = soapMessage.CreateElement("t", "Lifetime", soapMessage.DocumentElement.NamespaceURI);
soapEnvelope.AppendChild(lifeTime);
XmlElement created = soapMessage.CreateElement("wsu", "Created", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
XmlText createdValue = soapMessage.CreateTextNode(notBefore);
created.AppendChild(createdValue);
lifeTime.AppendChild(created);
XmlElement expires = soapMessage.CreateElement("wsu", "Expires", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
XmlText expiresValue = soapMessage.CreateTextNode(notOnOrAfter);
expires.AppendChild(expiresValue);
lifeTime.AppendChild(expires);
XmlElement appliesTo = soapMessage.CreateElement("wsp", "AppliesTo", "http://schemas.xmlsoap.org/ws/2004/09/policy");
soapEnvelope.AppendChild(appliesTo);
XmlElement endPointReference = soapMessage.CreateElement("wsa", "EndpointReference", "http://www.w3.org/2005/08/addressing");
appliesTo.AppendChild(endPointReference);
XmlElement address = soapMessage.CreateElement("wsa", "Address", endPointReference.NamespaceURI);
XmlText addressValue = soapMessage.CreateTextNode(relyingPartyIdentifier);
address.AppendChild(addressValue);
endPointReference.AppendChild(address);
XmlElement requestedSecurityToken = soapMessage.CreateElement("t", "RequestedSecurityToken", soapMessage.DocumentElement.NamespaceURI);
XmlNode samlToken = soapMessage.ImportNode(samlAssertion.DocumentElement, true);
requestedSecurityToken.AppendChild(samlToken);
soapEnvelope.AppendChild(requestedSecurityToken);
XmlElement tokenType = soapMessage.CreateElement("t", "TokenType", soapMessage.DocumentElement.NamespaceURI);
XmlText tokenTypeValue = soapMessage.CreateTextNode("urn:oasis:names:tc:SAML:1.0:assertion");
tokenType.AppendChild(tokenTypeValue);
soapEnvelope.AppendChild(tokenType);
XmlElement requestType = soapMessage.CreateElement("t", "RequestType", soapMessage.DocumentElement.NamespaceURI);
XmlText requestTypeValue = soapMessage.CreateTextNode("http://schemas.xmlsoap.org/ws/2005/02/trust/Issue");
requestType.AppendChild(requestTypeValue);
soapEnvelope.AppendChild(requestType);
XmlElement keyType = soapMessage.CreateElement("t", "KeyType", soapMessage.DocumentElement.NamespaceURI);
XmlText keyTypeValue = soapMessage.CreateTextNode("http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey");
keyType.AppendChild(keyTypeValue);
soapEnvelope.AppendChild(keyType);
return soapMessage.OuterXml;
}
catch (Exception ex)
{
// ExceptionLogging.SendErrorToText(ex);
Response.Write("WrapInSoapMessage" + "Some Technical Error occurred,Please visit after some time" + ex.InnerException);
return "";
}
}
#endregion
答案 0 :(得分:0)
我自己尝试做类似的事情......我使用此代码使用集成身份验证从ADFS服务器生成令牌:
WS2007HttpBinding binding = new WS2007HttpBinding(SecurityMode.Transport);
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
WSTrustChannelFactory factory = new WSTrustChannelFactory((binding), new EndpointAddress(stsEndpoint));
factory.TrustVersion = TrustVersion.WSTrustFeb2005;
factory.Credentials.SupportInteractive = false;
var rst = new RequestSecurityToken
{
RequestType = RequestTypes.Issue,
AppliesTo = new EndpointReference(realm),
KeyType = KeyTypes.Bearer
};
IWSTrustChannelContract channel = factory.CreateChannel();
return channel.Issue(rst) as GenericXmlSecurityToken;
GenericXmlSecurityToken对象具有TokenXml属性,该属性可以通过XmlReader传递到Saml2SecurityTokenHandler.ReadToken以获取令牌。然后,我得到了一个参数化SOAP请求的方法,该请求被传递到Microsof的STS服务器上:
StringBuilder s = new StringBuilder();
s.Append("<s:Envelope xmlns:s=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:a=\"http://www.w3.org/2005/08/addressing\" xmlns:u=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">");
s.Append("<s:Header>");
s.Append("<a:Action s:mustUnderstand=\"1\">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</a:Action>");
s.Append("<a:ReplyTo>");
s.Append("<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>");
s.Append("</a:ReplyTo>");
s.Append("<a:To s:mustUnderstand=\"1\">[toUrl]</a:To>");
s.Append("<o:Security s:mustUnderstand=\"1\" xmlns:o=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\">[assertion]");
s.Append("</o:Security>");
s.Append("</s:Header>");
s.Append("<s:Body>");
s.Append("<t:RequestSecurityToken xmlns:t=\"http://schemas.xmlsoap.org/ws/2005/02/trust\">");
s.Append("<wsp:AppliesTo xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2004/09/policy\">");
s.Append("<a:EndpointReference>");
s.Append("<a:Address>[url]</a:Address>");
s.Append("</a:EndpointReference>");
s.Append("</wsp:AppliesTo>");
s.Append("<t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType>");
s.Append("<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>");
s.Append("<t:TokenType>urn:oasis:names:tc:SAML:1.0:assertion</t:TokenType>");
s.Append("</t:RequestSecurityToken>");
s.Append("</s:Body>");
s.Append("</s:Envelope>");
string samlRTString = s.ToString();
samlRTString = samlRTString.Replace("[assertion]", samlAssertion);
samlRTString = samlRTString.Replace("[url]", url);
samlRTString = samlRTString.Replace("[toUrl]", toUrl);
return samlRTString;
无论如何,这个计划......我还没有机会在我们的环境中测试我的想法,而且我在下个月离开办公室,但希望这个可能会帮助你:)