> ## Documentation Index
> Fetch the complete documentation index at: https://developer.box.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Find or create Box app users

export const ProgressBar = ({pages = [], ...props}) => {
  const [currentStep, setCurrentStep] = useState(0);
  const [isDarkMode, setIsDarkMode] = useState(false);
  useEffect(() => {
    const checkDarkMode = () => {
      const isDark = document.documentElement.classList.contains('dark');
      console.log('ProgressBar - isDarkMode:', isDark);
      setIsDarkMode(isDark);
    };
    checkDarkMode();
    const observer = new MutationObserver(() => {
      checkDarkMode();
    });
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ['class']
    });
    return () => {
      observer.disconnect();
    };
  }, []);
  useEffect(() => {
    if (pages.length > 0) {
      const currentPath = window.location.pathname;
      const stepIndex = pages.findIndex(page => {
        const pagePath = page.startsWith('/') ? page : `/${page}`;
        return currentPath.endsWith(pagePath) || currentPath.includes(pagePath);
      });
      if (stepIndex !== -1) {
        setCurrentStep(stepIndex + 1);
      }
    }
  }, [pages]);
  if (!pages || pages.length === 0) {
    return null;
  }
  const step = currentStep;
  const total = pages.length;
  console.log('ProgressBar - Rendering with isDarkMode:', isDarkMode);
  const progressBarContainerStyle = {
    width: '100%',
    marginBottom: '32px',
    display: 'flex',
    alignItems: 'center',
    gap: '16px'
  };
  const stepsContainerStyle = {
    display: 'flex',
    alignItems: 'center',
    gap: '8px',
    flexShrink: 0
  };
  const progressBarTrackStyle = {
    flex: 1,
    height: '22px',
    backgroundColor: 'rgba(169, 210, 244, 0.06)',
    border: isDarkMode ? '1px solid rgba(230, 241, 247, 0.67)' : '1px solid #e3ecf3',
    borderRadius: '4px',
    overflow: 'hidden',
    position: 'relative'
  };
  const progressBarFillStyle = {
    height: '100%',
    backgroundColor: 'rgba(113, 192, 248, 0.23)',
    width: `${step / total * 100}%`,
    transition: 'width 0.3s ease'
  };
  const getStepStyle = (stepNumber, isActive) => {
    if (isDarkMode) {
      return {
        width: '22px',
        height: '22px',
        borderRadius: '4px',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        fontSize: '12px',
        fontWeight: '600',
        position: 'relative',
        zIndex: 1,
        transition: 'all 0.3s ease',
        backgroundColor: isActive ? 'rgba(113, 192, 248, 0.23)' : 'transparent',
        color: isActive ? '#60a5fa' : '#a0aec0',
        border: isActive ? '1px solid #e3ecf3' : '1px solid #e0e6eb',
        cursor: 'pointer',
        textDecoration: 'none'
      };
    }
    if (isActive) {
      return {
        width: '22px',
        height: '22px',
        borderRadius: '4px',
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        fontSize: '12px',
        fontWeight: '600',
        position: 'relative',
        zIndex: 1,
        transition: 'all 0.3s ease',
        backgroundColor: 'rgba(169, 210, 244, 0.32)',
        color: '#374151',
        border: '1px solid #e1eef8',
        cursor: 'pointer',
        textDecoration: 'none'
      };
    }
    return {
      width: '22px',
      height: '22px',
      borderRadius: '4px',
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
      fontSize: '12px',
      fontWeight: '600',
      position: 'relative',
      zIndex: 1,
      transition: 'all 0.3s ease',
      backgroundColor: '#fbfbfb',
      color: '#9ca3af',
      border: '1px solid #e3ecf3',
      cursor: 'pointer',
      textDecoration: 'none'
    };
  };
  return <div style={progressBarContainerStyle} {...props}>
      <div style={stepsContainerStyle}>
        {Array.from({
    length: total
  }, (_, index) => {
    const stepNumber = index + 1;
    const pageIndex = index;
    const pagePath = pages[pageIndex];
    const fullPath = pagePath.startsWith('/') ? pagePath : `/${pagePath}`;
    const isActive = stepNumber === step;
    return <a key={stepNumber} href={fullPath} style={getStepStyle(stepNumber, isActive)}>
              {stepNumber}
            </a>;
  })}
      </div>
      <div style={progressBarTrackStyle}>
        <div style={progressBarFillStyle}></div>
      </div>
    </div>;
};

export const Link = ({href, children, className, ...props}) => {
  const localizedHref = href;
  return <a href={localizedHref} className={className} {...props}>
      {children}
    </a>;
};

export const ChoiceDebug = ({option}) => {
  const [currentValue, setCurrentValue] = useState(null);
  const [allState, setAllState] = useState({});
  const [isDarkMode, setIsDarkMode] = useState(false);
  useEffect(() => {
    const updateState = () => {
      if (window.choiceStateManager) {
        setCurrentValue(window.choiceStateManager.getValue(option));
        setAllState(window.choiceStateManager.getState());
      }
    };
    updateState();
    const unsubscribe = window.listenToChoice?.(option, updateState) || (() => {});
    const handleGlobalUpdate = () => updateState();
    window.addEventListener("choiceStateUpdate", handleGlobalUpdate);
    return () => {
      unsubscribe();
      window.removeEventListener("choiceStateUpdate", handleGlobalUpdate);
    };
  }, [option]);
  useEffect(() => {
    const checkDarkMode = () => {
      if (document.documentElement.classList.contains("dark")) {
        setIsDarkMode(true);
      } else if (document.documentElement.classList.contains("light")) {
        setIsDarkMode(false);
      } else {
        setIsDarkMode(window.matchMedia("(prefers-color-scheme: dark)").matches);
      }
    };
    checkDarkMode();
    const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
    const handleMediaChange = e => {
      if (!document.documentElement.classList.contains("dark") && !document.documentElement.classList.contains("light")) {
        setIsDarkMode(e.matches);
      }
    };
    mediaQuery.addEventListener("change", handleMediaChange);
    const observer = new MutationObserver(() => {
      checkDarkMode();
    });
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ["class"]
    });
    return () => {
      mediaQuery.removeEventListener("change", handleMediaChange);
      observer.disconnect();
    };
  }, []);
  return <div style={{
    padding: "10px",
    backgroundColor: isDarkMode ? "#2d3748" : "#f5f5f5",
    border: isDarkMode ? "1px solid #4a5568" : "1px solid #ddd",
    borderRadius: "4px",
    fontSize: "12px",
    fontFamily: "monospace",
    marginTop: "20px",
    color: isDarkMode ? "#e2e8f0" : "inherit"
  }}>
      <strong>Choice Debug:</strong>
      <br />
      Option: {option}
      <br />
      Current Value: {currentValue || "undefined"}
      <br />
      All State: {JSON.stringify(allState, null, 2)}
    </div>;
};

export const Observe = ({option, value, children, ...props}) => {
  const [shouldShow, setShouldShow] = useState(false);
  useEffect(() => {
    const updateVisibility = () => {
      const matches = window.matchesChoiceValues?.(option, value) || false;
      setShouldShow(matches);
    };
    updateVisibility();
    const unsubscribe = window.listenToChoice?.(option, updateVisibility) || (() => {});
    return unsubscribe;
  }, [option, value]);
  if (!shouldShow) {
    return null;
  }
  return <div {...props}>{children}</div>;
};

export const Trigger = ({option, value, children, ...props}) => {
  const handleClick = () => {
    window.triggerChoice?.(option, value);
  };
  return <div onClick={handleClick} style={{
    cursor: "pointer"
  }} {...props}>
      {children}
    </div>;
};

export const Grid = ({columns = 2, compact = false, children, ...props}) => {
  const gridStyles = {
    display: "grid",
    gridTemplateColumns: `repeat(${columns}, 1fr)`,
    gap: compact ? "8px" : "16px",
    marginBottom: compact ? "10px" : "20px"
  };
  return <div style={gridStyles} {...props}>
      {children}
    </div>;
};

