【问题标题】:Sharepoint Office 365 OAuth Service authentication to list.asmxSharepoint Office 365 OAuth 服务对 list.asmx 的身份验证
【发布时间】:2016-05-31 20:30:48
【问题描述】:

我正在尝试从外部网站访问 Office 365 中的 Sharepoint 列表数据。我在 Azure Active Directory 中注册了我的应用程序,并完成了创建和信任证书以及获取访问令牌的所有过程。

Add-Type -Path ".\Microsoft.IdentityModel.Clients.ActiveDirectory.dll"

$authenticationContext = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext -ArgumentList "https://login.microsoftonline.com/{myTenantId}/", $false

$cer = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$cer.Import(".\WithPrivateKey.pfx", "privateKey", [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::MachineKeySet)

$clientAssertion = New-Object Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate -ArgumentList "{myClientId}", $cer

$authenticationResult = $authenticationContext.AcquireToken("https://{tenantName}.sharepoint.com", $clientAssertion)

$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization", "Bearer " + $authenticationResult.AccessToken)

通过在请求标头中显示访问令牌,我可以成功调用 Sharepoint REST Api。

$response = Invoke-RestMethod -Uri https://{myTenantName}.sharepoint.com/sites/devSite/_vti_bin/ListData.svc/TestList -Method Get -Headers $headers 

但是我不能做同样的事情来访问 asmx 端点,例如 Lists.asmx,每当我尝试在这些服务上调用任何方法时,我都会得到 401 UNAUTHORIZED

$body = '<?xml version="1.0" encoding="utf-8"?>
<soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
  <soap12:Body>
    <GetList xmlns="http://schemas.microsoft.com/sharepoint/soap/">
      <listName>TestList</listName>
    </GetList>
  </soap12:Body>
</soap12:Envelope>'

$response = Invoke-WebRequest -Uri https://{myTenantName}.sharepoint.com/sites/site/_vti_bin/Lists.asmx -Method Post -ContentType 'application/soap+xml' -Headers $headers -Body $body

【问题讨论】:

    标签: web-services sharepoint oauth office365


    【解决方案1】:

    ADAL 从 Azure AD 获取的令牌仅用于 Office 365 REST API(上面的代码使用 OAuth2.0,它为 REST API 获取 JSON 湿令牌)。此令牌不适用于 SharePoint Web 服务。

    要使用 SharePoint Web 服务,我们需要通过以下方式对 SharePoint 进行身份验证 SharePoint 声明身份验证。有关 SharePoint 身份验证的更多详细信息,您可以参考以下链接:

    https://msdn.microsoft.com/en-us/library/hh147177.aspx#SPO_RA_OverviewSPAuthentication

    【讨论】:

    • 我明白,但是该链接使用重定向来获得用户同意,但是我们不能让用户参与,因为这是服务器到服务器的身份验证。
    • 如果是这样,您需要使用 Office 365 REST API 或 SharePoint REST 服务,而不是 SharePoint Web 服务。
    • Sharepoint Online 客户端 SDK 允许使用用户帐户和密码执行此操作,但无需用户同意。由于这是一个 php 应用程序,我们不能使用 sdk,但需要使用原始 http,请参阅下面的答案。
    【解决方案2】:

    在深入研究 .net Sharepoint 客户端 sdk 之后,我发现了 SharepointOnlineCredential 类是如何做到的,从而允许访问 Sharepoint SOAP 服务。

    因此,正如 Fei Xue 所说,Azure AD 令牌对于访问 Sharepoint SOAP 服务无效(尽管令牌对于允许访问 REST 服务是有效的......)。要访问 Sharepoint Online 服务,您需要使用某种声明身份验证,方法是请求用户同意或直接使用已知用户和密码。

    由于我们无法在我们的 php 应用程序中使用 .net SDK,因此我们研究了 SDK 如何在直接使用用户凭据时创建请求以进行身份​​验证:

    首先将您的身份验证凭据作为 SAML-WSSecurity POST 请求发送到身份验证端点https://login.microsoftonline.com/rst2.srf

    POST https://login.microsoftonline.com/rst2.srf 
    Content-Type: application/soap+xml; charset=utf-8
    Content-Length: [calculate]
    Host: login.microsoftonline.com
    
    <?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">https://login.microsoftonline.com/rst2.srf</wsa:To>
        <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>
                <wsse:UsernameToken wsu:Id="user">
                    <wsse:Username>[user]</wsse:Username>
                    <wsse:Password>[password]</wsse:Password>
                </wsse:UsernameToken>                
    </wsse:Security>
      </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>sharepoint.com</wsa:Address>
            </wsa:EndpointReference>
          </wsp:AppliesTo>
          <wsp:PolicyReference URI="MBI"></wsp:PolicyReference>
        </wst:RequestSecurityToken>
      </S:Body>
    </S:Envelope>
    

    xml 格式的响应将附带安全令牌:

    ....
    <wst:RequestedSecurityToken>
        <wsse:BinarySecurityToken Id="Compact0">t=EwA4A06hBwAUNfDkMme61kIdXqvj9tWnUbHtXWEAAREB5clgLb8J/VvxRFIKLUnd9SRyoBHmTHFk0viit2FMlGXak5NJKJhicT8MiZmgA2HoTrJM1EgXCNUpmWqrX1LQRNfs0PHEV4XncjI9lnphsSTiFSCDjmdCKtW4TmV8n18xJHvBtDUWdvCT2lBti8/gf1oiqD5lQBPtxr+d4OwNtJHADEKpC/YIoatcKqgxI480tlWOZHpEL1wifo5EDMDRRc985ObMCZ31fPdSpA7WIbDzlZYX9ou6Cq7EybrIHsAcr5cPIJ8y0FRUacma9+dMxqr/lILAIyAYz/GdTNffa2Q3zJOSWW5RcnigtCApHgf83HjW8DqC6NgTrXs6rpUDZgAACC/4JZlSLB3JCALIntkKmNtRl2JLvwUljkXrP5jg5ipK/J/fGF3oc46aP/YT3VnrrD6TCV5ZECki5ycYZ6JR5RDK6OSqI9c5FDfFS/YmSCcdcaJ1cG2Ug3Oz3w14mznYGwmvrgyGvw35aoyjnKZALw8OQ2Ddi97gbe03L4rrM7CxTGwEPgoKCK7USkwxZT+myLJASVhd29+eNsTqd7wuphhLrzbgYZ+7swlJb3oIJw/2T7YvJ4fTPByaLxGaBt7iry74aSh/RnXdH3snOQnsr63bXqqoDJGcj7A3aIpElw2LlW2/PGh84zke3corp2q/jg7PEKCnV8PYN2xiwSfqY9vNCny14xhHEPsK8FWDBOPDpgeC18qz+FpTN0rGUMXl20bxJGxGqnQ+s8k0Gu9yTxoZKWPSeVihJk6qUQo6KJb/NE/QRco94QDUjMYi+gccGN0D1ouUe+O0fb0InXeM+98qfXJLQAjoUtgS8rRJUAqFk5XVwebGbx0ICRv3Q/wiJ7T5yUryMBTtwbaGf/07QuGTv9CW2UTsV9zT1nMSRDfUpelZrgZt6huLnDRLC8yVHfXjndMwONdymxWcD9sLb8EcNmTUFHDfBrv8XFb50PNJAV4qvK8CgVmWu2C2GWXoZfYkaR6o6jpliQdT5NcNnb9wNy36OqDnIWl0ZNM1SOzVX0yQOLeaf8+1bslaafyYMAbhcAI=&amp;p=
       </wsse:BinarySecurityToken>
    </wst:RequestedSecurityToken>                
    ...
    

    然后使用从上一个响应中提取的安全令牌,您需要向您的租户凭据端点发送一个 GET 请求:https://yourtenantname.sharepoint.com/_vti_bin/idcrl.svc/

    您需要发送格式为:BPOSIDCRL + 空格 + 令牌 的授权标头。喜欢:

    GET https://yourtenantname/_vti_bin/idcrl.svc/ 
    Host: yourtenant.sharepoint.com
    Authorization: BPOSIDCRL t=EwA4A06hBwAUNfDkMme61kIdXqvj9tWnUbHtXWEAAREB5clgLb8J/VvxRFIKLUnd9SRyoBHmTHFk0viit2FMlGXak5NJKJhicT8MiZmgA2HoTrJM1EgXCNUpmWqrX1LQRNfs0PHEV4XncjI9lnphsSTiFSCDjmdCKtW4TmV8n18xJHvBtDUWdvCT2lBti8
    

    对这个请求的响应将设置一个 cookie,我们需要在下一个对 soap 服务的请求中捕获和使用它:

    Set-Cookie: SPOIDCRL=77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48U1A+VHJ1ZSwwaC5mfG1lbWJlcnNoaXB8MTAwMzdmZmU5NTc2YzdlZUBsaXZlLmNvbSwwIy5mfG1lbWJlcnNoaXB8Y2xvdWRAYXNlbWJsaWFkZXYub25taWNyb3NvZnQuY29tLDEzMTAxMjE4ODQ0Mzc0NDcxMjsxMzA5NTg5NTQ0NTAwMDAwMDAsRmFsc2UsUCtRcmlFSFRkRnZCNkJEREZFek1mK3RVaGlzZTZtdnl1R0N4aXpjaWpyRUdxZk1BN1RpdTJNdGN0VE42TVNjdi9Cbjd2OXRxS2VPaTBzWTdlTnRqNkFESmRubFM2S0ttVjdoeHRWNjdtY3FlQVQzYWJGeDFEVFd5dEJsOWZ3MDJkZ2JTakV3eUM3WTRIWXg0ek5UYUtvUTZacGFXR0NjZ0svZEtEbloya3ozdGFBblVPM1gvUkxBeUorYkZac2RGclBCRGF4aDNTMGpBTml2VTBzb0pJR0FFRmdsQzVaMWhxU28rekZFMU5UV01oMXphMjNPYUU0TjJUNHVjd1BlaEREKzR4Ry9yMWdXMC9zOWdTaGxTMlc1U29iVDhTY2NyYi80aG9Xb1Y2TWxva0t1bXBNOWc4cCtxb0xFL3dtaElDUm9MRGhQSXR1anhoSjlqb2lZY1RBPT0saHR0cHM6Ly9hc2VtYmxpYWRldi5zaGFyZXBvaW50LmNvbS9fdnRpX2Jpbi9pZGNybC5zdmMvPC9TUD4=; path=/; secure; HttpOnly
    

    最后,通过将此 cookie 附加到对 Sharepoint 服务的每个请求,我们将获得经过身份验证的响应:

    POST https://yourtenantname.sharepoint.com/_vti_bin/Lists.asmx HTTP/1.1
    Host: yourtenantname.sharepoint.com
    Content-Type: application/soap+xml; charset=utf-8
    Content-Length: [calculate]
    Cookie: SPOIDCRL=77u/PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz48U1A+VHJ1ZSwwaC5mfG1lbWJlcnNoaXB8MTAwMzdmZmU5NTc2YzdlZUBsaXZlLmNvbSwwIy5mfG1lbWJlcnNoaXB8Y2xvdWRAYXNlbWJsaWFkZXYub25taWNyb3NvZnQuY29tLDEzMTAxMjExNjM5MjM3NTM1ODsxMzA5NTg5NTQ0NTAwMDAwMDAsRmFsc2UsdEFEQUZZSnZiMFF6cWxFSFlKOGRPN1d1cnJ5RzJvcGxTelBueWFMUzhrNitjenBGT0JVK292M1VkSWhydGU3TXFMOHRJaFFzazRrNHd5REFqMklDUDcyMWpES3hKWmZRZjdaUlZQeisrUi92c09Qak13em5ITkg4bHVEQXdKcVlLdE16NStoaU84cUtTRzNZWEJYbWF4SDk1cDZtSDlaMVRzaFVDRXZMZ3ZIbkt6aWlPclh4UDE2RDBmZHlTRWxsU0Radmt2Tkg0UHBLT2VGbjI5S25qSk9veDVha21TZVlIbTY2ZnF5S0tpOUJmMHdjRmlyelNRZzBWZTc4NW1JZ1ZaQUY2VTArVEI0QVRvVXRVVFFqTnd4ODJEZE9jbWlqQ25NUTUzUHUrWEFIT25lenFVb1dPTXovVWk5V2VSTUMvMWZiOUpsUmZMNlZaNjNaZDRVazB3PT0saHR0cHM6Ly9hc2VtYmxpYWRldi5zaGFyZXBvaW50LmNvbS9fdnRpX2Jpbi9pZGNybC5zdmMvPC9TUD4=; path=/; secure; HttpOnly
    
    <?xml version="1.0" encoding="utf-8"?>
    <soap12:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap12="http://www.w3.org/2003/05/soap-envelope">
      <soap12:Body>
        <GetListCollection xmlns="http://schemas.microsoft.com/sharepoint/soap/" />
      </soap12:Body>
                    </soap12:Envelope>
    

    【讨论】:

    • 很好的发现。你们调查过请求用户同意的流程吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多