net bearer asp c# .net oauth asp.net-web-api owin

bearer - oauth2 web api c#



Obtenga IPrincipal del Token de portador OAuth en OWIN (4)

He agregado OAuth con éxito a mi proyecto WebAPI 2 usando OWIN. Recibo tokens y puedo usarlos en el encabezado HTTP para acceder a los recursos.

Ahora quiero usar esos tokens también en otros canales para autenticación que no son las solicitudes HTTP estándar para las que está hecha la plantilla OWIN. Por ejemplo, estoy usando WebSockets donde el cliente tiene que enviar el token de portador OAuth para autenticarse.

En el lado del servidor, recibo el token a través de WebSocket. ¿Pero cómo puedo ahora poner esta ficha en la tubería OWIN para extraer IPrincipal y ClientIdentifier de ella? En la plantilla de WebApi 2, todo esto se abstrae para mí, por lo que no tengo que hacer nada para que funcione.

Entonces, básicamente, tengo el token como una cadena y quiero usar OWIN para acceder a la información del usuario codificada en ese token.

Gracias por adelantado por la ayuda.


¿Cómo es tu token? ¿Es una cadena de cifrado o una cadena formateada? ¿Qué formato tiene?

Yo mi código:

public static Action<AuthenticationTokenReceiveContext> receive = new Action<AuthenticationTokenReceiveContext>(c => { if (!string.IsNullOrEmpty(c.Token)) { c.DeserializeTicket(c.Token); //c.OwinContext.Environment["Properties"] = c.Ticket.Properties; } });

El c.Ticket es siempre nulo.


Además de la respuesta johnny-qian , usar este método es mejor para crear DataProtector. Respuesta de johnny-qian , depende de IIS y falla en escenarios autohospedados.

using Microsoft.Owin.Security.DataProtection; var dataProtector = app.CreateDataProtector(new string[] { typeof(OAuthAuthorizationServerMiddleware).Namespace, "Access_Token", "v1" });


De forma predeterminada, OWIN utiliza la protección de datos de clave de máquina ASP.NET para proteger el token de acceso OAuth cuando está alojado en IIS. Puede usar la clase MachineKey en System.Web.dll para desproteger los tokens.

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); } }

A continuación, construya un TicketDataFormat para obtener el objeto AuthenticationTicket donde puede obtener ClaimsIdentity y AuthenticationProperties.

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

Para desproteger otros tokens de OAuth, solo necesitas cambiar el contenido de _purpose. Para obtener información detallada, consulte la clase OAuthAuthorizationServerMiddleware aquí: 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); }


Encontré una parte de la solución en esta publicación de blog: http://leastprivilege.com/2013/10/31/retrieving-bearer-tokens-from-alternative-locations-in-katanaowin/

Así que creé mi propio proveedor de la siguiente manera:

public class QueryStringOAuthBearerProvider : OAuthBearerAuthenticationProvider { public override Task RequestToken(OAuthRequestTokenContext context) { var value = context.Request.Query.Get("access_token"); if (!string.IsNullOrEmpty(value)) { context.Token = value; } return Task.FromResult<object>(null); } }

Entonces necesité agregarlo a mi aplicación en Startup.Auth.cs así:

OAuthBearerOptions = new OAuthBearerAuthenticationOptions() { Provider = new QueryStringOAuthBearerProvider(), AccessTokenProvider = new AuthenticationTokenProvider() { OnCreate = create, OnReceive = receive }, }; app.UseOAuthBearerAuthentication(OAuthBearerOptions);

Con AuthenticationTokenProvider personalizado, puedo recuperar todos los demás valores del token al principio de la canalización:

public static Action<AuthenticationTokenCreateContext> create = new Action<AuthenticationTokenCreateContext>(c => { c.SetToken(c.SerializeTicket()); }); public static Action<AuthenticationTokenReceiveContext> receive = new Action<AuthenticationTokenReceiveContext>(c => { c.DeserializeTicket(c.Token); c.OwinContext.Environment["Properties"] = c.Ticket.Properties; });

Y ahora, por ejemplo, en mi WebSocket Hander, puedo recuperar ClientId y otros como este:

IOwinContext owinContext = context.GetOwinContext(); if (owinContext.Environment.ContainsKey("Properties")) { AuthenticationProperties properties = owinContext.Environment["Properties"] as AuthenticationProperties; string clientId = properties.Dictionary["clientId"]; ... }