export const Choice = ({option, value, color = "", unset = false, lazy = false, children, ...props}) => {
  const [shouldShow, setShouldShow] = useState(false);
  const [hasEverShown, setHasEverShown] = useState(false);
  const [isDarkMode, setIsDarkMode] = useState(false);
  useEffect(() => {
    const updateVisibility = () => {
      const hasOptionValue = window.hasChoiceValue?.(option) || false;
      const matchesValue = window.matchesChoiceValues?.(option, value) || false;
      let show = false;
      if (unset && !hasOptionValue) {
        show = true;
      } else if (!unset && matchesValue) {
        show = true;
      }
      setShouldShow(show);
      if (show && !hasEverShown) {
        setHasEverShown(true);
      }
    };
    updateVisibility();
    const unsubscribe = window.listenToChoice?.(option, updateVisibility) || (() => {});
    return unsubscribe;
  }, [option, value, unset, hasEverShown]);
  useEffect(() => {
    const checkDarkMode = () => {
      if (document.documentElement.classList.contains("dark")) {
        setIsDarkMode(true);
      } else if (document.documentElement.classList.contains("light")) {
        setIsDarkMode(false);
      } else {
        setIsDarkMode(window.matchMedia("(prefers-color-scheme: dark)").matches);
      }
    };
    checkDarkMode();
    const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
    const handleMediaChange = e => {
      if (!document.documentElement.classList.contains("dark") && !document.documentElement.classList.contains("light")) {
        setIsDarkMode(e.matches);
      }
    };
    mediaQuery.addEventListener("change", handleMediaChange);
    const observer = new MutationObserver(() => {
      checkDarkMode();
    });
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ["class"]
    });
    return () => {
      mediaQuery.removeEventListener("change", handleMediaChange);
      observer.disconnect();
    };
  }, []);
  const getColorStyles = () => {
    const baseStyles = {
      border: isDarkMode ? "1px dashed #4a5568" : "1px dashed #e1e5e9",
      padding: "20px",
      marginBottom: "20px",
      borderRadius: "8px",
      backgroundColor: isDarkMode ? "#1a202c" : "#ffffff"
    };
    const colorMap = {
      green: {
        light: {
          backgroundColor: "#d4edda",
          borderColor: "#28a745"
        },
        dark: {
          backgroundColor: "#1a3a2a",
          borderColor: "#66bb6a"
        }
      },
      red: {
        light: {
          backgroundColor: "#f8d7da",
          borderColor: "#dc3545"
        },
        dark: {
          backgroundColor: "#3a1a1a",
          borderColor: "#ef5350"
        }
      },
      blue: {
        light: {
          backgroundColor: "#d1ecf1",
          borderColor: "#0c5460"
        },
        dark: {
          backgroundColor: "#1a2a3a",
          borderColor: "#42a5f5"
        }
      },
      none: {
        backgroundColor: "transparent",
        padding: "0",
        margin: "0",
        border: "none"
      }
    };
    const colorStyles = color !== "none" ? colorMap[color]?.[isDarkMode ? "dark" : "light"] || ({}) : colorMap.none;
    return {
      ...baseStyles,
      ...colorStyles
    };
  };
  if (lazy && !hasEverShown && !shouldShow) {
    return null;
  }
  return <div style={{
    ...getColorStyles(),
    display: shouldShow ? "block" : "none"
  }} className="choice-content" {...props}>
      {children}
    </div>;
};

