2010-11-29 13 views
24

Me interesa cómo implementar un sistema de inicio de sesión compartido entre dominios, así como las mejores prácticas y precauciones de seguridad. Si está familiarizado con 37Signals, probablemente esté acostumbrado a su uso de tener un mecanismo de autenticación universal compartido por el cual no tiene que iniciar sesión posteriormente si usa el nivel superior de navegación para un producto diferente. Me gustaría implementar algo de manera similar.¿Cómo crear un Servicio de inicio de sesión compartido en varios dominios?

Lo más parecido que he encontrado en línea es la entrada de Wikipedia en un Central Authentication Service y la respuesta a Cross Domain Login - How to login a user automatically when transfered from one domain to another, que puede ser ligeramente diferente en este caso.

He inspeccionado sus cookies de sesión para obtener una idea de lo que están haciendo en el proceso. Inicialmente, cada eslabón producto tiene una uristub "goto", es decir:

https://MY_COMPANY.campfirenow.com/id/users/[int_identifier]/goto

Usando Firecookie y la lengüeta de NET en Firebug, soy capaz de ver las cookies que se establecen y las redirecciones eso ocurre en el proceso. La url goto dispara una redirección 302 a:

https://MY_COMPANY.basecamphq.com/login/authenticate?sig=[BASE64_ENCODED_AND_ENCRYPTED_DATA]

se vuelve a crear el identificador de sesión, lo más probable para los propósitos CSRF. Algunos de los datos en las galletas, así como la sig parámetro GET se descifra parcialmente usando base64_decode a lo siguiente:.

// sig GET param 
array(2) { 
    [0]=> 
���ף�:@marshal_with_utc_coercionT7�z��<k��kW" 
    [1]=> 
    string(18) "���k�<kn8�f���to��" 
} 

