Memorizzazione e accesso agli attributi

Con IBM Cloud® App ID, puoi compilare le informazioni sui singoli utenti della tua applicazione in un profilo. Le informazioni nel profilo possono essere apprese sui tuoi utenti dal modo in cui interagiscono con la tua applicazione o aggiunte da te per loro conto. Archiviando le informazioni, puoi accedere a esse per facilitare la creazione di esperienze personalizzate della tua applicazione per i tuoi utenti.

Descrizione dei profili

Un profilo utente è costituito da tutte le informazioni conosciute su uno specifico utente, compilate in un oggetto JSON e memorizzate da App ID. Esistono due tipi di informazioni, o attributi, che possono essere ottenuti e archiviati in un profilo: predefiniti (predefined) e personalizzati (custom). Gli attributi predefiniti sono specifici per l'identità del tuo utente e sono restituiti da un provider di identità quando il tuo utente accede alla tua applicazione e possono includere delle informazioni come nome o età. Gli attributi personalizzati sono utilizzati per archiviare ulteriori informazioni sui tuoi utenti. Li puoi impostare tu stesso oppure vengono acquisiti quando l'utente interagisce con la tua applicazione. Gli attributi personalizzati possono includere un ruolo assegnato, una preferenza alimentare o una preferenza di posto lato corridoio su un aeroplano.

caption-side=bottom"
App ID profili utente Flusso di informazioni sul profilo utente

Puoi archiviare fino a 100 KB di informazioni per ciascun utente.

Come ottengo le informazioni sul profilo utente?

Esistono diversi modi in cui si possono accedere alle informazioni degli utenti e diverse ragioni per cui si vorrebbe. L'endpoint che scegli di richiamare può variare a seconda del tuo caso d'uso.

Se hai bisogno di lavorare con un'API, controlla la seguente immagine e le informazioni corrispondenti per vedere come vengono estratte le informazioni.

caption-side=bottom"
App ID opzioni endpoint del profilo utente Opzioni endpoint che possono essere utilizzate per accedere alle informazioni dell'utente

/oauth/v4/<tenantID>/token
Dopo un'autenticazione eseguita correttamente, ricevi token di accesso e identità che contengono le informazioni utente più comuni, ad esempio un nome, un'immagine o una email. Se vuoi aggiungere ulteriori informazioni, puoi utilizzare l' associazione delle attestazioni personalizzate per configurare App ID per inserire informazioni nel token prima che ti venga restituito.
/oauth/v4/<tenantID>/userinfo
Se si vuole vedere una visione approfondita delle informazioni sul profilo dell'utente restituite da un fornitore di identità, si può chiamare l'endpoint /userinfo. Si consiglia di utilizzare questo endpoint solo se le informazioni non possono essere mappate sul token, poiché richiede ulteriori chiamate di rete.
/api/v1/attributes
Se la tua applicazione richiede la lettura e l'aggiornamento degli attributi di profilo personalizzati per un utente attualmente collegato, puoi utilizzare l'endpoint /attributes. Ad esempio, l'utente desidera aggiornare una preferenza alimentare.
/management/v4/<tenantID>/users
Se stai creando interfacce o processi amministrativi che potrebbero applicarsi a più utenti, puoi utilizzare l'API di gestione App ID. In particolare, è possibile utilizzare l'endpoint /users.

I modi più facili per lavorare con le informazioni utente sono utilizzando la GUI o un SDK. Con queste opzioni, tutte le chiamate API vengono effettuate dietro le quinte per voi.

Accesso agli attributi in fase di esecuzione

Dopo una corretta autenticazione utente, la tua applicazione riceve i token di accesso e identità da App ID. Il servizio inserisce automaticamente un sottoinsieme di attributi nei tuoi token di accesso e identità. Se le informazioni non sono presenti nel token, puoi utilizzare uno qualsiasi dei seguenti endpoint per trovare le informazioni.

Accesso all'endpoint /userinfo

Per visualizzare le informazioni sui tuoi utenti fornite dai tuoi provider di identità configurati, puoi accedere ai tuoi attributi predefiniti.

  1. Assicurarti di disporre di un token di accesso valido con un ambito openid. Puoi verificare che il token è valido utilizzando l'endpoint /introspect.

  2. Effettuare una richiesta all'endpoint /userinfo. Se i nuovi token non vengono inoltrati esplicitamente al SDK, App ID utilizza gli ultimi token ricevuti per richiamare e convalidare la risposta. Passare un token di identità è facoltativo, ma superato viene utilizzato per convalidare la risposta.

    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
       }
    }
    

    Output di esempio:

    "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"
             }
       }
    ]
    
  3. Verificare che l'attestazione sub corrisponda esattamente all'attestazione sub nel token di identità. Se non corrispondono, non utilizzare le informazioni restituite. Per saperne di più sulla sostituzione dei token, consultare le specifiche OIDC.

Se le modifiche vengono apportate da un provider di identità esterno, puoi ottenere le informazioni aggiornate quando gli utenti accedono nuovamente. I tuoi nuovi token richiamano i dati più aggiornati.

Accesso all'endpoint /attributes

A seconda della tua configurazione, gli attributi sono codificati e salvati come parte di un profilo utente quando un utente interagisce con la tua applicazione. L'interazione può essere un utente che esegue l'accesso o l'impostazione di una preferenza nella tua applicazione. Per accedere agli attributi, passa un token di accesso tramite un metodo 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)

Configurazione degli attributi personalizzati

Puoi aggiungere delle informazioni sui tuoi utenti nel loro profilo, ad esempio un ruolo o una preferenza, configurando un attributo personalizzato. Per impostare gli attributi personalizzati prima che un utente esegua la registrazione alla tua applicazione, vedi Preregistrazione degli utenti futuri.

Per impostazione predefinita, gli attributi personalizzati sono modificabili e possono essere aggiornati utilizzando un token di accesso App ID da un'applicazione client. Senza le dovute precauzioni, l'utente o l'applicazione possono aggiornare gli attributi personalizzati subito dopo il primo accesso dell'utente, se dispongono di un token di accesso. Ciò può potenzialmente portare a conseguenze indesiderate. Ad esempio, un utente potrebbe modificare il suo ruolo da utente ad amministratore e questo potrebbe esporre i privilegi di amministrazione a utenti malintenzionati.

  1. Vai alla scheda User profiles > Settings del dashboard App ID.

  2. Modifica gli attributi personalizzati in modo che siano impostati su Enabled.

  3. Ottenere l'accesso e i token di identità con l'API.

    1. Ottieni l'ID tenant, l'ID client, il segreto e l'URL del server OAuth dalle tue credenziali.

    2. Codificare il proprio ID client e segreto utilizzando un encoder base64.

    3. Utilizzare i seguenti esempi di codice per richiamare i token. Il tipo di concessione utilizzato per ottenere il token può variare a seconda del tipo di autorizzazione con cui si lavora. Per un elenco dettagliato delle opzioni, consultare il sito documentazione 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)
      
  4. Utilizzando l'endpoint attributes, effettua una richiesta 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
    }