Pseudo Users

Sometimes you do not want to force your application users to sign up with their usernames and passwords. Kii Cloud provides a "pseudo user" feature to accommodate such a need.

Using the pseudo user feature

A pseudo user is a feature to use a Kii Cloud user without a username and password. When a pseudo user is created, an access token is generated. A pseudo user is identified with an access token that is retained on the mobile app, instead of a pair of usernamne and password.

This feature will request a user creation without a username and password to Kii Cloud. When a pseudo user is created, Kii Cloud returns the access token for this user.

When a normal user logs in with its username and password, Kii Cloud issues an access token that indicates the user is logged in. The same effect is achieved when a pseudo user is created.

For a pseudo user, it is essential to keep the access token in the device's local storage until the user no longer needs it. When a user wants to login again, you can do so with the access token by following the steps described in Logging in and Using an Access Token. Please note that if the access token is lost, the user will no longer be able to login as the same user.

A pseudo user can leverage almost all Kii Cloud features like normal users; the only feature not achievable with a pseudo user is getting a new access token. This is because a pseudo user has no associated username and password and thus he cannot login with them so as to get his access token.

A pseudo user can become a normal user by registering his identifier (i.e. username, email address and/or phone number) and password. To allow a pseudo user to access from another device, for example, you might want to first ask the user to become a normal user and then ask him to login as a normal user from another device.

Creating a pseudo user

Here is an example of creating a pseudo user. In this example, the access token issued for the created pseudo user is saved in the device.

Swift:

  • // Set predefined fields and a custom field.
    let userFields = KiiUserFields()
    userFields.displayName = "Player 1"
    userFields.locale = LocaleContainer()
    userFields.setObject(NSNumber(value: 12000 as Int), forKey: "HighScore")
    
    do{
      // Register a pseudo user.
      let user = try KiiUser.registerAsPseudoUserSynchronous(with: userFields)
    
      // Save the access token.
      // If you want to encrypt the access token, store it in the keychain.
      UserDefaults.standard.set(user.accessToken, forKey: "token")
    }catch(let error as NSError){
      // Handle the error.
      return
    }
  • // Set predefined fields and a custom field.
    let userFields = KiiUserFields()
    userFields.displayName = "Player 1"
    userFields.locale = LocaleContainer()
    userFields.setObject(NSNumber(value: 12000 as Int), forKey: "HighScore")
    
    // Register a pseudo user.
    KiiUser.registerAsPseudoUser(with: userFields) { (user :KiiUser?, error : Error?) -> Void in
      if error != nil {
        // Handle the error.
        return
      }
    
      // Save the access token.
      // If you want to encrypt the access token, store it in the keychain.
      UserDefaults.standard.set(user!.accessToken, forKey: "token")
    }

Objective-C:

  • // Set predefined fields and a custom field.
    KiiUserFields *userFields = [[KiiUserFields alloc] init];
    [userFields setDisplayName:@"Player 1"];
    [userFields setLocale: [[LocaleContainer alloc] init]];
    [userFields setObject:@12000 forKey:@"HighScore"];
    
    NSError *error;
    
    // Register a pseudo user.
    KiiUser *user = [KiiUser registerAsPseudoUserSynchronousWithUserFields:userFields error:&error];
    if (error != nil) {
      // Handle the error.
      return;
    }
    
    // Save the access token.
    // If you want to encrypt the access token, store it in the keychain.
    [[NSUserDefaults standardUserDefaults] setObject:user.accessToken
                                              forKey:@"token"];
  • // Set predefined fields and a custom field.
    KiiUserFields *userFields = [[KiiUserFields alloc] init];
    [userFields setDisplayName:@"Player 1"];
    [userFields setLocale: [[LocaleContainer alloc] init]];
    [userFields setObject:@12000 forKey:@"HighScore"];
    
    // Register a pseudo user.
    [KiiUser registerAsPseudoUserWithUserFields:userFields block:^(KiiUser *user, NSError *error) {
      if (error != nil) {
        // Handle the error.
        return;
      }
    
      // Save the access token.
      // If you want to encrypt the access token, store it in the keychain.
      [[NSUserDefaults standardUserDefaults] setObject:user.accessToken
                                                forKey:@"token"];
    }];