export const Choose = ({option, value, color = "", children, ...props}) => {
  const [isSelected, setIsSelected] = useState(false);
  const [hasOptionTriggered, setHasOptionTriggered] = useState(false);
  const [isDarkMode, setIsDarkMode] = useState(false);
  useEffect(() => {
    const currentValue = window.getChoiceValue?.(option);
    const optionTriggered = window.hasChoiceValue?.(option) || false;
    setIsSelected(currentValue === value);
    setHasOptionTriggered(optionTriggered);
    const unsubscribe = window.listenToChoice?.(option, newValue => {
      setIsSelected(newValue === value);
      setHasOptionTriggered(true);
    }) || (() => {});
    return unsubscribe;
  }, [option, value]);
  useEffect(() => {
    const checkDarkMode = () => {
      if (document.documentElement.classList.contains("dark")) {
        setIsDarkMode(true);
      } else if (document.documentElement.classList.contains("light")) {
        setIsDarkMode(false);
      } else {
        setIsDarkMode(window.matchMedia("(prefers-color-scheme: dark)").matches);
      }
    };
    checkDarkMode();
    const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
    const handleMediaChange = e => {
      if (!document.documentElement.classList.contains("dark") && !document.documentElement.classList.contains("light")) {
        setIsDarkMode(e.matches);
      }
    };
    mediaQuery.addEventListener("change", handleMediaChange);
    const observer = new MutationObserver(() => {
      checkDarkMode();
    });
    observer.observe(document.documentElement, {
      attributes: true,
      attributeFilter: ["class"]
    });
    return () => {
      mediaQuery.removeEventListener("change", handleMediaChange);
      observer.disconnect();
    };
  }, []);
  const handleClick = () => {
    window.triggerChoice?.(option, value);
  };
  const handleKeyDown = e => {
    if (e.key === "Enter" || e.key === " ") {
      e.preventDefault();
      handleClick();
    }
  };
  const getColorStyles = () => {
    const baseStyles = {
      border: isDarkMode ? "1px dashed #4a5568" : "1px dashed #e1e5e9",
      cursor: "pointer",
      padding: "20px",
      position: "relative",
      backgroundColor: isDarkMode ? "#2d3748" : "#f8f9fa",
      outline: "none",
      height: "100%",
      borderRadius: "8px",
      transition: "all 0.2s ease",
      display: "flex",
      flexDirection: "column"
    };
    const colorMap = {
      green: {
        light: {
          backgroundColor: "#d4edda",
          borderColor: "#28a745"
        },
        dark: {
          backgroundColor: "#1a3a2a",
          borderColor: "#66bb6a"
        }
      },
      red: {
        light: {
          backgroundColor: "#f8d7da",
          borderColor: "#dc3545"
        },
        dark: {
          backgroundColor: "#3a1a1a",
          borderColor: "#ef5350"
        }
      },
      blue: {
        light: {
          backgroundColor: "#d1ecf1",
          borderColor: "#0c5460"
        },
        dark: {
          backgroundColor: "#1a2a3a",
          borderColor: "#42a5f5"
        }
      }
    };
    const colorStyles = colorMap[color]?.[isDarkMode ? "dark" : "light"] || ({});
    if (isSelected) {
      return {
        ...baseStyles,
        ...colorStyles,
        borderStyle: "solid",
        borderWidth: "3px",
        borderColor: colorStyles.borderColor || (isDarkMode ? "#42a5f5" : "#0061d5"),
        backgroundColor: colorStyles.backgroundColor || (isDarkMode ? "#1a2a3a" : "#e3f2fd"),
        boxShadow: isDarkMode ? "0 2px 8px rgba(66, 165, 245, 0.3)" : "0 2px 8px rgba(0, 97, 213, 0.3)",
        transform: "scale(1.02)"
      };
    }
    if (hasOptionTriggered && !isSelected) {
      return {
        ...baseStyles,
        ...colorStyles,
        opacity: 0.5
      };
    }
    return {
      ...baseStyles,
      ...colorStyles
    };
  };
  const iconStyles = {
    float: "left",
    position: "relative",
    top: "2px",
    marginRight: "12px",
    width: "20px",
    height: "20px",
    color: isSelected ? isDarkMode ? "#42a5f5" : "#0061d5" : isDarkMode ? "#a0aec0" : "#666"
  };
  return <div onClick={handleClick} style={getColorStyles()} tabIndex={0} onKeyDown={handleKeyDown} {...props}>
      <div style={iconStyles}>
        {isSelected ? <svg viewBox="0 0 24 24" fill="currentColor" style={{
    width: "100%",
    height: "100%"
  }}>
            <path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z" />
          </svg> : <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" style={{
    width: "100%",
    height: "100%"
  }}>
            <circle cx="12" cy="12" r="10" />
          </svg>}
      </div>
      <div style={{
    flex: 1
  }} className="choose-content">
        {children}
      </div>
    </div>;
};

