我正在尝试在需要在 Windows-XP 及更高版本上运行的 WPF 客户端应用程序上为我的用户获取 SAML 令牌。我使用 WS-Trust 从身份提供者那里获取 SAML,然后将其传递给 Azure 访问控制服务,该服务使用 O-Auth 返回一个简单的 Web 令牌,我使用该令牌对客户端上的用户进行身份验证并调用安全 API在信任 ACS 的 Azure 上。
我的代码使用 WIF (Windows Identity Foundation) 并且在 windows-xp 之上的操作系统上运行良好。我见过的唯一示例使用 WIF 从安全令牌服务请求 SAML 令牌,但 Windows-xp 不支持 WIF,因此我被卡住了。我试图做一些研究,但找不到在不使用 WIF 的情况下完成上述场景的方法。我有什么办法可以在 windows xp 客户端上执行此操作吗?如果不是,那么我应该做些什么不同的事情?
我用来获取令牌的代码是:
//GetSamlToken from STS for ACS realm using UserCredential, this uses WIF
private SecurityToken GetSamlToken(string realm, string stsEndpoint, UserCredential userCredential)
{
Logger.Info("Getting Saml Token from Identity provider...");
using (var factory = new WSTrustChannelFactory(new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential), new EndpointAddress(new Uri(stsEndpoint))))
{
factory.Credentials.UserName.UserName = userCredential.UserName;
factory.Credentials.UserName.Password = userCredential.Password;
factory.TrustVersion = TrustVersion.WSTrust13;
WSTrustChannel channel = null;
try
{
var rst = new RequestSecurityToken
{
RequestType = WSTrust13Constants.RequestTypes.Issue,
AppliesTo = new EndpointAddress(realm),
KeyType = KeyTypes.Bearer,
};
channel = (WSTrustChannel)factory.CreateChannel();
RequestSecurityTokenResponse response;
var token = channel.Issue(rst, out response);
Logger.Info("Got Saml Token from Identity provider.");
return token;
}
finally
{
if (channel != null)
{
channel.Abort();
}
factory.Abort();
}
}
}
//使用从 STS 获得的 xmlSamlToken 从 ACS 服务端点获取 OAuthToken。
private NameValueCollection GetOAuthToken(string xmlSamlToken, string serviceEndpoint, string acsRelyingParty)
{
Logger.Info("Passing Saml token to ACS...");
WebClient client = new WebClient { BaseAddress = serviceEndpoint };
var values = new NameValueCollection
{
{ "grant_type", "urn:oasis:names:tc:SAML:2.0:assertion" },
{ "assertion", xmlSamlToken },
{ "scope", acsRelyingParty }
};
byte[] acsTokenResponse = client.UploadValues("v2/OAuth2-13", "POST", values);
string acsToken = Encoding.UTF8.GetString(acsTokenResponse);
var tokens = new NameValueCollection();
var parsed = new JavaScriptSerializer().DeserializeObject(acsToken) as Dictionary<string, object>;
Logger.Info("Parsed OAuth token.");
foreach (var item in parsed)
{
tokens.Add(item.Key, item.Value.ToString());
}
Logger.Info("Returning OAuth token.");
return tokens;
}