IIS 主机的 OWIN 中默认的 OAuth AccessTokenFormat 实现是啥?

Posted

技术标签:

【中文标题】IIS 主机的 OWIN 中默认的 OAuth AccessTokenFormat 实现是啥?【英文标题】:What's the default OAuth AccessTokenFormat implementation in OWIN for IIS host?IIS 主机的 OWIN 中默认的 OAuth AccessTokenFormat 实现是什么? 【发布时间】:2014-07-02 21:49:48 【问题描述】:

Web API 2 OWIN Bearer token authentication - AccessTokenFormat null?

默认的 /Token 端点工作正常,我可以从那里获取令牌, 但我需要在票证上使用 AccessTokenFormat.Protect 方法为 externalLogin 生成 accessToken。

基本上我的实现和这个差不多,我也遇到了同样的问题,AccessTokenFormat 为空。 从documentation 它说:

用于保护访问令牌中包含的信息的数据格式。如果应用程序未提供默认数据保护提供程序,则取决于主机服务器。 IIS 上的 SystemWeb 主机将使用 ASP.NET 机器密钥数据保护,而 HttpListener 和其他自托管服务器将使用 DPAPI 数据保护。如果分配了不同的访问令牌提供程序或格式,则必须将兼容的实例分配给资源服务器的 OAuthBearerAuthenticationOptions.AccessTokenProvider 或 OAuthBearerAuthenticationOptions.AccessTokenFormat 属性。

在我看来,如果未分配 AccessTokenFormat,主机将为它提供基本实现。但我认为它在这里不起作用。 有没有办法找到 ISecureDataFormatAccessTokenFormat 的默认实现并将其手动分配给变量?

或者有没有人有其他想法如何解决这个问题?

更新: 我得到了 katana 的源代码并找到了 OAuthAuthorizationServerMiddleware 类,从源代码中我可以看到以下代码:

if (Options.AccessTokenFormat == null)
        
            IDataProtector dataProtecter = app.CreateDataProtector(
                typeof(OAuthAuthorizationServerMiddleware).Namespace,
                "Access_Token", "v1");
            Options.AccessTokenFormat = new TicketDataFormat(dataProtecter);
        

在我的 Startup.Auth 中,这是我的代码:

     static Startup()
    
        PublicClientId = "self";

        UserManagerFactory = () => new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));

        OAuthOptions = new OAuthAuthorizationServerOptions()
        
            TokenEndpointPath = new PathString("/Token"),
            AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
            Provider = new ApplicationOAuthProvider(PublicClientId, UserManagerFactory),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
            AllowInsecureHttp = true
        ;

        OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
        OAuthBearerOptions.AccessTokenFormat = OAuthOptions.AccessTokenFormat;
        OAuthBearerOptions.AccessTokenProvider = OAuthOptions.AccessTokenProvider;
        OAuthBearerOptions.AuthenticationMode = OAuthOptions.AuthenticationMode;
        OAuthBearerOptions.AuthenticationType = OAuthOptions.AuthenticationType;
        OAuthBearerOptions.Description = OAuthOptions.Description;

        OAuthBearerOptions.Provider = new CustomBearerAuthenticationProvider();
        OAuthBearerOptions.SystemClock = OAuthOptions.SystemClock;
    

    public void ConfigureAuth(IAppBuilder app)
    
        // Configure the db context and user manager to use a single instance per request
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);


        app.UseOAuthAuthorizationServer(OAuthOptions);

        // Enable the application to use bearer tokens to authenticate users
        app.UseOAuthBearerTokens(OAuthOptions);
        // 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
        // Configure the sign in cookie
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            Provider = new CookieAuthenticationProvider
            
                OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
            
        );
        // Use a cookie to temporarily store information about a user logging in with a third party login provider
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

我在 WebApiConfig 中也有以下内容

// Web API configuration and services
        // Configure Web API to use only bearer token authentication.
        config.SuppressDefaultHostAuthentication();
        config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

我不知道为什么 app.UseOAuthAuthorizationServer(OAuthOptions); 没有设置 accessTokenFormat

【问题讨论】:

【参考方案1】:

我不确定为什么它没有正确设置,但我提取了代码并自己分配给它。这是我的最终工作代码:

      public void ConfigureAuth(IAppBuilder app)
    
        // Configure the db context and user manager to use a single instance per request
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);


        OAuthOptions = new OAuthAuthorizationServerOptions()
        
            TokenEndpointPath = new PathString("/Token"),
            Provider = new ApplicationOAuthProvider(PublicClientId, UserManagerFactory),
            AccessTokenFormat = new TicketDataFormat(app.CreateDataProtector(
               typeof(OAuthAuthorizationServerMiddleware).Namespace,
               "Access_Token", "v1")),
            RefreshTokenFormat = new TicketDataFormat(app.CreateDataProtector(
                typeof(OAuthAuthorizationServerMiddleware).Namespace,
                "Refresh_Token", "v1")),
            AccessTokenProvider = new AuthenticationTokenProvider(),
            RefreshTokenProvider = new AuthenticationTokenProvider(),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
            AllowInsecureHttp = true
        ;

        OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
        OAuthBearerOptions.AccessTokenFormat = OAuthOptions.AccessTokenFormat;
        OAuthBearerOptions.AccessTokenProvider = OAuthOptions.AccessTokenProvider;
        OAuthBearerOptions.AuthenticationMode = OAuthOptions.AuthenticationMode;
        OAuthBearerOptions.AuthenticationType = OAuthOptions.AuthenticationType;
        OAuthBearerOptions.Description = OAuthOptions.Description;

        OAuthBearerOptions.Provider = new CustomBearerAuthenticationProvider();
        OAuthBearerOptions.SystemClock = OAuthOptions.SystemClock;

        app.UseOAuthAuthorizationServer(OAuthOptions);
        app.UseOAuthBearerAuthentication(OAuthBearerOptions);

        // 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
        // Configure the sign in cookie
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            Provider = new CookieAuthenticationProvider
            
                OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
            
        );
        // Use a cookie to temporarily store information about a user logging in with a third party login provider
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
        

【讨论】:

以上是关于IIS 主机的 OWIN 中默认的 OAuth AccessTokenFormat 实现是啥?的主要内容,如果未能解决你的问题,请参考以下文章

Owin自身主机上的SignalR websocket

在WebApi中基于Owin OAuth使用授权发放Token

在自主机模式下获取当前的 owin 上下文

OWIN 自托管静态网站

Webapi、Webhost和Owin的关系

扩展 Microsoft.Owin.Security