porta microsoft management azure oauth oauth-2.0 asp.net-web-api2 asp.net-identity

microsoft - porta azure



RelaciĆ³n con los usuarios cuando estos se almacenan en un servicio de proveedor de identidad externo (2)

Estoy tratando de crear una API y un cliente de sitio web para ello. Últimamente he estado leyendo mucho sobre OAuth2 como un mecanismo de seguridad y compañías que ofrecen autenticación como un servicio como auth0.com o incluso el Directorio activo de Azure y puedo ver las ventajas de usarlos

Porque estoy acostumbrado a tener siempre a los usuarios en la misma base de datos y tablas con relaciones con la tabla Usuarios en la forma de uno a muchos, como a continuación

public class User { public string subjectId { get; set; } public virtual List<Invoice> Invoices { get; set; } /* More properties in here */ } public class Invoice { public int InvoiceId { get; set; } public string PaymentNumber { get; set; } public DateTime Date { get; set; } public double Amount { get; set; } public string Description { get; set; } public virtual User User { get; set; } }

Mi pregunta es entonces.

Si los usuarios están almacenados en un servicio de autenticación externo como Auth0.com,

  • ¿Cómo manejará la clase Factura la relación con el usuario?
  • ¿Se estaría simplemente agregando una nueva propiedad subjectId en la tabla Factura y esto tomaría el valor de cualquier identificación que el servicio de autenticación asignó?

En este último caso, ¿la factura de la clase sería algo como abajo?

public class Invoice { public int InvoiceId { get; set; } public string PaymentNumber { get; set; } public DateTime Date { get; set; } public double Amount { get; set; } public string Description { get; set; } public string SubjectId{get;set;} }

Además, si los usuarios están almacenados en otro lugar, ¿cómo hacer una consulta como,

Select * from Users u inner join Invoices i where Users.Name=''John Doe'' and i.Date>Somedate.


Como mencionó Auth0 como su proveedor de Identidad, existen múltiples formas de lograr la tabla de usuarios en su base de datos. 1. La autenticación / registro del usuario con Auth0 enviará una respuesta con el objeto de perfil que tendrá toda la información básica del perfil que necesita. Publica este objeto de perfil en tu propia API para guardarlo en la base de datos. Este punto final API debe asegurarse con el token de acceso que recibió junto con el objeto de perfil de Auth0. 2. Puede crear una regla personalizada en Auth0 que registre la información del usuario en su API. Esta regla se ejecuta en el servidor Auth0, por lo que esta es una llamada segura. 3. Los proveedores de identidad (Auth0 en nuestro caso) están obligados a exponer un punto final API que nos brinde datos de perfil de usuario (ej .: https://yourdoamin.auth0.com/userinfo ). Puede hacer una llamada a este punto final desde su API para recibir la información del usuario.

Cuando el usuario se registra en su aplicación, utilice una de estas técnicas para establecer una tabla de información de perfil de usuario en su base de datos. Siempre es una buena idea tratar al Proveedor de Identidades como un servicio responsable de autenticar al propietario del recurso (el usuario de su aplicación) y proporcionar un token de acceso para acceder de manera segura a su API / aplicación. Si tiene el perfil del usuario en su base de datos, no tiene que depender del Proveedor de identidad una vez que el usuario está autenticado.

Por favor, hágamelo saber si tiene más preguntas.

Gracias, Soma.


Tenemos una configuración similar para nuestro sitio web. Usamos Passport para nuestra base de datos de usuarios y nuestro sitio web no tiene ninguna tabla de usuarios. Esto hace la vida mucho más simple que tener un montón de datos duplicados entre Passport y nuestro sitio web. Usaré nuestro código como ejemplo de lo que estás haciendo y espero que tenga sentido.

Nuestro sitio web tiene un objeto de licencia que se ve así (Java no es C #, pero son similares):

public class License { public String companyName; public List<User> users; }

La tabla de licencias se ve así (recortada):

CREATE TABLE licenses ( id UUID NOT NULL, company_name VARCHAR(255) NOT NULL, PRIMARY KEY (id) );

La Licencia identifica a los usuarios que están asociados a ella a través de una tabla de unión como esta (Passport usa UUID para identificadores de usuario volviendo a la vida simple):

CREATE TABLE users_licenses ( users_id UUID NOT NULL, licenses_id UUID NOT NULL, PRIMARY KEY (users_id, licenses_id), CONSTRAINT users_licenses_fk_1 FOREIGN KEY (licenses_id) REFERENCES licenses (id) );

Entonces podemos seleccionar en cualquier dirección. Si conocemos la identificación de usuario, podemos solicitar todas sus licencias de esta manera:

select * from licenses where users_id = ?

O si conocemos la identificación de la licencia, podemos preguntarle a todos los usuarios que tienen acceso a la licencia:

select * from users_licenses where licenses_id = ?

Una vez que tenemos uno o más identificadores de usuario, podemos llamar al punto final Passport / api / user o al punto final / api / user / search para recuperar uno o más objetos del usuario. En realidad, estamos usando Passport Java Client ( https://github.com/inversoft/passport-java-client ) que realiza la llamada API para nosotros y luego devuelve una List<User> . Esto es lo que está almacenado en la clase de License desde arriba. Ese código se ve así:

License license = licenseMapper.retrieveById(licenseId); List<UUID> userIds = licenseMapper.retrieveUserIdsFor(licenseId); ClientResponse<SearchResponse, Errors> clientResponse = passportClient.searchUsers(userIds); license.users = clientResponse.successResponse.users;

LicenseMapper es una interfaz MyBatis que ejecuta el SQL y devuelve los objetos de la Licencia. Los ORM de C # usan LINQ, pero sería similar.

Lo bueno de esta configuración es que no tenemos una tabla de base de datos de user base de datos de nuestro sitio web que tengamos que mantener sincronizada. Todo se carga desde Passport a través de la API. Tampoco nos preocupa el rendimiento. El pasaporte es in situ y puede hacer miles de búsquedas de usuarios por segundo, por lo que siempre cargamos los datos en lugar de almacenarlos en caché.

La única parte de su pregunta que requiere código adicional es manejar las uniones cuando está buscando usuarios arbitrarios como name=''John Doe'' . La única forma de manejar esto es consultar primero su base de datos de usuario, recuperar todos los ID y luego cargar sus facturas. Parece que podría ser peligroso si tienes una gran base de datos de usuarios, pero sigue siendo factible.

Eso podría verse así en nuestra situación:

UserSearchCriteria criteria = new UserSearchCriteria().withName("John Doe"); ClientResponse<SearchResponse, Errors> clientResponse = passportClient.searchUsersByQueryString(criteria); List<User> users = clientResponse.successResponse.users; Set<License> licenses = new HashSet<>(); for (User user : users) { licenses.addAll(licenseMapper.retrieveByUserId(user.id)); }