// _basecamp_session cookie session param 
string(247) { 
:_csrf_token"1Sj5D6jCwJKIxkZ6oroy7o/mYUqr4R5Ca34cOPNigqkw=:session_id"%060c0804a5d06dafd1c5b3349815d863" 
flashIC:'ActionController::Flash::FlashHash{: 
@used{: auth{" 
       MY_COMPANY{: 
         user_idi�3 
:identity_idi�W����������s�]��:�N[��: 

߾"

La codificación se está rompiendo el bloque de código Gracias por su ayuda!

+0

¿Funcionaría para usted un servicio de inicio de sesión compartido preempaquetado como OpenID, Facebook, OAuth o Google? ¿O necesita absolutamente su propio servicio de inicio de sesión compartido? – Flipster

Respuesta

49

Creo que la clave de su Q es donde escribe "por lo que no tiene que iniciar sesión posteriormente si utiliza el nivel superior de navegación para un producto diferente".

Voy a explicar: Quiere ser capaz de moverse de site1.com a site2.com y dejar que site2.com sepa que es usted un usuario que inició sesión en site1.com.

porque las cookies no se pueden compartir entre dominios diferentes (distintos de los subdominios pero supongo que no se trata de subdominios), debe pasar cierta información en el enlace a site2.com que le permitirá hablar con su contenido final y saber qué usuario eres.

Comencemos con una solución ingenua y luego trabajemos para resolver algunos de los problemas que plantea: supongamos que tiene una tabla de usuarios en algún DB back-end y su usuario tiene alguna ID. ahora asume que el usuario se autenticó en site1.com y que él es el usuario 123 de su base de datos. La solución más ingenua sería llamar a site2.com/url/whatever?myRealID=123 y hacer que Site2 compruebe esta identificación y "creer" que el usuario es él.

Problema: Cualquier persona (incluso un usuario válido de su sitio) que verá su enlace puede crear un enlace con myRealID = 123 o intentar con otros valores. y site2.com lo aceptará como ese usuario.

Solución: no permitamos usar IDs adivinables supongamos que usted agrega a su tabla de usuarios un GUID único y si el usuario 123 tiene una guía de 8dc70780-15e5-11e0-ac64-0800200c9a66, entonces llame a site2.com/url/whawhat?myGuid= 8dc70780-15e5-11e0-ac64-0800200c9a66.

Problema nuevo: bueno, aunque sería muy poco probable que alguien adivine el GUID de su usuario su GUID todavía puede ser secuestrado por un intermediario que vea este enlace y alguien tendrá la guía para usarlo para siempre.

Solución: Utilice una clave privada guardada en su servidor para firmar una cadena que contiene los siguientes elementos de datos, marca de tiempo actual, sitio de destino (es decir, "sitio2.com") dicho GUID, esta firma puede traducirse a diciendo "Esto es una prueba de que este enlace fue creado por el sitio en ese momento para el usuario que tiene este GUID autenticado por este dominio" y lo envía a site2.com junto con la marca de tiempo y el GUID. Ahora cuando site2.com obtiene el enlace, puede asegurarse de que esté firmado correctamente y si algún intermediario o usuario original intentara cambiarlo de alguna manera (ya sea modificando la hora o el GUID), entonces la firma no coincidiría con el sitio2. com se negará a autenticar al usuario.

Un último problema: si el enlace es interceptado por un intermediario, puede seguir utilizándolo en otra máquina.

Solución: agregue un nonce a los parámetros pasados. El nonce es solo un número aleatorio que su sistema de autenticación debería asegurarse de que no le permite autenticarse con este número más de una vez (de ahí entonces nombre N (umber) -ONCE). Tenga en cuenta que esto significa que cada enlace que cree en site1.com que conduzca a site2.com debe tener un nonce distinto que debe guardarse en el back-end para su posterior validación.

porque no desea seguir agregando registros a esta tabla de nonce para siempre, es costumbre decidir que dicho enlace solo es válido durante un tiempo determinado después de su creación. y entonces usted puede crear registros nonce que son más antiguos que este límite de tiempo.

Espero que este es el perfil que estaba buscando. Es posible que haya omitido algo, pero esas son las pautas básicas, use una firma para probar la autenticidad de los datos en el enlace y use un código para evitar los ataques de los intermediarios. También recomendaría usar HTTPS para esos enlaces si es posible.

Eyal

+1

Para fomentar la implementación de claves compartidas: agregue valores de configuración que contengan un par de claves pública/privada para cada dominio en el sistema de inicio de sesión compartido. Si el método de verificación de firma es el mismo en todos los cuadros, puede verificar las firmas e incluso usar mcrypt() o una biblioteca equivalente para transferir datos encriptados bidireccionales para mayor seguridad en la parte superior de la firma de verificación (donde la firma es esencialmente suma de comprobación de los datos). –

+0

¿Por qué no utilizar solo el nonce (vinculado al ID de sesión en el back-end)? Lo que quiero decir es solo crear un token (quizás 1 o 2 minutos de caducidad, utilizable solo una vez) que está vinculado a la identificación de la sesión en el back-end, así que cuando lo uso en site2, el servidor puede capturar el ID de la sesión desde el DB, borrar el token y envíe la cookie de vuelta al navegador, dándole al navegador la misma sesión que tenía en el sitio1. ¿Qué inconvenientes tiene este enfoque? – mettjus

+0

al menos una diferencia sería que en cada intento de hackeo tendrías que ir al DB haciendo que te cueste más que solo verificar que los datos estén debidamente firmados y luego solo ir al DB si es correcto firmado. – epeleg

0

Ha intentado algo así como Charles para oler lo que se está enviando un lado a otro? puede ser que sea capaz de descomponer aún más las cosas para usted.

como se ha mencionado por FlipScript, quizás u cantar OAuth/OpenID podría ser un camino a seguir para ti?

0

Tome un vistazo a JASIG CAS http://www.jasig.org/cas. Creo que hará lo que quieras. Es de código abierto, y tiene una serie de complementos que le permiten autenticarse. Utilice múltiples fuentes de autenticación y desde múltiples dominios/idiomas.

1

Permitir a los usuarios la opción de utilizar su solución facebook/yahoo/gmail/openID es un comienzo, pero eso no soluciona definitivamente la solución de implementar o usar la propia solución.

Al haber desarrollado y gestionado una implementación en el pasado (en última instancia, fuimos a SiteMinder, pero supongo que no desea el costo de un producto real), creo que Eyal tiene una muy buena idea, pero yo Le agregaré un pequeño toque.

En el momento de la autenticación, genere un código aleatorio (podría ser un valor GUID, pero no es estático por usuario) que se almacena en una tabla transaccional junto con la identificación del usuario. Este código tiene una duración máxima (deberá juzgar el valor de seguridad para ese período de tiempo).Idealmente, este código debe ser hash con el nombre de usuario o encriptado y enviado como parte de la URL.

4

Puede intentar implementar una solución Global Network Auto-Login à Stack Overflow.
Hay una publicación perspicaz con respecto a su brillante implementación por Kevin Montrose here.

Requeriría Cookies, HTML5 localStorage, Javascript, Iframe y muchos controles de seguridad, pero creo que vale la pena.

0

Por qué no usar Abrir ID para este propósito.

OperID será la solución óptima para este problema.

+0

Open ID es una buena manera de autenticarse pero no resuelve el problema de cross site, es decir, si usa su Open ID para iniciar sesión en siteA.com, aún necesita los métodos anteriores para crear una situación en la que ahora también haya iniciado sesión en siteB.com. por cierto si quiere poder autenticarse con las redes sociales comunes también puede usar la solución proporcionada por gigya.com (donde estuve trabajando hasta hace poco), pero nuevamente, esto no resuelve el problema de los dominios cruzados que tendrá que manejar usted mismo. – epeleg

0

Usa algo como .NET Passport (es decir, Windows Live Id) o de la forma en que Facebook lo ha hecho con su API, que se puede ver abiertamente.

Cuestiones relacionadas