<ProgressBar
  pages={[
                      "guides/sso-identities-and-app-users/connect-okta-to-app-users/scaffold-application-code",
                      "guides/sso-identities-and-app-users/connect-okta-to-app-users/configure-okta",
                      "guides/sso-identities-and-app-users/connect-okta-to-app-users/configure-box",
                      "guides/sso-identities-and-app-users/connect-okta-to-app-users/logging-into-app",
                      "guides/sso-identities-and-app-users/connect-okta-to-app-users/find-or-create-box-users",
                      "guides/sso-identities-and-app-users/connect-okta-to-app-users/run-the-app"
                    ]}
/>

At this point we have application code that will handle traffic from users
visiting, forward them to Okta to login, provide Okta user information, before
finally handing off to a yet to be created handler for Box.

This section will cover the final Box components:

* Validating if an Okta user has an associated Box app user account.
* Creating a new app user for the associated Okta record if they don't.
* Fetching tokens for the Box user to make user-specific API calls.

## Create Platform App Users

Before validating users we need a method for creating an associated Box user
account if one doesn't already exist for the Okta user.

<Choice option="programming.platform" value="node" color="none">
  In your local application directory, load the `server.js` file created in
  step 1.

  Add the following `box` object into the file and save.

  ```js theme={null}
  const box = (() => {
      const configJSON = JSON.parse(fs.readFileSync(path.resolve(__dirname, './config.json')));
      const sdk = boxSDK.getPreconfiguredInstance(configJSON);
      const client = sdk.getAppAuthClient('enterprise');

      let oktaRecord = {};
      let userId = '';
      let userClient;

      function validateUser(userInfo, res) {
          // TODO: VALIDATE USER
      }

      function createUser(res) {
          // TODO: CREATE USER
      }

      return {
          validateUser,
          createUser
      };
  })();
  ```

  This object defines a number of items:

  * Configuration: A new instance of the Box Node SDK is instantiated and made available to the object functions, along with a number of variables.
  * `validateUser` function: Will house the code to validate whether a Box user exists for an associated Okta user.
  * `createUser` function: Creates a new Box user bound to the associated Okta user ID.

  With that structure defined, replace the `// TODO: CREATE USER` section with
  the following code.

  ```js theme={null}
  const spaceAmount = 1073741824;   // ~ 1gb

  client.enterprise.addAppUser(
      this.oktaRecord.name,
      {
        space_amount: spaceAmount,
        external_app_user_id: this.oktaRecord.sub
      }
  ).then(appUser => {
      res.send(`New user created: ${appUser.name}`);
  });
  ```

  This code will create a new Box app user and will set the
  `external_app_user_id` parameter of the user object to the unique Okta user ID,
  which will define the binding between the two user records.
</Choice>

<Choice option="programming.platform" value="java" color="none">
  In your local application directory, load the
  `/src/main/java/com/box/sample/Application.java` file created in step 1, or
  similar directory if an alternate application name was used.

  Within the `public class Application` definition, add the following methods:

  ```java theme={null}
  static String validateUser(OidcUser user) throws IOException {
      // TODO: VALIDATE USER
  }

  static String createUser(OidcUser user) {
      // TODO: CREATE USER
  }
  ```

  These methods will handle the Box user validation and creation. Breaking them
  down:

  * `validateUser`: Will house the code to validate whether a Box user exists for an associated Okta user.
  * `createUser`: Creates a new Box user bound to the associated Okta user ID.

  With those methods defined, replace `# TODO: CREATE USER` with the following
  code:

  ```java theme={null}
  String oktaName = (String) user.getAttributes().get("name");
  Object oktaSub = user.getAttributes().get("sub");

  CreateUserParams params = new CreateUserParams();
  params.setExternalAppUserId((String) oktaSub);
  BoxUser.Info createdUserInfo = BoxUser.createAppUser(api, oktaName, params);

  return "New User Created: " + createdUserInfo.getName();
  ```

  This code will create a new Box app user and will set the
  `external_app_user_id` parameter of the user object to the unique Okta user ID,
  which will define the binding between the two user records.
