简体   繁体   English

从OWIN Cookie获取持有者令牌并将其置于API请求中

[英]Get bearer token from OWIN Cookie and put it on API Requests

Here is my scenario: I have a MVC4.5/WebApi2 application that uses OpenIdConnectAuthentication based on a Thinktecture.IdentityServer provider. 这是我的情况:我有一个基于一个Thinktecture.IdentityServer提供商使用OpenIdConnectAuthentication一个MVC4.5 / WebApi2应用。 So far I can authenticate against MVC. 到目前为止,我可以对MVC进行身份验证。 Now I want to authenticate to the WebApi using Bearer Token. 现在我想使用Bearer Token对WebApi进行身份验证。 Here is my configuration 这是我的配置

app.UseWebApi(ConfigureAPI());
app.UseCookieAuthentication(new CookieAuthenticationOptions() {
        AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
        CookieSecure = CookieSecureOption.Always,
        AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
        CookieHttpOnly = true
    });

app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions() {
                EnableValidationResultCache = false,
                Authority = WebConfigurationManager.AppSettings["Authority"],
                AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Passive
            });

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions() {
                Authority = WebConfigurationManager.AppSettings["Authority"],
                ClientId = WebConfigurationManager.AppSettings["ClientId"],
                ClientSecret = WebConfigurationManager.AppSettings["ClientSecret"],
                ResponseType = "code id_token",
                Scope = "openid email profile", 
                SignInAsAuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
                Notifications = new OpenIdConnectAuthenticationNotifications {
                    AuthenticationFailed = OnAuthenticationFailed,
                    AuthorizationCodeReceived = OnAuthorizationCodeReceived,
                    RedirectToIdentityProvider = OnRedirectToIdentityProvider
                }
            };
);

And my WebApi Configuration 还有我的WebApi配置

public HttpConfiguration ConfigureAPI() {
            var httpConfig = new HttpConfiguration();
            // Configure Web API to use only bearer token authentication.
            httpConfig.SuppressDefaultHostAuthentication();
            httpConfig.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));    
            httpConfig.Formatters.JsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

            // Web API routes
            httpConfig.MapHttpAttributeRoutes();

            httpConfig.Routes.MapHttpRoute(
                 name: "DefaultApi",
                 routeTemplate: "api/{controller}/{id}",
                 defaults: new { id = RouteParameter.Optional }
            );
            return httpConfig;
        }

Since I already have the access token in my OWIN Cookie, I want to add it to the authorization header before it reaches the API and so get a successful authentication. 由于我已经在我的OWIN Cookie中拥有访问令牌,因此我希望在它到达API之前将其添加到授权标头中,从而获得成功的身份验证。

Here is what I tried 这是我试过的

public class CustomAuthorizeAttribute : AuthorizeAttribute {
        protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext) {
            var cookies = actionContext.Request.Headers.GetCookies(".AspNet.Cookies");
            var cookie = cookies.First().Cookies.FirstOrDefault(c => c.Name == ".AspNet.Cookies");
            if (cookie != null) {               
                var unprotectedTicket = Startup.OAuthOptions.TicketDataFormat.Unprotect(ticket);
                actionContext.Request.Headers.Add("Authorization", string.Format("Bearer {0}", unprotectedTicket.Identity.Claims.First(c => c.Type == "access_token").Value));                  
            }
            return base.IsAuthorized(actionContext);
        }
    }

I even try with an OWIN Middleware placed after app.UseWebApi(ConfigureAPI()); 我甚至尝试在app.UseWebApi(ConfigureAPI());之后放置一个OWIN中间件app.UseWebApi(ConfigureAPI());

public class UseCookieToBearerAuthentication : OwinMiddleware {
        public UseCookieToBearerAuthentication(OwinMiddleware next) : base(next) { }

        public async override Task Invoke(IOwinContext context) {
            //TODO Retrieve cookie name from somewhere like in FormsAuthentication.FormsCookieName          
            var cookies = context.Request.Cookies;
            var cookie = cookies.FirstOrDefault(c => c.Key == ".AspNet.Cookies");
            if (!cookie.Equals(default(KeyValuePair<string, string>))) {
                var ticket = cookie.Value;
                var unprotectedTicket = Startup.OAuthOptions.TicketDataFormat.Unprotect(ticket);
                context.Request.Headers.Add("Authorization", new string[]{
                    string.Format("Bearer {0}", unprotectedTicket.Identity.Claims.First(c => c.Type == "access_token").Value)
                });
            }
            await Next.Invoke(context);
        }
    }

So, How can I achieve token authentication for my web api based on the access token in my Owin Cookie?. 那么,如何根据我的Owin Cookie中的访问令牌为我的web api实现令牌认证?

Thanks in advance. 提前致谢。

The problem was that IdentityServerBearerTokenAuthenticationOptions by default uses AuthenticationMode = ValidationMode.ValidationEndpoint; 问题是IdentityServerBearerTokenAuthenticationOptions默认使用AuthenticationMode = ValidationMode.ValidationEndpoint; that by default uses Microsoft.Owin.Security.AuthenticationMode.Active and cannot be overriden. 默认情况下使用Microsoft.Owin.Security.AuthenticationMode.Active并且无法覆盖。

So I set IdentityServerBearerTokenAuthenticationOptions to ValidationMode = ValidationMode.Local; 所以我将IdentityServerBearerTokenAuthenticationOptions设置为ValidationMode = ValidationMode.Local; and AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Passive; AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Passive; which is fine because the Access Token is a JWT (self-contained). 这很好,因为访问令牌是一个JWT(自包含)。

I also use an OWIN middleware to get the access token from the cookie on the request and set it on the autorization header. 我还使用OWIN中间件从请求中的cookie获取访问令牌,并将其设置在autorization标头上。

public class UseCookieToBearerAuthentication : OwinMiddleware {
        public UseCookieToBearerAuthentication(OwinMiddleware next) : base(next) { }



    public async override Task Invoke(IOwinContext context) {
                var x = Startup.OAuthOptions.CookieName;
                var cookieName = string.Format("{0}{1}", CookieAuthenticationDefaults.CookiePrefix, CookieAuthenticationDefaults.AuthenticationType);
                var cookies = context.Request.Cookies;
                var cookie = cookies.FirstOrDefault(c => c.Key == ".AspNet.Cookies");
                if (!cookie.Equals(default(KeyValuePair<string, string>))) {
                    var ticket = cookie.Value;
                    var unprotectedTicket = Startup.OAuthOptions.TicketDataFormat.Unprotect(ticket);
                    context.Request.Headers.Add("Authorization", new string[]{
                        string.Format("Bearer {0}", unprotectedTicket.Identity.Claims.First(c => c.Type == "access_token").Value)
                    });
                }
                await Next.Invoke(context);
            }
        }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM