Registro de inicios de sesión externos de Web API 2 desde múltiples clientes API con identidad OWIN


Me gustaría la siguiente arquitectura (he creado el nombre del producto para este ejemplo):

Aplicación Web API 2 ejecutándose en un servidor http://api.prettypictures.com

Aplicación cliente MVC 5 que se ejecuta en otro servidor http://www.webpics.com

Me gustaría www.webpics.com aplicación cliente para usar la API Pretty Pictures para:

  • Registrar nuevas cuentas con nombre de usuario y contraseña
  • Registrar nuevo cuentas con Facebook/Google/Twitter / Microsoft
  • Iniciar sesión
  • Recuperar imágenes

Todo lo anterior funciona excepto registrar cuentas externas con Facebook, Google, etc.

No puedo calcular el flujo correcto para crear una cuenta externa desde un usuario cliente separado de la API.

He estudiado la mayoría de los documentos disponibles en el flujo de autenticación, así: introduzca la descripción de la imagen aquí

He leído casi todo lo que puedo sobre la nueva Identidad modelo en OWIN.

He examinado la plantilla SPA en Visual Studio 2013. Demuestra cómo hacer la mayoría de lo que necesito, pero solo cuando el cliente y la API están en el mismo host; si quiero que varios clientes accedan a mi API y puedan permitir que los usuarios se registren a través de Google, etc. no funciona y por lo que puedo decir se rompe el flujo de autenticación de OWIN.

Aquí está el flujo hasta ahora:

  • El usuario navega a www.webpics.com/Login
  • www.webpics.com llama api.prettypictures.com/Account/ExternalLogins (con un returnUrl configurado para volver a una devolución de llamada en www.webpics.com ) y muestra los enlaces resultantes al usuario
  • El usuario hace clic en "Google"
  • El navegador redirige a api.prettypictures.com/Account/ExternalLogin con el nombre del proveedor, etc.
  • La acción de la API ExternalLogin crea una instancia desafío a google.com
  • El navegador es redirigido a google.com
  • El usuario introduce su nombre de usuario y contraseña (si aún no ha iniciado sesión en google.com )
  • google.com ahora presenta la autorización de seguridad: "api.prettypictures.com" desea acceder a su dirección de correo electrónico, nombre, esposa, hijos, etc. ¿Esto está bien?
  • El usuario hace clic en " Yep " y es llevado de nuevo a api.prettypictures.com/Account/ExternalLogin con una cookie que Google ha establecido.

Aquí es donde me he quedado atascado. Lo que se supone que sucederá a continuación es que de alguna manera se debe notificar a la aplicación cliente que el usuario se ha autenticado correctamente con google.com y se le dará un código de acceso de un solo uso para intercambiar por un token de acceso más adelante. La aplicación cliente debe tener la oportunidad, si es necesario, de solicitar al usuario un nombre de usuario para asociarse con su google.com sesión.

No se como facilitar esto.

De hecho, en este punto el navegador termina sentado en el api.prettypictures.com/Account/ExternalLogin punto final después de la devolución de llamada de Google. La API está iniciada para Google, pero el cliente no sabe cómo lidiar con eso. Debo canalizar esa galleta de vuelta a www.webpics.com ?

En la aplicación SPA, se hace a través de AJAX y google.com devolverá un token como un fragmento de URL y todo funciona muy bien porque todo se asienta en un dominio. Pero eso desafía gran parte del punto de tener una "API" que múltiples clientes pueden usar completamente.

Ayuda!

Author: joshcomley, 2014-01-16

1 answers

Actualización: las cosas han cambiado desde que escribí este post en enero: MSFT lanzó su middleware cliente OpenID connect oficial y trabajé duro con @manfredsteyer para adaptar el servidor de autorización OAuth2 construido en Katana para OpenID connect. Esta combinación resulta en una solución mucho más fácil y mucho más potente que no requiere ningún código de cliente personalizado y es 100% compatible con los clientes estándar OAuth2 / OpenID connect. Los diferentes pasos que mencioné en enero ahora pueden ser sustituido por unas pocas líneas:

Servidor:

app.UseOpenIdConnectServer(options =>
{
    options.TokenEndpointPath = new PathString("/connect/token");
    options.SigningCredentials.AddCertificate(certificate);

    options.Provider = new CustomOpenIdConnectServerProvider();
});

Cliente:

app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
    Authority = "http://localhost:55985/",

    ClientId = "myClient",
    ClientSecret = "secret_secret_secret",
    RedirectUri = "http://localhost:56854/oidc"
});

Puedes encontrar todos los detalles (y diferentes muestras) en el repositorio GitHub:

Https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server

Https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/tree/dev/samples/Nancy


