3

I am looking for any working examples of remote CSOM or SOAP OData calls against Office 365 with multi-factor authentication enabled.

The available documentation is unclear on this scenario. I think I may need to disable MFA for any accounts that will be used to interact with SharePoint, or create an Application Password. The latter is cited as not working with powershell so I do not have high hopes it will work with bespoke remote web service calls. The former may be a tough sell to the customer.

http://blogs.office.com/2014/02/10/multi-factor-authentication-for-office-365/

1 Answer 1

5

I was able to find a solution for this by decompiling the CSOM and watching the exchange via Fiddler.

*If someone with 300+ reputation can add a "vNext" tag that would be appreciated. It's really hard to find vNext-specific documentation as-is.

Yes, you do have to disable MFA. There is no programmatic way around this for now. Microsoft is planning to (or may have already) release support for MFA in powershell but it will still require a human to be present even if you're using something like Symantec VIP from a registered device.

Microsoft would tell you to register an Application with Azure AD and use a Client ID/Key. That's best practice. In my case the overhead of managing application registrations and retrofitting existing solutions was unacceptable... but that's the way you're supposed to do it.

At a high level, this is what you need to do:

Hit the root of the farm containing the site collection you want to authenticate to. Include a header of X-IDRCL_ACCEPTED and set it to t. We're expecting a 401 with a header called X-IDCRL_AUTH_PARAMS_V1. Parse and store the following values from that header (there's code for this in the CSOM). I put them in a POCO: IDCRL TYPE, ENDPOINT, ROOTDOMAIN, POLICY

POST to Microsoft's user realm service url. In the CSOM this is hard baked as https://login.microsoftonline.com/GetUserRealm.srf. The type should be application/s-www-form-encoded. The body should be login=YourUser&xml=1

Check to make sure you got a Success attribute on the root of the response. If not, do not pass go. Something is wrong and you're not going to be able to get any further.

Pull out the NameSpacetype. It should be Federated or Managed. In my case it's Federated. I store that as an IsFederated bool.

Next you pull out the STSAuthURL element. That's our next target.

Now we need to go get our SAMLToken. We do this by posting to the STSAuthURL using the body I'v included at the end of this post. Note I set the last value to urn:federation:MicrosoftOnline based on what the CSOM does.

Drill down to the following element to get your saml token: Body -> RequestSecurityTokenResponse -> RequestedSecurityToken -> Assertion

Now we need to get the "service token". We do this by posting to the ROOTDOMAIN header we stored earlier. The template for the body of this request is included under the template for the SAML request. The MustUnderstand value is set to https://login.microsoftonline.com/rst2.srf, which is hard-baked into the CSOM. The MessageId is where we put the SAML token. Service policy should look something like <wsp:PolicyReference URI="POLICY"></wsp:PolicyReference>. Grab your token by drilling to: Body -> RequestSecurityTokenResponse -> RequestedSecurityToken -> BinarySecurityToken

Now that we have a token we can post back to our farm again to acquire rtFa and FedAuth cookies. We'll post to the root and add the suffix _forms/default.aspx?wa=wsignin1.0. Capture the cookies returned.

Now you can include those cookies for any subsequent calls to SharePoint and you should be authenticated. Note you may also need to get a digest value if you're executing anything but a read operation. That is well covered ground elsewhere, there's nothing special about the process for O365 vNext.

So, the answer is do all of the above, or... just use the CSOM with SharePointOnlineCredentials. I highly recommend the authentication tools provided in the Patterns and Practices library as well.

STS post template:

<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:wssc="http://schemas.xmlsoap.org/ws/2005/02/sc" xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust">
    <s:Header>
        <wsa:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</wsa:Action>
        <wsa:To s:mustUnderstand="1">{0}</wsa:To>
        <wsa:MessageID>{1}</wsa:MessageID>
        <ps:AuthInfo xmlns:ps="http://schemas.microsoft.com/Passport/SoapServices/PPCRL" Id="PPAuthInfo">
            <ps:HostingApp>Managed IDCRL</ps:HostingApp>
            <ps:BinaryVersion>6</ps:BinaryVersion>
            <ps:UIVersion>1</ps:UIVersion>
            <ps:Cookies/>
            <ps:RequestParams>AQAAAAIAAABsYwQAAAAxMDMz</ps:RequestParams>
        </ps:AuthInfo>
        <wsse:Security>
            <wsse:UsernameToken wsu:Id="user">
                <wsse:Username>{2}</wsse:Username>
                <wsse:Password>{3}</wsse:Password>
            </wsse:UsernameToken>
            <wsu:Timestamp Id="Timestamp">
                <wsu:Created>{4}</wsu:Created>
                <wsu:Expires>{5}</wsu:Expires>
            </wsu:Timestamp>
        </wsse:Security>
    </s:Header>
    <s:Body>
        <wst:RequestSecurityToken Id="RST0">
            <wst:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</wst:RequestType>
            <wsp:AppliesTo>
                <wsa:EndpointReference>
                    <wsa:Address>{6}</wsa:Address>
                </wsa:EndpointReference>
            </wsp:AppliesTo>
            <wst:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</wst:KeyType>
        </wst:RequestSecurityToken>
    </s:Body>
</s:Envelope>

Service token request template:

<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://www.w3.org/2003/05/soap-envelope" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust">
  <S:Header>
    <wsa:Action S:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue</wsa:Action>
    <wsa:To S:mustUnderstand="1">{0}</wsa:To>
    <!-- service token url -->
    <ps:AuthInfo xmlns:ps="http://schemas.microsoft.com/LiveID/SoapServices/v1" Id="PPAuthInfo">
      <ps:BinaryVersion>5</ps:BinaryVersion>
      <ps:HostingApp>Managed IDCRL</ps:HostingApp>
    </ps:AuthInfo>
    <wsse:Security>{1}</wsse:Security>
    <!-- saml:assertion goes here -->
  </S:Header>
  <S:Body>
    <wst:RequestSecurityToken xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust" Id="RST0">
      <wst:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</wst:RequestType>
      <wsp:AppliesTo>
        <wsa:EndpointReference>
          <wsa:Address>{2}</wsa:Address>
          <!-- service target goes here -->
        </wsa:EndpointReference>
      </wsp:AppliesTo>
      {3}    <!-- policy reference goes here -->
    </wst:RequestSecurityToken>
  </S:Body>

</S:Envelope>
3
  • Where i can find documentation for connect to Office 365 having MFA using C#(CSOM) Oct 25, 2016 at 7:34
  • Is there any links or if you can put some code block it will be helpful. Oct 25, 2016 at 7:35
  • @DOM: It is not possible to connect programmatically with an MFA-enabled user. This can be disabled on a user-by-user basis. Once MFA-disabled, you can use SharepointOnlineCredentials() to connect without issue. Your other option is to register your application with Azure and leverage the Add-In model.
    – Pete M
    Nov 2, 2016 at 19:37

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.