Almacenamiento y acceso a los atributos
Con IBM Cloud® App ID, puede compilar información sobre los usuarios individuales de la aplicación en un perfil. La información en el perfil se puede obtener de los usuarios por la forma en que interactúan con la app o puede añadirlos usted mismo por ellos. Al almacenar la información, puede acceder a ella para ayudar a crear experiencias personalizadas de la app para los usuarios.
Visión general de los perfiles
Un perfil de usuario es toda la información que se conoce sobre un usuario específico, compilada en un objeto JSON y almacenada por App ID. Hay dos tipos de información, o atributos, que se pueden obtener y almacenar en un perfil: predefined
y custom
. Los atributos predefinidos son específicos de la identidad del usuario y son los que devuelve un proveedor de identidad cuando el usuario inicia sesión en la app, y puede incluir información como su nombre o su edad.
Los atributos personalizados se utilizan para almacenar información adicional sobre los usuarios. Los puede establecer usted o se pueden ir obteniendo sobre el usuario a medida que éste interactúa con la app. Los atributos personalizados pueden
incluir un rol asignado, una preferencia de comida o la preferencia por un asiento de pasillo en un avión.
Puede almacenar hasta 100 KB de información de cada usuario.
¿Cómo puedo obtener la información del perfil de usuario?
Existen varias formas diferentes en las que se puede acceder a la información del usuario y varias razones diferentes por las que querría hacerlo. El punto final que elija para llamar puede variar según el caso práctico.
Si necesita trabajar con una API, compruebe la siguiente imagen y la información correspondiente para ver cómo se extrae la información.
/oauth/v4/<tenantID>/token
- Tras una autenticación satisfactoria, recibe las señales de acceso y de identidad que contienen la información de usuario más común: un nombre, una imagen o un correo electrónico, por ejemplo. Si desea añadir información adicional, puede utilizar correlación de reclamaciones personalizadas para configurar App ID para inyectar la información en la señal antes de que ésta le sea devuelta.
/oauth/v4/<tenantID>/userinfo
- Si necesita ver una vista en profundidad de la información de perfil de usuario devuelta por un proveedor de identidad, puede llamar al
/userinfo
punto final. Se recomienda utilizar este punto final sólo si la información no se puede asignar al token, ya que requiere llamadas de red adicionales. /api/v1/attributes
- Si su aplicación requiere leer y actualizar los atributos de perfil personalizados para un usuario conectado actualmente, puede utilizar el punto final /attributes. Por ejemplo, el usuario desea actualizar una preferencia de comida.
/management/v4/<tenantID>/users
- Si está creando interfaces o procesos administrativos que se pueden aplicar a varios usuarios, puede utilizar la API de gestión de App ID. Concretamente, puede utilizar el punto final
/users
.
Las formas más sencillas de trabajar con la información de usuario son utilizando la GUI o un SDK. Con esas opciones, todas las llamadas de API se realizan en segundo plano para usted.
Acceso a atributos en tiempo de ejecución
Tras una autenticación de usuario satisfactoria, la app recibe señales de acceso e identidad de App ID. El servicio inyecta automáticamente un subconjunto de atributos en las señales de acceso y de identidad. Si la información no está en la señal, puede utilizar cualquiera de los siguientes puntos finales para buscarla.
Acceso al punto final /userinfo
Para ver la información acerca de los usuarios que proporcionan los proveedores de identidades que tiene configurados, puede acceder a sus atributos predefinidos.
-
Asegúrese de que tiene una señal de acceso válida con un alcance
openid
. Puede verificar que la señal es válida mediante el punto final/introspect
. -
Realice una solicitud al punto final
/userinfo
. Si las nuevas señales no se pasan de forma explícita al SDK, App ID utiliza las últimas señales recibidas para recuperar y validar la respuesta. Pasar una señal de identidad es opcional, pero se utiliza para validar la respuesta.GET https://<region>.appid.cloud.ibm.com/oauth/v4/<tenantID>/userinfo Authorization: 'Bearer <accessToken>'
// iOS Swift example AppID.sharedInstance.userProfileManager.getUserInfo(accessToken: String, identityToken: String?) { (error: Error?, userInfo: [String: Any]?) in guard let userInfo = userInfo, err == nil { return // an error has occurred } // retrieved user info successfully }
AppID appId = AppID.getInstance(); appId.getUserProfileManager().getUserInfo(accessToken, identityToken, new UserProfileResponseListener() { @Override public void onSuccess(JSONObject userInfo) { // retrieved attribute "name" successfully } @Override public void onFailure(UserInfoException e) { // exception occurred } });
let userProfileManager = UserProfileManager(options: options) let accessToken = req.session[WebAppStrategy.AUTH_CONTEXT].accessToken; let identityToken = req.session[WebAppStrategy.AUTH_CONTEXT].identityToken; // Retrieve user info and validate against the given identity token userProfileManager.getUserInfo(accessToken, identityToken).then(function (profile) { // retrieved user info successfully }); // Retrieve user info without validation userProfileManager.getUserInfo(accessToken).then(function (profile) { // retrieved user info successfully });
// Server-side Swift example let userProfileManager = UserProfileManager(options: options) let accessToken = "<accessToken>" let identityToken = "<identityToken>" // If identity token is provided (recommended approach), response is validated against the identity token userProfileManager.getUserInfo(accessToken: accessToken, identityToken: identityToken) { (err, userInfo) in guard let userInfo = userInfo, err == nil { return } } // Retrieve the UserInfo without any validation userProfileManager.getUserInfo(accessToken: accessToken) { (err, userInfo) in guard let userInfo = userInfo, err == nil { return } }
Salida de ejemplo:
"sub": "cad9f1d4-e23b-3683-b81b-d1c4c4fd7d4c", "name": "John Doe", "email": "john.doe@gmail.com", "picture": "https://lh3.googleusercontent.com/-XdUIqdbhg/AAAAAAAAI/AAAAAAA/42rbcbv5M/photo.jpg", "gender": "male", "locale": "en", "identities": [ { "provider": "google", "id": "104560903311317789798", "profile": { "id": "104560903311317789798", "email": "john.doe@gmail.com", "verified_email": true, "name": "John Doe", "given_name": "John", "family_name": "Doe", "link": "https://plus.google.com/104560903311317789798", "picture": "https://lh3.googleusercontent.com/-XdUIqdbhg/AAAAAAAAI/AAAAAAA/42rbcbv5M/photo.jpg", "gender": "male", "locale": "en", "idpType": "google" } } ]
-
Verifique que la reclamación
sub
coincida exactamente con la reclamaciónsub
en la señal de identidad. Si no coinciden, no utilice la información devuelta. Para obtener más información sobre la sustitución de tokens, consulte la especificación OIDC.
Si un proveedor de identidad externo hace algún cambio, puede obtener la información actualizada cuando el usuario vuelva a iniciar sesión. Las nuevas señales recuperan los datos más actualizados.
Acceso al punto final /attributes
En función de la configuración, los atributos se cifran y guardan como parte el perfil de usuario cuando este interactúa con la aplicación. La interacción podría ser, por ejemplo, un usuario iniciando sesión o estableciendo una preferencia en la app. Para acceder a los atributos, pase una señal de acceso a través de un método de API.
curl -X GET 'https://<region>.appid.cloud.ibm.com/api/v1/attributes'
-H 'Accept: application/json'
-H 'Authorization: Bearer <accessToken>'
//iOS Swift example
func setAttribute(key: String, value: String, completionHandler: @escaping(Error?, [String:Any]?) -> Void)
func setAttribute(key: String, value: String, accessTokenString: String, completionHandler: @escaping(Error?, [String:Any]?) -> Void)
func getAttribute(key: String, completionHandler: @escaping(Error?, [String:Any]?) -> Void)
func getAttribute(key: String, accessTokenString: String, completionHandler: @escaping(Error?, [String:Any]?) -> Void)
func getAttributes(completionHandler: @escaping(Error?, [String:Any]?) -> Void)
func getAttributes(accessTokenString: String, completionHandler: @escaping(Error?, [String:Any]?) -> Void)
func deleteAttribute(key: String, completionHandler: @escaping(Error?, [String:Any]?) -> Void)
func deleteAttribute(key: String, accessTokenString: String, completionHandler: @escaping(Error?, [String:Any]?) -> Void)
void setAttribute(@NonNull String name, @NonNull String value, UserAttributeResponseListener listener);
void setAttribute(@NonNull String name, @NonNull String value, @NonNull AccessToken accessToken, UserAttributeResponseListener listener);
void getAttribute(@NonNull String name, UserAttributeResponseListener listener);
void getAttribute(@NonNull String name, @NonNull AccessToken accessToken, UserAttributeResponseListener listener);
void deleteAttribute(@NonNull String name, UserAttributeResponseListener listener);
void deleteAttribute(@NonNull String name, @NonNull AccessToken accessToken, UserAttributeResponseListener listener);
void getAllAttributes(@NonNull UserAttributeResponseListener listener);
void getAllAttributes(@NonNull AccessToken accessToken, @NonNull UserAttributeResponseListener listener);
const userProfileManager = require("ibmcloud-appid").UserProfileManager;
userProfileManager.init();
var accessToken = req.session[WebAppStrategy.AUTH_CONTEXT].accessToken;
// get all attributes
userProfileManager.getAllAttributes(accessToken).then(function (attributes) {
});
// get single attribute
userProfileManager.getAttribute(accessToken, name).then(function (attributes) {
});
// set attribute value
userProfileManager.setAttribute(accessToken, name, value).then(function (attributes) {
});
// delete attribute
userProfileManager.deleteAttribute(accessToken, name).then(function () {
});
//Server-side Swift example
func getAllAttributes(accessToken: String, completionHandler: (Swift.Error?, [String: Any]?) -> Void)
func getAttribute(accessToken: String, attributeName: String, completionHandler: (Swift.Error?, [String: Any]?) -> Void)
func setAttribute(accessToken: String, attributeName: String, attributeValue : "abc", completionHandler: (Swift.Error?, [String: Any]?) -> Void)
func deleteAllAttributes(accessToken: String, completionHandler: (Swift.Error?, [String: Any]?) -> Void)
Establecer atributos personalizados
Puede añadir información sobre los usuarios en el perfil de los mismos, como por ejemplo un rol o una preferencia, estableciendo un atributo personalizado. Para establecer atributos personalizados antes de que un usuario inicie sesión en la aplicación, consulte Registro previo de futuros usuarios.
De forma predeterminada, es posible modificar y actualizar los atributos mediante la señal de acceso de App ID desde una aplicación de cliente. Sin tomar las precauciones adecuadas, el usuario o la aplicación pueden actualizar los atributos personalizados inmediatamente después del primer inicio de sesión del usuario, si tienen una señal de acceso. Hacerlo puede conducir posiblemente a consecuencias no deseadas. Por ejemplo, un usuario podría cambiar el rol de usuario a administrador, lo que podría exponer privilegios administrativos a usuarios malintencionados.
-
Vaya al separador Perfiles de usuario > Valores del panel de control de App ID.
-
Cambie los atributos personalizados a Habilitado.
-
Obtenga tokens de acceso e identidad con la API.
-
Obtenga el ID de arrendatario, el ID de cliente, el secreto y el URL de servidor OAuth de sus credenciales.
-
Codifique el ID de cliente y el secreto utilizando un codificador base64.
-
Utilice los siguientes ejemplos de código para recuperar las señales. El tipo de otorgamiento que utilice para obtener la señal puede diferir según el tipo de autorización con el que trabaje. Para obtener una lista detallada de opciones, consulte la documentación de swagger.
curl -X POST 'https://<region>.appid.cloud.ibm.com/oauth/v4/<tenantID>/token' \ -H 'Authorization: Basic base64Encoded{<clientID>:<clientSecret>}' \ -H 'Accept: application/json' \ -F 'grant_type=password' \ -F 'username=testuser@test.com' \ -F 'password=testuser'
// iOS Swift example class delegate : TokenResponseDelegate { public func onAuthorizationSuccess(accessToken: AccessToken?, identityToken: IdentityToken?, refreshToken: RefreshToken?, response:Response?) { //User authenticated } public func onAuthorizationFailure(error: AuthorizationError) { //Exception occurred } } AppID.sharedInstance.signinWithResourceOwnerPassword(username: username, password: password, delegate: delegate())
AppID.getInstance().signinWithResourceOwnerPassword(getApplicationContext(), username, password, new TokenResponseListener() { @Override public void onAuthorizationFailure (AuthorizationException exception) { //Exception occurred } @Override public void onAuthorizationSuccess (AccessToken accessToken, IdentityToken identityToken, RefreshToken refreshToken) { //User authenticated } });
// Declare the API you want to protect app.get("/api/protected", passport.authenticate(APIStrategy.STRATEGY_NAME, { session: false }), function(req, res) { // Get full appIdAuthorizationContext from request object var appIdAuthContext = req.appIdAuthorizationContext; appIdAuthContext.accessToken; // Raw access_token appIdAuthContext.accessTokenPayload; // Decoded access_token JSON appIdAuthContext.identityToken; // Raw identity_token appIdAuthContext.identityTokenPayload; // Decoded identity_token JSON appIdAuthContext.refreshToken; // Raw refresh_token ... } );
// Server-side swift example let options = [ "clientId": "<clientID>", "secret": "<secret>", "tenantId": "<tenantID>", "oauthServerUrl": "<oauthServerURL>", "redirectUri": "<appURL>" + CALLBACK_URL ] let webappKituraCredentialsPlugin = WebAppKituraCredentialsPlugin(options: options) let kituraCredentials = Credentials() kituraCredentials.register(plugin: webappKituraCredentialsPlugin)
-
-
Utilizando el punto final
attributes
, realice una solicitud PUT.curl -X PUT "https://<region>.appid.cloud.ibm.com/api/v1/attributes/<attributeName>" \ -H "Authorization: Bearer <token>" \ -d "<attributeValue>"
// iOS Swift example AppID.sharedInstance.userProfileManager?.setAttribute("key", "value") { (error, result) in guard let result = result, error == nil else { return // an error has occurred } // attributes recieved as a Dictionary })
appId.getUserProfileManager().setAttribute(name, value, useThisToken, new UserProfileResponseListener() { @Override public void onSuccess(JSONObject attributes) { // attributes received in JSON format on successful response } @Override public void onFailure(UserAttributesException e) { // exception occurred } });
const userProfileManager = require("ibmcloud-appid").UserProfileManager; userProfileManager.init(); var accessToken = req.session[WebAppStrategy.AUTH_CONTEXT].accessToken; userProfileManager.setAttribute(accessToken, name, value).then(function (attributes) { // attributes returned as dictionary });
// Server-side Swift let userProfileManager = UserProfileManager(options: options) let accesstoken = "access token" userProfileManager.setAttribute(accessToken: accessToken, attributeName: "name", attributeValue : "abc") { (error, response) in guard let response = response, error == error else { return // an error has occurred } // attributes received as a Dictionary }