Problem logging in to Office 365 Sharepoint Online from Webole hosted in the cloud
-
Wednesday, August 24, 2011 1:42 PM
Hi,
I have a problem logging in to the Office 365 Sharepoint Online from a WebRole hosted in the cloud.
I have a WebService that logs in a user to Sharepoint Online as described in this post:
http://www.wictorwilen.se/Post/How-to-do-active-authentication-to-Office-365-and-SharePoint-Online.aspxWhen starting my application with the cloud emulator in Visual Studio 2010, everything works fine.
When uploading the WebRole to my Azure Account, i get the following message:Meldung: Unhandled Error in Silverlight Application Invoke operation 'GetGroups' failed. The remote server returned an error: (403) Forbidden. at System.Net.HttpWebRequest.GetResponse() at Microsoft.SharePoint.Client.SPWebRequestExecutor.Execute() at Microsoft.SharePoint.Client.ClientContext.EnsureFormDigest() at Microsoft.SharePoint.Client.ClientContext.ExecuteQuery() at BTC.WFC.Dashboard.RiaServices.Web.UserInformationService.GetGroups(String username) in D:ProjekteSVN runkCORE_DevelopmentWFC-DashboardsrcDashboardServicesBTC.WFC.Dashboard.RiaServices.WebUserInformationService.cs:line 35 at GetGroups(DomainService , Object[] ) at System.ServiceModel.DomainServices.Server.ReflectionDomainServiceDescriptionProvider.ReflectionDomainOperationEntry.Invoke(DomainService domainService, Object[] parameters) at System.ServiceModel.DomainServices.Server.DomainService.Invoke(InvokeDescription invokeDescription, IEnumerable`1& validationErrors) at System.ServiceModel.DomainServices.Hosting.InvokeOperationBehavior.OperationInvoker.InvokeCore(Object instance, Object[] inputs, Object[]& outputs)
Is there any restriction or is there some configuration stuff that must be different when using the service in the cloud?
Kind regards,
Maik
All Replies
-
Thursday, August 25, 2011 5:47 PMModerator
Greetings Maik
The reason you are getting this error message is because the program is failing authentication with Office 365, as it uses claims based authentication a token also needs to be sent for authentication to work.
I have found the following resources to assist you with this process:
http://msdn.microsoft.com/en-us/library/hh147177.aspx
http://code.msdn.microsoft.com/Remote-Authentication-in-b7b6f43c
This question is better answered in the Office 365 Communities Form. If you have any further questions regarding this issue, please create a thread here:
http://community.office365.com/en-us/default.aspx
Thank you.
- Marked As Answer by Marcus Gilbertson - BPOSMicrosoft Contingent Staff, Moderator Thursday, August 25, 2011 5:48 PM
- Unmarked As Answer by Maik-btc Friday, August 26, 2011 5:50 AM
-
Friday, August 26, 2011 6:25 AM
Hi Marcus,
thanks for your replay. Unfortunatly that does not answer my question. I didn't write explicitly in my post, that i want an "silent" authentification without any authentication scrren shown. In the article i've posted there is a description how that works.
The sample of Wictor works fine when starting it in my cloud emulator in VS2010. I successfully auth against my Sharepoint Online.
Another problem that I have. I'm developing a Silverlight application. So I can't reference the SharePoint DLLs. The server side is stateless due to the hosting in cloud instances.
Any other suggestions?
Here is a code snippet, working in cloud emulator, failing in the cloud instance:
public class UserInformationService : DomainService { public List<string> GetGroupsForUser(string username) { List<string> result = new List<string>(); string url = "https://my.sharepoint.com/"; string adminUser = "admin@my.onmicrosoft.com"; string password = "XXX"; MsOnlineClaimsHelper claimsHelper = new MsOnlineClaimsHelper(url, adminUser, password); using (ClientContext context = new ClientContext(url)) { context.ExecutingWebRequest += claimsHelper.clientContext_ExecutingWebRequest; //Do some stuff in SP Object Model } return result; } } public class MsOnlineClaimsHelper { #region Properties readonly string _username; readonly string _password; readonly bool _useRtfa; readonly Uri _host; CookieContainer _cachedCookieContainer = null; DateTime _expires = DateTime.MinValue; #endregion #region Constructors public MsOnlineClaimsHelper(string host, string username, string password) : this(new Uri(host), username, password) { } public MsOnlineClaimsHelper(Uri host, string username, string password) { _host = host; _username = username; _password = password; _useRtfa = true; } public MsOnlineClaimsHelper(Uri host, string username, string password, bool useRtfa) { _host = host; _username = username; _password = password; _useRtfa = useRtfa; } #endregion #region Constants public const string office365STS = "https://login.microsoftonline.com/extSTS.srf"; public const string office365Login = "https://login.microsoftonline.com/login.srf"; public const string office365Metadata = "https://nexus.microsoftonline-p.com/federationmetadata/2007-06/federationmetadata.xml"; public const string wsse = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; public const string wsu = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"; private const string userAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)"; #endregion class MsoCookies { public string FedAuth { get; set; } public string rtFa { get; set; } public DateTime Expires { get; set; } public Uri Host { get; set; } } // Method used to add cookies to CSOM public void clientContext_ExecutingWebRequest(object sender, WebRequestEventArgs e) { e.WebRequestExecutor.WebRequest.CookieContainer = getCookieContainer(); //e.WebRequestExecutor.WebRequest.UserAgent = userAgent; } // Creates or loads cached cookie container CookieContainer getCookieContainer() { if (_cachedCookieContainer == null || DateTime.Now > _expires) { // Get the SAML tokens from SPO STS (via MSO STS) using fed auth passive approach MsoCookies cookies = getSamlToken(); if (cookies != null && !string.IsNullOrEmpty(cookies.FedAuth)) { // Create cookie collection with the SAML token _expires = cookies.Expires; CookieContainer cc = new CookieContainer(); // Set the FedAuth cookie Cookie samlAuth = new Cookie("FedAuth", cookies.FedAuth) { Expires = cookies.Expires, Path = "/", Secure = cookies.Host.Scheme == "https", HttpOnly = true, Domain = cookies.Host.Host }; cc.Add(samlAuth); if (_useRtfa) { // Set the rtFA (sign-out) cookie, added march 2011 Cookie rtFa = new Cookie("rtFA", cookies.rtFa) { Expires = cookies.Expires, Path = "/", Secure = cookies.Host.Scheme == "https", HttpOnly = true, Domain = cookies.Host.Host }; cc.Add(rtFa); } _cachedCookieContainer = cc; return cc; } return null; } return _cachedCookieContainer; } public CookieContainer CookieContainer { get { if (_cachedCookieContainer == null || DateTime.Now > _expires) { return getCookieContainer(); } return _cachedCookieContainer; } } private MsoCookies getSamlToken() { MsoCookies ret = new MsoCookies(); try { var sharepointSite = new { Wctx = office365Login, Wreply = _host.GetLeftPart(UriPartial.Authority) + "/_forms/default.aspx?wa=wsignin1.0" }; //get token from STS string stsResponse = getResponse(office365STS, sharepointSite.Wreply); // parse the token response XDocument doc = XDocument.Parse(stsResponse); // get the security token var crypt = from result in doc.Descendants() where result.Name == XName.Get("BinarySecurityToken", wsse) select result; // get the token expiration var expires = from result in doc.Descendants() where result.Name == XName.Get("Expires", wsu) select result; ret.Expires = Convert.ToDateTime(expires.First().Value); HttpWebRequest request = createRequest(sharepointSite.Wreply); byte[] data = Encoding.UTF8.GetBytes(crypt.FirstOrDefault().Value); using (Stream stream = request.GetRequestStream()) { stream.Write(data, 0, data.Length); stream.Close(); using (HttpWebResponse webResponse = request.GetResponse() as HttpWebResponse) { // Handle redirect, added may 2011 for P-subscriptions if (webResponse.StatusCode == HttpStatusCode.MovedPermanently) { HttpWebRequest request2 = createRequest(webResponse.Headers["Location"]); using (Stream stream2 = request2.GetRequestStream()) { stream2.Write(data, 0, data.Length); stream2.Close(); using (HttpWebResponse webResponse2 = request2.GetResponse() as HttpWebResponse) { ret.FedAuth = webResponse2.Cookies["FedAuth"].Value; ret.rtFa = webResponse2.Cookies["rtFa"].Value; ret.Host = request2.RequestUri; } } } else { ret.FedAuth = webResponse.Cookies["FedAuth"].Value; ret.rtFa = webResponse.Cookies["rtFa"].Value; ret.Host = request.RequestUri; } } } } catch (Exception ex) { return null; } return ret; } static HttpWebRequest createRequest(string url) { HttpWebRequest request = HttpWebRequest.Create(url) as HttpWebRequest; request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; request.CookieContainer = new CookieContainer(); request.AllowAutoRedirect = false; // Do NOT automatically redirect request.UserAgent = userAgent; return request; } private string getResponse(string stsUrl, string realm) { RequestSecurityToken rst = new RequestSecurityToken { RequestType = WSTrustFeb2005Constants.RequestTypes.Issue, AppliesTo = new EndpointAddress(realm), KeyType = WSTrustFeb2005Constants.KeyTypes.Bearer, TokenType = Microsoft.IdentityModel.Tokens.SecurityTokenTypes.Saml11TokenProfile11 }; WSTrustFeb2005RequestSerializer trustSerializer = new WSTrustFeb2005RequestSerializer(); WSHttpBinding binding = new WSHttpBinding(); binding.Security.Mode = SecurityMode.TransportWithMessageCredential; binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName; binding.Security.Message.EstablishSecurityContext = false; binding.Security.Message.NegotiateServiceCredential = false; binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None; EndpointAddress address = new EndpointAddress(stsUrl); using (WSTrustFeb2005ContractClient trustClient = new WSTrustFeb2005ContractClient(binding, address)) { trustClient.ClientCredentials.UserName.UserName = _username; trustClient.ClientCredentials.UserName.Password = _password; Message response = trustClient.EndIssue( trustClient.BeginIssue( Message.CreateMessage( MessageVersion.Default, WSTrustFeb2005Constants.Actions.Issue, new RequestBodyWriter(trustSerializer, rst) ), null, null)); trustClient.Close(); using (XmlDictionaryReader reader = response.GetReaderAtBodyContents()) { return reader.ReadOuterXml(); } } } }
Happy investigating.Thanks,
Maik -
Saturday, January 28, 2012 12:10 AM
Thanks so much Maik,
The code you posted works great!
Update:
Well, it works great on Dev machine in Visual Studio environment, but gives Forbidden (Error 403) when deployed on IIS on a Windows server 2008 :(
Update2:
The server was missing Windows Identity Foundation (http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=17331) Once I installed that and rebooted the machine, it works like a charm!
-
Saturday, April 14, 2012 6:15 PM
Hey Maik, I also am trying to do the same thing in SilverLight. Did you ever figure out a way to solve this issue?
thank you
Al
-
Thursday, May 31, 2012 7:38 AM
hi Maik,
I was also trying the same thing to be deployed as WCF service to azure , i am also getting same error, did you figured out what is causing the problem?
thanks
vimal
regards Vimal