</Choice>

<Choice option="programming.platform" value="python" color="none">
  In your local application directory, load the `server.py` file created in step
  1\.

  Add the following `Box` class object to the existing code, below the route
  definitions.

  ```python theme={null}
  # Box user class
  class Box(object):
      def __init__(self):
          # Instantiate Box Client instance
          auth = JWTAuth.from_settings_file('../config.json')
          self.box_client = Client(auth)

      # Validate if Box user exists
      def validateUser(self, g):
          # TODO: VALIDATE USER

      # Create new Box user
      def createUser(self, ouser):
          # TODO: CREATE USER
  ```

  This class defines:

  * `init`: When initialized, a new instance of the Box Python SDK is instantiated and made available to the object methods.
  * `validateUser` method: Accepting a user object as input, this will house the code to validate whether a Box user exists for an associated Okta user.
  * `createUser` method: Accepting a user object as input, this creates a new Box user bound to the associated Okta user ID.

  With that class defined, replace the `# TODO: CREATE USER` section with
  the following code.

  ```python theme={null}
  user_name = f'{ouser.profile.firstName} {ouser.profile.lastName}'
  uid = ouser.id
  space = 1073741824

  user = self.box_client.create_user(user_name, None, space_amount=space, external_app_user_id=uid)
  return f'New user created: {user_name}'
  ```

  This code will create a new Box app user and will set the
  `external_app_user_id` parameter of the user object to the unique Okta user ID,
  which will define the binding between the two user records.
</Choice>

<Choice option="programming.platform" value="cs" color="none">
  Within the `Controllers` > `AccountController.cs` file, inside the associated
  `AccountController` class, add the following method.

  ```csharp theme={null}
  static async Task validateUser(string name, string sub)
  {
      // Configure Box SDK instance
      var reader = new StreamReader("config.json");
      var json = reader.ReadToEnd();
      var config = BoxConfig.CreateFromJsonString(json);
      var sdk = new BoxJWTAuth(config);
      var token = sdk.AdminToken();
      BoxClient client = sdk.AdminClient(token);

      // Search for matching Box app user for Okta ID
      BoxCollection<BoxUser> users = await client.UsersManager.GetEnterpriseUsersAsync(externalAppUserId:sub);
      System.Diagnostics.Debug.WriteLine(users.TotalCount);

      if (users.TotalCount > 0)
      {
           // TODO: VALIDATE USER
      }
      else
      {
          // TODO: CREATE USER
      }
  }
  ```

  Within the code block a new Box .NET SDK client is created using the
  `config.json` file downloaded in step 2. In the case of this code sample, that
  `config.json` file is stored at the root of the local application directory.

  That client is then used to search all users in the Box enterprise, passing in
  the Okta `sub` unique ID as the `externalAppUserId` search parameter. The
  number of users returned is then checked to see if a valid user was found.

  With that structure defined, replace the // TODO: CREATE USER section with the
  following code.

  ```csharp theme={null}
  var userRequest = new BoxUserRequest()
  {
      Name = name,
      ExternalAppUserId = sub,
      IsPlatformAccessOnly = true
  };
  var user = await client.UsersManager.CreateEnterpriseUserAsync(userRequest);
  System.Diagnostics.Debug.WriteLine("New user created: " + user.Name);
  ```

  This code will create a new Box app user and will set the
  `external_app_user_id` parameter of the user object to the unique Okta user ID,
  which will define the binding between the two user records.

  A diagnostic message is then written back stating that the new user was created.
</Choice>

<Choice option="programming.platform" unset color="none">
  <Danger>
    **Incomplete previous step**
    Please select a preferred language / framework in step 1 to get started.
  </Danger>
</Choice>

## Validate Okta Users

With the create user functionality defined, let's turn our attention to
defining the code for validating whether an Okta user record has an associated
Box user record by searching all Box enterprise users for the associated
`external_app_user_id`.

