2014-02-24 60 views
2

我有一個通過ADFS進行身份驗證的Web應用程序和Web API服務。它們包含在同一個IIS應用程序中,並且Web應用程序可以毫無問題地回調Web API服務。將SAML令牌傳遞到Web API調用

我現在試圖從不同的應用程序調用相同的服務,但在傳遞令牌時遇到問題。我可以用下面的代碼進行驗證和檢索SAML令牌:

var stsEndpoint = "https://MyAdfsServer/adfs/services/trust/13/UsernameMixed"; 
var reliantPartyUri = "https://MyDomain/AppRoot/"; 

var factory = new Microsoft.IdentityModel.Protocols.WSTrust.WSTrustChannelFactory(
      new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential), 
      new EndpointAddress(stsEndpoint)); 

factory.TrustVersion = System.ServiceModel.Security.TrustVersion.WSTrust13; 

// Username and Password here... 
factory.Credentials.UserName.UserName = @"Domain\UserName"; 
factory.Credentials.UserName.Password = "Password"; 

var rst = new RequestSecurityToken 
    { 
     RequestType = RequestTypes.Issue, 
     AppliesTo = new EndpointAddress(reliantPartyUri), 
     KeyType = KeyTypes.Bearer, 
    }; 

var channel = factory.CreateChannel(); 
var token = channel.Issue(rst) as GenericXmlSecurityToken; 

var saml = token.TokenXml.OuterXml; 

但是,我不知道如何通過SAML到Web API調用。我試過這個:

using (var handler = new HttpClientHandler() 
    { 
     ClientCertificateOptions = ClientCertificateOption.Automatic, 
     AllowAutoRedirect = false 
    }) 
{ 
    using (var client = new HttpClient(handler)) 
    { 
     client.BaseAddress = new Uri("https://MyDomain/AppRoot/api/"); 

     client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("SAML", saml); 

     HttpResponseMessage response = client.GetAsync("MyService/Get/").Result; 

     // Get the results... 
     var result = response.Content.ReadAsStringAsync().Result; 
     var status = response.StatusCode; 
    } 
} 

這是返回狀態碼302並嘗試將我重定向到ADFS服務器進行身份驗證。是否有另一種方式將SAML令牌傳遞給Web api服務?

+0

SAML令牌和REST API不玩好起來。考慮使用OAuth 2.0。 –

+0

我也有同樣的問題,因爲我有Windows Server 2008 R2和Oauth 2.0不可用,您是否設法做到這一點? –

+0

不,我們最終創建了一個使用Windows身份驗證進行身份驗證的獨立IIS應用程序來公開所需的服務。不是最好的解決方案,但它符合我們的需求。 –

回答

1

我一直在處理同樣的挑戰。問題的核心在於SAML是基於SOAP的規範;它旨在跨多個SOAP處理節點進行消息保護,而不考慮傳輸。

另一方面,REST是關於運輸。因此,REST端點的安全性基於傳輸安全(例如SSL)。

我們實施了一個「黑客」,我們使用NetworkCredential和固定用戶名(如「saml_user」)並將密碼設置爲SAML令牌。但這是短期的事情。你真的想在每次通話中添加8到10 KB嗎?

簡單Web令牌更適合REST安全。事實上,Microsoft的基於聲明的身份和訪問控制指南(第二版)有一整章致力於從SAML令牌提供者到簡單Web令牌的橋接。見Accessing REST Services from a Windows Phone Device

1

(SET)

  string samlString = "blah blah blah"; 

      byte[] bytes = Encoding.UTF8.GetBytes(samlString); 

      string base64SamlString = Convert.ToBase64String(bytes); 

      myHttpClient.DefaultRequestHeaders.Add("X-My-Custom-Header", base64SamlString); 

(GET)

 IEnumerable<string> headerValues = request.Headers.GetValues("X-My-Custom-Header"); 

     if (null != headerValues) 

     { 

      var encoding = Encoding.GetEncoding("iso-8859-1"); 

      string samlToken = encoding.GetString(Convert.FromBase64String(headerValues.FirstOrDefault())); 

     } 
+0

當我調用encoding時,這種方法給了我一個'錯誤411:長度required'。GetString –

+0

「headerValues.FirstOrDefault()」的字符串長度是多少? – granadaCoder

+0

對不起,我最終將數據編碼爲POST數據(即不是作爲標題)並丟失了該代碼的軌跡 –