Josh, definitivamente estás en el camino correcto y tu autenticación delegada/federada la implementación parece bastante buena (imagino que ha utilizado el middleware OWIN predefinido de Microsoft.Owin.Security.Facebook/Google/Twitter).

Lo que necesita hacer es crear su propio servidor de autorización personalizado OAuth2. Tienes muchas opciones para lograrlo, pero la más fácil es probablemente conectar OAuthAuthorizationServerMiddleware en tu clase de inicio de OWIN. Lo encontrarás en el paquete Nuget Microsoft.Owin.Security.OAuth.

Mientras que la mejor práctica sería crear un proyecto separado (a menudo llamado "AuthorizationServer"), personalmente prefiero agregarlo a mi "proyecto API" cuando no está destinado a ser utilizado a través de múltiples API (aquí, tendría que insertarlo en el alojamiento del proyecto "api.prettypictures.com").

Encontrarás una gran muestra en el repositorio Katana:

Https://katanaproject.codeplex.com/SourceControl/latest#tests/Katana.Sandbox.WebServer/Startup.cs

app.UseOAuthAuthorizationServer(new OAuthAuthorizationServerOptions
{
    AuthorizeEndpointPath = new PathString("/oauth2/authorize"),
    TokenEndpointPath = new PathString("/oauth2/token"),
    ApplicationCanDisplayErrors = true,

    AllowInsecureHttp = true,

    Provider = new OAuthAuthorizationServerProvider
    {
        OnValidateClientRedirectUri = ValidateClientRedirectUri,
        OnValidateClientAuthentication = ValidateClientAuthentication,
        OnGrantResourceOwnerCredentials = GrantResourceOwnerCredentials,
    },
    AuthorizationCodeProvider = new AuthenticationTokenProvider
    {
        OnCreate = CreateAuthenticationCode,
        OnReceive = ReceiveAuthenticationCode,
    },
    RefreshTokenProvider = new AuthenticationTokenProvider
    {
        OnCreate = CreateRefreshToken,
        OnReceive = ReceiveRefreshToken,
    }
});

No dude en navegar por todo el proyecto para ver cómo el el formulario de consentimiento de autorización se ha implementado utilizando archivos Razor simples. Si prefiere un marco de alto nivel como ASP.NET MVC o NancyFx, cree su propio controlador AuthorizationController y métodos Authorize (asegúrese de aceptar tanto GET como POST) y use el Enrutamiento de atributos para que coincida con el AuthorizeEndpointPath definido en su servidor de autorización OAuth2 (ie. [Route("oauth2/authorize")] en mi ejemplo, donde he cambiado el AuthorizeEndpointPath para usar oauth2/ como una base de ruta).

La otra cosa que debe hacer es agregar un OAuth2 cliente de autorización en su aplicación web. Desafortunadamente, no hay soporte al cliente genérico OAuth2 en Katana, y tendrás que construir el tuyo propio. He presentado personalmente una propuesta al equipo Katana, pero ha sido rechazada. Pero no te asustes, es bastante fácil de hacer:

Copie los archivos apropiados de Microsoft.Owin.Seguridad.Repositorio de Google ubicado allí: https://katanaproject.codeplex.com/SourceControl/latest#src/Microsoft.Owin.Security.Google/GoogleOAuth2AuthenticationHandler.cs

Necesitarás GoogleOAuth2AuthenticationHandler, GoogleOAuth2AuthenticationMiddleware, GoogleOAuth2AuthenticationOptions, GoogleAuthenticationExtensions (tendrás que eliminar los primeros 2 métodos correspondientes a la implementación de Google OpenID), IGoogleOAuth2AuthenticationProvider, GoogleOAuth2ReturnEndpointContext, GoogleOAuth2AuthenticationProvider, GoogleOAuth2AuthenticatedContext y GoogleOAuth2ApplyRedirectContext. Una vez que haya insertado estos archivos en el alojamiento de su proyecto "webpics.com", cambiar el nombre en consecuencia y cambiar la autorización y acceso token endpoints URL en GoogleOAuth2AuthenticationHandler para que coincida con los que ha definido en su servidor de autorización OAuth2.

Luego, agregue el método Use desde su renombrado/personalizado GoogleAuthenticationExtensions a su clase de inicio OWIN. Sugiero usar AuthenticationMode.Active para que sus usuarios sean redirigidos directamente a su endpoint de autorización API OAuth2. Por lo tanto, usted debe suprimir el "api.prettypictures.com/Account/ExternalLogins" viaje de ida y vuelta y deje que el middleware del cliente OAuth2 altere las respuestas 401 para redirigir a los clientes a su API.

Buena suerte. Y no lo dudes si necesitas más información;)

 46
Author: Pinpoint,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-30 19:35:01