<Choice option="programming.platform" value="node" color="none">
  Replace the `// TODO: VALIDATE USER` comment with the following:

  ```js theme={null}
  this.oktaRecord = userInfo

  client.enterprise.getUsers({ "external_app_user_id": this.oktaRecord.sub })
      .then((result) => {
          if (result.total_count > 0) {
              // TODO: MAKE AUTHENTICATED USER CALL
          } else {
              // User not found - create user
              this.createUser();
          }
      });
  ```

  Using the Box Node SDK, we call `enterprise.getUsers` to search all enterprise
  users, and pass in the unique Okta user ID as the `external_app_user_id` value
  to search specifically for that user.

  If found (number of records is greater than 0) we can make an
  authenticated call to the Box APIs using that user record, which will be
  defined in the next section.

  If not found, we call the `createUser` function we defined in the last section
  to create a new Box user with that `external_app_user_id` association.
</Choice>

<Choice option="programming.platform" value="java" color="none">
  Replace the `// TODO: VALIDATE USER` comment with the following:

  ```java theme={null}
  // Set up Box enterprise client
  Reader reader = new FileReader("config.json");
  BoxConfig config = BoxConfig.readFrom(reader);
  api = BoxDeveloperEditionAPIConnection.getAppEnterpriseConnection(config);

  // Get Okta user sub for unique ID attachment to Box user
  Object oktaSub = user.getAttributes().get("sub");

  // Check enterprise users for matching external_app_user_id against Okta sub
  URL url = new URL("https://api.box.com/2.0/users?external_app_user_id=" + oktaSub);
  BoxAPIRequest request = new BoxAPIRequest(api, url, "GET");
  BoxJSONResponse jsonResponse = (BoxJSONResponse) request.send();
  JsonObject jsonObj = jsonResponse.getJsonObject();
  JsonValue totalCount = jsonObj.get("total_count");

  // Set return string
  String outputString = "";

  if (totalCount.asInt() > 0) {
      // TODO: MAKE AUTHENTICATED USER CALL
  } else {
      outputString = createUser(user);
  }

  return outputString;
  ```

  Using the Box Java SDK generic request method, we make a call directly to the
  `https://api.box.com/2.0/users` endpoint to search enterprise users, passing in
  the unique Okta user ID as the `external_app_user_id` value to search
  specifically for that user.

  If found (number of records is greater than 0) we can make an
  authenticated call to the Box APIs using that user record, which will be
  defined in the next section.

  If not found, we call the `createUser` function we defined in the last section
  to create a new Box user with that `external_app_user_id` association.
</Choice>

<Choice option="programming.platform" value="python" color="none">
  Replace the `# TODO: VALIDATE USER` comment with the following:

  ```python theme={null}
  # Fetch Okta user ID
  uid = g.user.id

  # Validate is user exists
  url = f'https://api.box.com/2.0/users?external_app_user_id={uid}'
  response = self.box_client.make_request('GET', url)
  user_info = response.json()

  # If user not found, create user, otherwise fetch user token
  if (user_info['total_count'] == 0):
      self.createUser(g.user)
  else:
      # TODO: MAKE AUTHENTICATED USER CALL
  ```

  Using the Box Python SDK generic request method, we make a call directly to the
  `https://api.box.com/2.0/users` endpoint to search enterprise users, passing in
  the unique Okta user ID as the `external_app_user_id` value to search
  specifically for that user.

  If found (number of records is greater than 0) we can make an
  authenticated call to the Box APIs using that user record, which will be
  defined in the next section.

  If not found, we call the `createUser` function we defined in the last section
  to create a new Box user with that `external_app_user_id` association.
</Choice>

<Choice option="programming.platform" value="cs" color="none">
  Replace the `// TODO: VALIDATE USER` comment with the following:

  ```csharp theme={null}
  var userId = users.Entries[0].Id;
  var userToken = sdk.UserToken(userId);
  BoxClient userClient = sdk.UserClient(userToken, userId);

  // TODO: MAKE AUTHENTICATED USER CALL
  ```

  If a valid user is found, the Box ID is extracted and used to generate a Box
  SDK client that is scoped specifically for that user, rather than the
  application.
