【问题标题】:OWIN multi-app bearer token authenticationOWIN 多应用不记名令牌认证
【发布时间】:2014-01-04 13:48:24
【问题描述】:

我想对 VS 2013 中 ASP.NET 的默认单页应用程序模板进行修改,该模板目前使用不记名令牌身份验证。该示例使用 app.UseOAuthBearerTokens 创建令牌服务器和中间件,以验证同一应用中请求的令牌。

我想做的是保留它,但添加第二个应用程序(在 IIS 中绑定到同一个域,不同的路径 - 例如 /auth/* 用于身份验证服务器, /app1/* 用于应用程序)。对于第二个应用程序,我希望它接受第一个应用程序中的身份验证服务器发出的令牌。这怎么可能实现?我在 Startup.Auth.cs 中尝试了以下操作,只是从 UseOAuthBearerTokens 中的代码开始,但我得到了对任何具有 [Authorize] 属性的请求的 401 响应:

public partial class Startup
{
    static Startup()
    {
        PublicClientId = "self";

        UserManagerFactory = () => new UserManager<IdentityUser>(new UserStore<IdentityUser>());

        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            //TokenEndpointPath = new PathString("/Token"),
            Provider = new ApplicationOAuthProvider(PublicClientId, UserManagerFactory),
            //AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            //AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
            AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
            AuthenticationType = "ExternalBearer",
            AllowInsecureHttp = true,
        };
    }

    public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

    public static Func<UserManager<IdentityUser>> UserManagerFactory { get; set; }

    public static string PublicClientId { get; private set; }

    // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
    public void ConfigureAuth(IAppBuilder app)
    {
        //// Enable the application to use a cookie to store information for the signed in user
        //// and to use a cookie to temporarily store information about a user logging in with a third party login provider
        //app.UseCookieAuthentication(new CookieAuthenticationOptions());
        //app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        OAuthBearerAuthenticationOptions bearerOptions = new OAuthBearerAuthenticationOptions();
        bearerOptions.AccessTokenFormat = OAuthOptions.AccessTokenFormat;
        bearerOptions.AccessTokenProvider = OAuthOptions.AccessTokenProvider;
        bearerOptions.AuthenticationMode = OAuthOptions.AuthenticationMode;
        bearerOptions.AuthenticationType = OAuthOptions.AuthenticationType;
        bearerOptions.Description = OAuthOptions.Description;
        bearerOptions.Provider = new CustomBearerAuthenticationProvider();
        bearerOptions.SystemClock = OAuthOptions.SystemClock;
        OAuthBearerAuthenticationExtensions.UseOAuthBearerAuthentication(app, bearerOptions);
    }
}

public class CustomBearerAuthenticationProvider : OAuthBearerAuthenticationProvider
    {
        public override Task ValidateIdentity(OAuthValidateIdentityContext context)
        {
            var claims = context.Ticket.Identity.Claims;
            if (claims.Count() == 0 || claims.Any(claim => claim.Issuer != "LOCAL AUTHORITY"))
                context.Rejected();
            return Task.FromResult<object>(null);
        }
    }

显然,我错过了第二个应用程序可以通过某种方式验证令牌来自第一个应用程序的部分。某种公共签名密钥?

这只是一个概念证明。

编辑:机器密钥建议在 POC 演示中运行良好,很高兴知道有支持其他关键场景的 AS 实现选项。

我能够使用此站点生成一个演示密钥(不用于生产): http://aspnetresources.com/tools/machineKey

并将结果放在 IIS 站点中托管的每个应用程序的 web.config 中的 &lt;system.web&gt; 元素下。我还必须在资源服务器的 Startup 类中删除一些特定于 AS 的配置选项。

【问题讨论】:

    标签: asp.net oauth asp.net-web-api owin


    【解决方案1】:

    目前,中间件(或者更确切地说是生成的令牌)并非真正设计为跨应用程序工作。对于这些场景,您应该使用真正的授权服务器(例如https://github.com/thinktecture/Thinktecture.AuthorizationServer)。

    也就是说,您可以通过在两个应用程序中同步机器密钥(web.config 中的 machineKey 元素)来使其工作。但我从未尝试过。

    【讨论】:

    • +1 用于在网络场中使用相同的机器密钥,以允许在多个服务器上使用相同的访问/承载令牌。今天学习了《IIS 上的默认数据保护提供程序...将使用 ASP.NET 机器密钥数据保护》msdn.microsoft.com/en-us/library/…
    • 不 +1 使用机器密钥。整个下午都在和这些东西作斗争,机器钥匙并不能解决我的问题。刚刚推出了我自己的 IDataProtector 并试图弄清楚如何将它全部放在链中,我遇到的每个样本都让人吐出机器钥匙,就像它是圣杯一样。跛脚!
    【解决方案2】:

    默认情况下,当托管在 IIS 上时,OWIN 使用 ASP.NET 机器密钥数据保护来保护 OAuth 访问令牌。您可以使用 System.Web.dll 中的 MachineKey 类来取消对令牌的保护。

    public class MachineKeyProtector : IDataProtector
    {
        private readonly string[] _purpose =
        {
            typeof(OAuthAuthorizationServerMiddleware).Namespace,
            "Access_Token",
            "v1"
        };
    
        public byte[] Protect(byte[] userData)
        {
           throw new NotImplementedException();
        }
    
        public byte[] Unprotect(byte[] protectedData)
        {
            return System.Web.Security.MachineKey.Unprotect(protectedData, _purpose);
        }
    }
    

    然后,构造一个 TicketDataFormat 来获取 AuthenticationTicket 对象,您可以在其中获取 ClaimsIdentity 和 AuthenticationProperties。

    var access_token="your token here";
    var secureDataFormat = new TicketDataFormat(new MachineKeyProtector());
    AuthenticationTicket ticket = secureDataFormat.Unprotect(access_token);
    

    要取消保护其他 OAuth 令牌,您只需更改 _purpose 内容。有关详细信息,请参阅此处的 OAuthAuthorizationServerMiddleware 类: http://katanaproject.codeplex.com/SourceControl/latest#src/Microsoft.Owin.Security.OAuth/OAuthAuthorizationServerMiddleware.cs

    if (Options.AuthorizationCodeFormat == null)
    {
        IDataProtector dataProtecter = app.CreateDataProtector(
            typeof(OAuthAuthorizationServerMiddleware).FullName,
            "Authentication_Code", "v1");
    
        Options.AuthorizationCodeFormat = new TicketDataFormat(dataProtecter);
    }
    if (Options.AccessTokenFormat == null)
    {
        IDataProtector dataProtecter = app.CreateDataProtector(
            typeof(OAuthAuthorizationServerMiddleware).Namespace,
            "Access_Token", "v1");
        Options.AccessTokenFormat = new TicketDataFormat(dataProtecter);
    }
    if (Options.RefreshTokenFormat == null)
    {
        IDataProtector dataProtecter = app.CreateDataProtector(
            typeof(OAuthAuthorizationServerMiddleware).Namespace,
            "Refresh_Token", "v1");
        Options.RefreshTokenFormat = new TicketDataFormat(dataProtecter);
    }
    

    【讨论】:

      【解决方案3】:

      虽然目前列出的答案都很好,但我已经使用了几次并取得了巨大的成功。在 web.config 中设置机器密钥效果很好。确保您使用 microsoft 网站上的 powershell 生成您自己的! http://bitoftech.net/2014/09/24/decouple-owin-authorization-server-resource-server-oauth-2-0-web-api/

      【讨论】:

        【解决方案4】:

        尝试创建自定义IDataProtector 并按以下方式配置您的OAuthAuthorizationServerOptions

            AuthorizationCodeFormat = new TicketDataFormat(new CustomDataProtector()),
            RefreshTokenFormat = new TicketDataFormat(new CustomDataProtector()),
            AccessTokenFormat = new TicketDataFormat(new CustomDataProtector()),
        

        【讨论】:

          猜你喜欢
          • 2014-10-11
          • 2023-03-05
          • 2017-10-28
          • 2020-09-13
          • 2016-01-01
          • 2018-02-07
          • 2019-08-30
          • 1970-01-01
          • 2016-11-22
          相关资源
          最近更新 更多