Armazenando e acessando atributos
Com o IBM Cloud® App ID, é possível compilar informações sobre os usuários individuais de seu aplicativo em um perfil. As informações no perfil podem ser aprendidas sobre seus usuários pela maneira como eles interagem com seu app ou incluídas por você em seu nome. Ao armazenar as informações, é possível acessá-la para ajudar a criar experiências personalizadas de seu app para seus usuários.
Entendendo perfis
Um perfil de usuário são todas as informações conhecidas sobre um usuário específico, compiladas em um objeto JSON e armazenadas pelo App ID. Há dois tipos de informações ou atributos que podem ser obtidos e armazenados em um perfil: predefined e custom. Os atributos predefinidos são específicos para a identidade de seu usuário e são retornados por um provedor de identidade quando seu usuário se conecta ao seu aplicativo e podem incluir informações como seu nome ou idade.
Os atributos customizados são usados para armazenar informações adicionais sobre seus usuários. Elas podem ser configuradas por você ou aprendidas sobre o usuário à medida que ele interage com seu app. Os atributos customizados podem incluir
uma função designada, uma preferência alimentar ou um assento de corredor preferencial em um avião.
É possível armazenar até 100 KB de informações para cada usuário.
Como obtenho as informações do perfil do usuário?
Há várias maneiras diferentes nas quais é possível acessar informações do usuário, e várias razões diferentes por que você desejaria. O terminal que você escolhe para chamar pode variar dependendo de seu caso de uso.
Se você precisar trabalhar com uma API, confira a imagem a seguir e as informações correspondentes para ver como as informações são extraídas.
/oauth/v4/<tenantID>/token- Após uma autenticação bem-sucedida, você recebe tokens de acesso e identidade que contêm as informações sobre o usuário mais comuns: um nome, uma figura ou um e-mail, por exemplo. Se desejar incluir informações adicionais, será possível usar o mapeamento de solicitações customizadas para configurar o App ID para injetar as informações no token antes que ele seja retornado a você.
/oauth/v4/<tenantID>/userinfo- Se precisar de uma visão detalhada das informações do perfil do usuário retornadas por um provedor de identidade, você poderá chamar o endpoint
/userinfo. Recomenda-se usar esse ponto de extremidade somente se as informações não puderem ser mapeadas para o token, pois isso exige chamadas de rede adicionais. /api/v1/attributes- Se o seu aplicativo requerer a leitura e a atualização de atributos de perfil customizado para um usuário atualmente com login efetuado, será possível usar o terminal /attributes. Por exemplo, o usuário deseja atualizar uma preferência alimentar.
/management/v4/<tenantID>/users- Se você estiver desenvolvendo interfaces ou processos administrativos que podem se aplicar a múltiplos usuários, será possível usar a API de gerenciamento do App ID. Especificamente, é possível usar o terminal
/users.
As maneiras mais fáceis de trabalhar com informações sobre o usuário são usando a GUI ou um SDK. Com essas opções, todas as chamadas de API são feitas nos bastidores para você.
Acessando atributos no tempo de execução
Após a autenticação bem-sucedida do usuário, seu app recebe tokens de acesso e de identidade do App ID. O serviço injeta automaticamente um subconjunto de atributos em seus tokens de acesso e identidade. Se as informações não estiverem no token, será possível usar qualquer um dos terminais a seguir para localizar as informações.
Acessando o terminal /userinfo
Para ver as informações sobre seus usuários que são fornecidos por seus provedores de identidade configurados, é possível acessar seus atributos predefinidos.
-
Certifique-se de que você tenha um token de acesso válido com um escopo
openid. É possível verificar seo token é válido usando o terminal/introspect. -
Faça uma solicitação para o ponto de extremidade
/userinfo. Se novos tokens não forem passados explicitamente para o SDK, o App ID usará os tokens recebidos pela última vez para recuperar e validar a resposta. A passagem de um token de identidade é opcional, mas, quando passado, ele é usado para validar a resposta.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 } }Saída de exemplo:
"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 se a solicitação
subcorresponde exatamente à solicitaçãosubno token de identidade. Se elas não corresponderem, não use as informações retornadas. Para saber mais sobre a substituição de tokens, consulte a especificação OIDC.
Se as mudanças forem feitas por um provedor de identidade externo, você poderá obter as informações atualizadas quando osusuários efetuarem login novamente. Os novos tokens recuperam os dados mais atualizados.
Acessando o terminal /attributes
Dependendo de sua configuração, os atributos são criptografados e salvos como parte de um perfil do usuário quando um usuário interage com seu aplicativo. A interação pode ser um usuário se conectando ou configurando uma preferência em seu app. Para acessar os atributos, passe um token de acesso por meio de um 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)
Configurando atributos customizados
É possível incluir informações sobre seus usuários em seu perfil, como uma função ou uma preferência, configurando um atributo customizado. Para configurar atributos customizados antes que um usuário se conecte ao seu aplicativo, consulte Pré-registrando usuários futuros.
Por padrão, os atributos customizados são modificáveis e podem ser atualizados usando um token de acesso do App ID por meio de um aplicativo cliente. Sem tomar as devidas precauções, o usuário ou o aplicativo pode atualizar atributos customizados imediatamente após a primeira conexão do usuário, se eles tiverem um token de acesso. Fazer isso pode potencialmente levar a consequências indesejadas. Por exemplo, um usuário pode mudar sua função de usuário para administrador, o que pode expor privilégios administrativos a usuários maliciosos.
-
Acesse a guia Perfis do usuário > Configurações do painel do App ID.
-
Alterne atributos customizados para Ativado.
-
Obter tokens de acesso e identidade com a API.
-
Obtenha seu ID de locatário, ID de cliente, segredo e URL do OAuth Server por meio de suas credenciais.
-
Codifique o seu ID e segredo do cliente usando um codificador base64.
-
Use os exemplos de código a seguir para recuperar seus tokens. O tipo de concessão que você usa para obter o seu token pode diferir dependendo do tipo de autorização com a qual você está trabalhando. Para obter uma lista detalhada de opções, consulte a documentação do 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)
-
-
Usando o terminal
attributes, faça uma solicitação de 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 }