docs: @PostMapping(value = TOKEN_ENDPOINT_URI, produces = MediaType.APPLICATION_JSON_VALUE)
      public ResponseEntity oauthToken(
              @RequestParam(value = "client_id") String clientId,
              @RequestParam(value = "client_secret") String clientSecret,
              @RequestParam(
                              value = "grant_type",
                              required = false,
                              defaultValue = "client_credentials")
                      String grantType,
              @RequestParam(value = "scope", required = false, defaultValue = "/all") String scope,
              @RequestParam(value = "claims", required = false) String claims,
              @RequestParam(value = "groups", required = false) String groups) {
  
          /*
           * NB:  Several of this method's parameters are not consumed (yet) in any way.  They are
           * defined to match a two-legged OAuth strategy and for future use.
           */
  
          final String msg =
                  "Processing request for OAuth access token;  client_id='{}', client_secret='{}', "
                          + "grant_type='{}', scope='{}', claims='{}', groups='{}'";
          logger.debug(
                  msg,
                  clientId,
                  StringUtils.repeat("*", clientSecret.length()),
                  grantType,
                  scope,
                  claims,
                  groups);
  
          // STEP 1:  identify the client
          final OAuthClient oAuthClient = clientMap.get(clientId);
          if (oAuthClient == null) {
              return ResponseEntity.status(HttpStatus.FORBIDDEN)
                      .body(Collections.singletonMap("message", "client_id not found"));
          }
  
          logger.debug(
                  "Selected known OAuthClient with client_id='{}' for access token request",
                  oAuthClient.getClientId());
  
          // STEP 2:  validate the client_secret
          if (!oAuthClient.getClientSecret().equals(clientSecret)) {
              return ResponseEntity.status(HttpStatus.FORBIDDEN)
                      .body(Collections.singletonMap("message", "authentication failed"));
          }
  
          // STEP 3:  obtain the specified user
          final IPerson person = personService.getPerson(oAuthClient.getPortalUserAccount());
          if (person == null) {
              return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                      .body(
                              Collections.singletonMap(
                                      "message",
                                      "portal user account not found: "
                                              + oAuthClient.getPortalUserAccount()));
          }
  
          logger.debug(
                  "Selected portal Person with username='{}' for client_id='{}'",
                  person.getUserName(),
                  oAuthClient.getClientId());
  
          // STEP 4:  build a standard OAuth2 access token response
          final String token = createToken(person, claims, groups);
          final Map<String, Object> rslt = new HashMap<>();
          rslt.put("access_token", token);
          rslt.put("token_type", "bearer");
          rslt.put(
                  "expires_in",
                  timeoutSeconds > 2 ? timeoutSeconds - 2L /* fudge factor */ : timeoutSeconds);
          rslt.put("scope", scope);
  
          logger.debug(
                  "Produced the following access token for client_id='{}':  {}",
                  oAuthClient.getClientId(),
                  rslt);
  
          return ResponseEntity.ok(rslt);
      }