OWIN多应用承载令牌认证

时间:2013-12-16 23:48:50

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

我想修改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实现选项支持其他关键场景。

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

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

4 个答案:

答案 0 :(得分:7)

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

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

答案 1 :(得分:4)

默认情况下,OWIN使用ASP.NET机器密钥数据保护来保护在IIS上托管时的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);
}

答案 2 :(得分:1)

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

答案 3 :(得分:0)

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

    AuthorizationCodeFormat = new TicketDataFormat(new CustomDataProtector()),
    RefreshTokenFormat = new TicketDataFormat(new CustomDataProtector()),
    AccessTokenFormat = new TicketDataFormat(new CustomDataProtector()),
相关问题