编程语言
首页 > 编程语言> > c# – 使用ADFS对ASP.NET Web Api进行身份验证

c# – 使用ADFS对ASP.NET Web Api进行身份验证

作者:互联网

我遇到的情况是我需要访问使用ADFS进行身份验证的ASP.NET Web Api.我可以通过浏览器通过ADFS登录门户网站获取相关的FedAuth cookie,从而可靠地点击它.不幸的是,我需要从专用浏览器外部访问它,以便在移动应用中使用.该项目几乎是为工作和学校认证(内部部署)设置的标准visual studio web api模板的略微修改版本,并设置用于cookie认证.

来自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请求访问令牌,并可使用相关登录信息获取不同版本的SAML断言,但它会被Web API拒绝.我误解了它应该如何工作吗?

根据我的理解,它应该是这样的:
How I think it’s supposed to work

> App从ADFS请求身份验证令牌
>如果提供的信息正确,ADFS会向被请求者提供身份验证令牌
> App向Web API发出请求,并在名为FedAuth的cookie中发送令牌(默认情况下,无论如何)作为base64编码的字符串
> Web Api将令牌发送到ADFS以查明令牌是否正确.
> ADFS以某种成功的方式回应
> Web Api会根据身份验证的方式对拒绝或数据进行响应.

这就是我现在正在试图弄清楚如何获得正确的令牌.

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:我明显得到的断言.也许我的googlefoo不够强大,但我似乎无法弄清楚从哪里开始.我可以设置api接受SAML断言还是我需要以不同的方式请求令牌?

解决方法:

您不能使用WS-Fed来调用Web API.您需要在Calling a web API in a web app using Azure AD and OpenID Connect中使用OpenID Connect / OAuth.

它适用于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,asp-net-web-api,access-token,adfs
来源: https://codeday.me/bug/20190608/1197753.html