</Choice>

<Choice option="programming.platform" unset color="none">
  <Danger>
    **Incomplete previous step**
    Please select a preferred language / framework in step 1 to get started.
  </Danger>
</Choice>

## Make Authenticated Box User Calls

Once an associated Box user is found for the Okta user we're going to generate
an access token specifically
<Link href="/guides/authentication/jwt/user-access-tokens">scoped for that user</Link> to make Box
API calls, then make a call to get the current user to ensure that everything
is working and that we have a valid user access token.

<Choice option="programming.platform" value="node" color="none">
  Replace `// TODO: MAKE AUTHENTICATED USER CALL` from the previous section with
  the following:

  ```js theme={null}
  this.userId = result.entries[0].id;
  this.userClient = sdk.getAppAuthClient('user', this.userId);

  this.userClient.users.get(this.userClient.CURRENT_USER_ID)
      .then(currentUser => {
          res.send(`Hello ${currentUser.name}`);
      });
  ```

  With a user found we capture the Box user ID, then generate a user client
  object scoped for that user. We finish by making a call to fetch the current
  user with the user client object, which should return the user profile
  information for the Okta associated Box app user.
</Choice>

<Choice option="programming.platform" value="java" color="none">
  Replace `// TODO: MAKE AUTHENTICATED USER CALL` from the previous section with
  the following:

  ```java theme={null}
  // User found, authenticate as user
  // Fetch user ID
  JsonArray entries = (JsonArray) jsonObj.get("entries");
  JsonObject userRecord = (JsonObject) entries.get(0);
  JsonValue userId = userRecord.get("id");

  // Get user scoped access token and fetch current user with it
  BoxDeveloperEditionAPIConnection userApi = BoxDeveloperEditionAPIConnection.getAppUserConnection(userId.asString(), config);
  BoxUser currentUser = BoxUser.getCurrentUser(userApi);
  BoxUser.Info currentUserInfo = currentUser.getInfo();

  outputString = "Hello " + currentUserInfo.getName();
  ```

  With a user found we capture the Box user ID, then generate a user client
  object scoped for that user. We finish by making a call to fetch the current
  user with the user client object, which should return the user profile
  information for the Okta associated Box app user.
</Choice>

<Choice option="programming.platform" value="python" color="none">
  Replace `# TODO: MAKE AUTHENTICATED USER CALL` from the previous section with
  the following:

  ```python theme={null}
  # Create user client based on discovered user
  user = user_info['entries'][0]
  user_to_impersonate = self.box_client.user(user_id=user['id'])
  user_client = self.box_client.as_user(user_to_impersonate)

  # Get current user
  current_user = user_client.user().get()
  return f'Hello {current_user.name}'
  ```

  With a user found we capture the Box user ID, then generate a user client
  object scoped for that user. We finish by making a call to fetch the current
  user with the user client object, which should return the user profile
  information for the Okta associated Box app user.
</Choice>

<Choice option="programming.platform" value="cs" color="none">
  Replace `// TODO: MAKE AUTHENTICATED USER CALL` from the previous section with
  the following:

  ```csharp theme={null}
  BoxUser currentUser = await userClient.UsersManager.GetCurrentUserInformationAsync();
  System.Diagnostics.Debug.WriteLine("Current user name: " + currentUser.Name);
  ```

  Using that user scoped client, the current user record is then extracted from
  Box, and a diagnostic message is written back stating the current user name.
</Choice>

<Choice option="programming.platform" unset color="none">
  <Danger>
    **Incomplete previous step**
    Please select a preferred language / framework in step 1 to get started.
  </Danger>
</Choice>

## Summary

* You've validated whether an Okta user exists as a Box user.
* You've creating a new app user if they don't exist.
* You're making a Box API call for an existing Box user.

<Observe option="box.app_type" value="use_own,create_new_">
  <Next>I have set up Box user validation and creation</Next>
</Observe>
