我现在的情况是需要访问使用 ADFS 进行身份验证的 ASP.NET Web Api。通过 ADFS 登录门户并获取相关的 FedAuth cookie,我可以通过我的浏览器可靠地访问它。不幸的是,我需要从专用浏览器外部访问它以便在移动应用程序中使用。该项目几乎是为工作和学校身份验证(本地)设置并为 cookie 身份验证设置的标准 visual studio web api 模板的略微修改版本。
来自 Startup.Auth.cs 的一些代码:
public void Configuration(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseWsFederationAuthentication(
new WsFederationAuthenticationOptions
{
Wtrealm = realm,
MetadataAddress = adfsMetadata
});
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType
});
}
我似乎不知道从哪里开始。我已经尝试从 ADFS 请求访问 token ,并且可以使用相关的登录信息获取不同版本的 SAML 断言,但它被 Web API 拒绝了。我是否误解了它的工作原理?
根据我的理解,它应该是这样的: How I think it's supposed to work
- 应用从 ADFS 请求身份验证 token
- 如果提供的信息正确,ADFS 会为被请求者提供一个身份验证 token
- 应用程序向 Web API 发出请求,并将 token 作为 base64 编码字符串发送到名为 FedAuth 的 cookie 中(无论如何默认情况下)
- Web Api 将 token 发送到 ADFS 以确定 token 是否正确。
- ADFS 以某种成功消息作为响应
- Web Api 会根据身份验证的进行情况,通过拒绝或一段数据来响应应用。
这就是我在尝试弄清楚如何获得正确 token 时所拥有的。
using System;
using System.IdentityModel.Protocols.WSTrust;
using System.IdentityModel.Tokens;
using System.Net;
using System.Net.Http;
using System.ServiceModel;
using System.ServiceModel.Security;
using Thinktecture.IdentityModel.Extensions;
using Thinktecture.IdentityModel.WSTrust;
namespace ConsoleApplication1
{
class Program
{
private const string UserName = "USERNAME";
private const string Password = "PASSWORD";
private const string Domain = "DOMAIN";
private const string ADFSEndpoint = "ADFS ENDPOINT";
private const string ApiBaseUri = "THE API";
private const string ApiEndPoint = "AN ENDPOINT";
static void Main(string[] args)
{
SecurityToken token = RequestSecurityToken(); // Obtain security token from ADFS.
CallApi(token); // Call api.
Console.ReadKey(); // Stop console from closing
}
private static SecurityToken RequestSecurityToken()
{
var trustChannelFactory =
new WSTrustChannelFactory(new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),
new EndpointAddress(new Uri(ADFSEndpoint)))
{
TrustVersion = TrustVersion.WSTrust13,
Credentials = { UserName = { UserName = UserName + "@" + Domain, Password = Password } },
};
var requestSecurityToken = new RequestSecurityToken
{
RequestType = RequestTypes.Issue,
KeyType = KeyTypes.Bearer,
AppliesTo = new EndpointReference(ApiBaseUri)
};
RequestSecurityTokenResponse response;
var securityToken = trustChannelFactory.CreateChannel().Issue(requestSecurityToken, out response);
return securityToken;
}
private static async void CallApi(SecurityToken securityToken)
{
using (var handler = new HttpClientHandler { CookieContainer = new CookieContainer() })
{
using (var client = new HttpClient(handler))
{
handler.CookieContainer.MaxCookieSize = 8000; // Trying to make sure I can fit it in the cookie
var cookie = new Cookie {
Name = "FedAuth",
Value = Base64Encode(securityToken.ToTokenXmlString()),
HttpOnly = true,
Secure = true
};
handler.CookieContainer.Add(new Uri(ApiBaseUri), cookie);
var response = client.GetAsync(new Uri(ApiBaseUri + ApiEndPoint)).Result;
string result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
}
}
public static string Base64Encode(string plainText)
{
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
}
}
我不太记得我的示例基于什么代码,但如果有人能指出我正确的方向或告诉我哪里搞砸了,我将不胜感激。
编辑:抱歉,忘记添加我得到的内容。 由于抛出异常,Web Api 吐出一堆调试信息,告诉我需要 SecurityContextToken 而不是我显然得到的 saml:Assertion。也许我的 googlefoo 不够强大,但我似乎无法弄清楚从哪里开始。我可以设置 api 来接受 SAML 断言,还是我需要以不同的方式请求 token ?
最佳答案
您不能使用 WS-Fed 调用 Web API。您需要 OpenID Connect/OAuth,如 Calling a web API in a web app using Azure AD and OpenID Connect .
它适用于 Azure AD,但它确实说明了流程。
什么版本的 ADFS?
- 如果是 2.0,则不支持 OAuth。
- 如果是 3.0,则仅限 Web API - 请参阅 Securing a Web API with ADFS on WS2012 R2 Got Even Easier .
- 如果是 4.0,则您拥有完整的堆栈。
关于c# - 使用 ADFS 对 ASP.NET Web Api 进行身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42251515/