Here is what is happening in the sample code:

  1. Defines a user attribute (optional).
  2. Executes the registerAsPseudoUserWithUserFields:block method to create and register a pseudo user.
  3. Gets the access token of the pseudo user from the KiiUser.accessToken property. Then saves this token in the device.

When a pseudo user is created, the user will be automatically logged in as the pseudo user; the user can use Kii Cloud just like a normal user.

Please note that a pseudo user will lose a mean to login if their access token is lost (e.g. by the application uninstallation). If you can identify the pseudo user, for example by their display name, you can delete this user on the User Console.

Logging in as a pseudo user

Since a pseudo user has no username or password, you need to log in with the access token, like the following example:

Swift:

  • do{
      // Get an access token.
      let token = UserDefaults.standard.string(forKey: "token")!
    
      // Authenticate a user with the access token.
      let user = try KiiUser.authenticate(withTokenSynchronous: token)
    }catch(let error as NSError){
      // Handle the error.
      return
    }
  • // Get an access token.
    let token = UserDefaults.standard.string(forKey: "token")!
    
    // Authenticate a user with the access token.
    KiiUser.authenticate(withToken: token) { (user :KiiUser?, error : Error?) -> Void in
      if error != nil {
        // Handle the error.
        return
      }
    }

Objective-C:

  • // Get an access token.
    NSString *token = [[NSUserDefaults standardUserDefaults] stringForKey:@"token"];
    
    NSError *error;
    
    // Authenticate a user with the access token.
    [KiiUser authenticateWithTokenSynchronous:token andError:&error];
    if (error != nil) {
      // Handle the error.
      return;
    }
  • // Get an access token.
    NSString *token = [[NSUserDefaults standardUserDefaults] stringForKey:@"token"];
    
    // Authenticate a user with the access token.
    [KiiUser authenticateWithToken:token
                          andBlock:^(KiiUser *user, NSError *error) {
      if (error != nil) {
        // Handle the error.
        return;
      }
    }];

Changing to a normal user

A pseudo user can be changed to a normal user by setting a username and a password.

Swift:

  • // Get the currently logged-in user.
    let user = KiiUser.current()!
    
    // If the current user is a pseudo user
    if !user.isPseudoUser {
      // Instantiate an IdentityData object.
      let builder = KiiIdentityDataBuilder()
      builder.userName = "user_123456"
      builder.email = "user_123456@example.com"
      builder.phoneNumber = "+819012345678"
      let identityData = builder.build()!
    
      // Set a predefined field and a custom field.
      let userFields = KiiUserFields()
      userFields.displayName = "Player 1"
      userFields.setObject(NSNumber(value: 0 as Int32), forKey: "HighScore")
    
      // Remove a custom field.
      userFields.removeFromServer(forKey: "app_flag")
    
      do{
        // Update the current pseudo user to a normal user.
        try user.putIdentityDataSynchronous(identityData, userFields: nil, password: "123ABC")
      } catch let error as NSError {
        // Handle the error.
        return
      }
    
    }
  • // Get the currently logged-in user.
    let user = KiiUser.current()!
    
    // If the current user is a pseudo user
    if !user.isPseudoUser {
      // Instantiate an IdentityData object.
      let builder = KiiIdentityDataBuilder()
      builder.userName = "user_123456"
      builder.email = "user_123456@example.com"
      builder.phoneNumber = "+819012345678"
      let identityData = builder.build()!
    
      // Set a predefined field and a custom field.
      let userFields = KiiUserFields()
      userFields.displayName = "Player 1"
      userFields.setObject(NSNumber(value: 0 as Int32), forKey: "HighScore")
    
      // Remove a custom field.
      userFields.removeFromServer(forKey: "app_flag")
    
      // Update the current pseudo user to a normal user.
      user.put(identityData, userFields: nil, password: "123ABC") { (user :KiiUser?, error : Error?) -> Void in
        if error != nil {
          // Handle the error.
          return
        }
      }
    }

