使用OAuth2S2SClient获取AccessToken会返回“令牌请求失败”?

时间:2014-05-19 11:58:40

标签: sharepoint oauth-2.0 ms-office exchangewebservices office365

我尝试创建Sharepoint ClientContext以从sharpoint在线获取文档列表。 要做到这一点,我使用TokenHelper.cs类。 如果您还没有看过该类,则返回sharepoint上下文的代码如下所示:

/// <summary>
/// Uses the specified access token to create a client context
/// </summary>
/// <param name="targetUrl">Url of the target SharePoint site</param>
/// <param name="accessToken">Access token to be used when calling the specified targetUrl</param>
/// <returns>A ClientContext ready to call targetUrl with the specified access token</returns>
public static ClientContext GetClientContextWithAccessToken(string targetUrl, string accessToken)
  {
    Uri targetUri = new Uri(targetUrl);
    ClientContext clientContext = new ClientContext(targetUrl);

    clientContext.AuthenticationMode = ClientAuthenticationMode.Anonymous;
    clientContext.FormDigestHandlingEnabled = false;
    clientContext.ExecutingWebRequest +=
              delegate(object oSender, WebRequestEventArgs webRequestEventArgs)
                {
                    webRequestEventArgs.WebRequestExecutor.RequestHeaders["Authorization"] =
                        "Bearer " + accessToken;
                };
    return clientContext;
  }

但在调用此方法之前,我需要获取访问令牌,为此我使用TokenHelper类中的以下方法:

/// <summary>
/// Uses the specified authorization code to retrieve an access token from ACS to call the specified principal 
/// at the specified targetHost. The targetHost must be registered for target principal.  If specified realm is 
/// null, the "Realm" setting in web.config will be used instead.
/// </summary>
/// <param name="authorizationCode">Authorization code to exchange for access token</param>
/// <param name="targetPrincipalName">Name of the target principal to retrieve an access token for</param>
/// <param name="targetHost">Url authority of the target principal</param>
/// <param name="targetRealm">Realm to use for the access token's nameid and audience</param>
/// <returns>An access token with an audience of the target principal</returns>
public static OAuth2AccessTokenResponse GetAccessToken(string authorizationCode, string targetPrincipalName, string targetHost, string targetRealm, Uri redirectUri)
   {
     if (targetRealm == null)
     {
       targetRealm = Realm;
     }

     string resource = GetFormattedPrincipal(targetPrincipalName, targetHost, targetRealm);
     string clientId = GetFormattedPrincipal(ClientId, null, targetRealm);

     // Create request for token. The RedirectUri is null here.  This will fail if redirect uri is registered
     OAuth2AccessTokenRequest oauth2Request = OAuth2MessageFactory.CreateAccessTokenRequestWithAuthorizationCode(clientId, ClientSecret, authorizationCode, redirectUri, resource);

     // Get token
     OAuth2S2SClient client = new OAuth2S2SClient();
     OAuth2AccessTokenResponse oauth2Response;
     try
       {
         oauth2Response = client.Issue(AcsMetadataParser.GetStsUrl(targetRealm), oauth2Request) as OAuth2AccessTokenResponse;
       }
     catch (WebException wex)
       {
         using (StreamReader sr = new StreamReader(wex.Response.GetResponseStream()))
         {
           string responseText = sr.ReadToEnd();
           throw new WebException(wex.Message + " - " + responseText, wex);
         }
       }
 return oauth2Response;
 }

当我跟踪我的代码时,我可以看到以下行抛出异常:

oauth2Response = client.Issue(AcsMetadataParser.GetStsUrl(targetRealm),oauth2Request)as OAuth2AccessTokenResponse;

令牌请求失败。 HResult:-2146233088 来源:Microsoft.IdentityModel.Extensions 内部异常:远程服务器返回错误:(400)Bad Request。

任何想法?

2 个答案:

答案 0 :(得分:1)

请确保您将正确的参数传递给方法,我能够使用此方法获得访问令牌,只需很少的反复试验。我的方法调用签名是

var accessToken = TokenHelper.GetAccessToken(authCode, "00000003-0000-0ff1-ce00-000000000000", targetUri.Authority, realm, redirectUri).AccessToken;

authorizationCode是您使用SharePoint成功进行身份验证并重定向到应用程序页面时获得的。

string authCode = Request["code"];

targetPrincipalName是一个常量。

targetHost就像&#34; tenant.sharepoint.com&#34;

领域如下获得(这是您可以在租赁中重复使用的常数):

Uri targetUri = new Uri("https://<tenant>.sharepoint.com/sites/<sitename>");
string realm = TokenHelper.GetRealmFromTargetUrl(targetUri)

重定向uri是当前页面的uri,没有任何查询字符串。

redirectUri = new Uri(Request.Url.GetLeftPart(UriPartial.Path))

有关详细信息,请参阅此文章。 http://msdn.microsoft.com/en-us/library/office/jj687470(v=office.15).aspx

答案 1 :(得分:0)

MSDN下载图库中提供了许多示例,您可以下载并测试已经确认已正常工作的租户。我建议下拉其中一个示例,以证明它不是代码中的内容,并注销它不是您的租户环境。 http://code.msdn.microsoft.com/sharepoint/SharePoint-2013-Sample-81b03d1e