Objective-C:

  • // Get the currently logged-in user.
    KiiUser *currentUser = [KiiUser currentUser];
    
    // If the current user is a pseudo user
    if (currentUser.isPseudoUser != NO) {
      // Instantiate an IdentityData object.
      KiiIdentityDataBuilder *builder = [[KiiIdentityDataBuilder alloc] init];
      builder.userName = @"user_123456";
      builder.email = @"user_123456@example.com";
      builder.phoneNumber = @"+819012345678";
      KiiIdentityData *identityData = [builder build];
    
      // Set a predefined field and a custom field.
      KiiUserFields *userFields = [[KiiUserFields alloc] init];
      [userFields setDisplayName:@"Player 1"];
      [userFields setObject:[NSNumber numberWithInt:0] forKey:@"HighScore"];
    
      // Remove a custom field.
      [userFields removeFromServerForKey:@"app_flag"];
    
      NSError *error;
    
      // Update the current pseudo user to a normal user.
      [currentUser putIdentityDataSynchronous:identityData userFields:nil password:@"123ABC" error:&error];
      if (error != nil) {
        // Handle the error.
        return;
      }
    }
  • // Get the currently logged-in user.
    KiiUser *currentUser = [KiiUser currentUser];
    
    // If the current user is a pseudo user
    if (currentUser.isPseudoUser != NO) {
      // Instantiate an IdentityData object.
      KiiIdentityDataBuilder *builder = [[KiiIdentityDataBuilder alloc] init];
      builder.userName = @"user_123456";
      builder.email = @"user_123456@example.com";
      builder.phoneNumber = @"+819012345678";
      KiiIdentityData *identityData = [builder build];
    
      // Set a predefined field and a custom field.
      KiiUserFields *userFields = [[KiiUserFields alloc] init];
      [userFields setDisplayName:@"Player 1"];
      [userFields setObject:[NSNumber numberWithInt:0] forKey:@"HighScore"];
    
      // Remove a custom field.
      [userFields removeFromServerForKey:@"app_flag"];
    
      // Update the current pseudo user to a normal user.
      [currentUser putIdentityData:identityData userFields:nil password:@"123ABC" block:^(KiiUser *user, NSError *error) {
        if (error != nil) {
          // Handle the error.
          return;
        }
      }];
    }

Here is what is happening in the sample code:

  1. Checks the [KiiUser currentUser].isPseudoUser property to see if the current user is a pseudo user.
  2. Creates a KiiIdentityDataBuilder instance.
  3. Sets a username, email address and phone number in the KiiIdentityDataBuilder instance.
  4. Executes the build method to create a KiiIdentityData instance.
  5. Executes the putIdentityData:userFields:password:block method with the KiiIdentityData and password.

With the above steps, a pseudo user becomes a normal user. The user will be able to authenticate and get the access token with the username and password from that point forward.

Using Kii Cloud without explicit login

Besides using the pseudo user feature, you can use the following methods to use Kii Cloud without explicit login. Kii recommends using the pseudo user feature because these methods can make the implementation complex or limited.

Creating a user in the mobile app

Your application can automatically create arbitrary username and password, register them to Kii Cloud on behalf of the user and use them every time the user tries to use your mobile app. For example, your mobile app can create a random username and password in background, use them to proceed with the user sign up & sign in, and then store them in the device storage (e.g., SharedPreference on Android and NSUserDefaults on iOS). The user will be able to automatically log in with these username and password until the mobile app is uninstalled or the stored data is explicitly erased.

In this method, your mobile app must assign a unique username to each user.

Once the username and password are erased from the device storage, the user will no longer be able to sign in. Using an immutable value like a device ID for the username and/or password, however, is strongly discouraged so as to prevent the possible privacy infringement.

To provide a support for device migration or back up, simply implement the export and import feature of the username and password stored in the device storage.

Anonymous user

Kii Cloud does support an anonymous user (i.e., a user without any sign in), but the features allowed to the anonymous user are very limited. Most features, like accessing a user-scope data, require the user to sign in.