code: def handle_token_request(self, request_body,  # type: str
                               http_headers=None,  # type: Optional[Mapping[str, str]]
                               extra_id_token_claims=None
                               # type: Optional[Union[Mapping[str, Union[str, List[str]]], Callable[[str, str], Mapping[str, Union[str, List[str]]]]]
                               ):
          # type: (...) -> oic.oic.message.AccessTokenResponse
          
  
          token_request = self._verify_client_authentication(request_body, http_headers)
  
          if 'grant_type' not in token_request:
              raise InvalidTokenRequest('grant_type missing', token_request)
          elif token_request['grant_type'] == 'authorization_code':
              return self._do_code_exchange(token_request, extra_id_token_claims)
          elif token_request['grant_type'] == 'refresh_token':
              return self._do_token_refresh(token_request)
  
          raise InvalidTokenRequest('grant_type \'{}\' unknown'.format(token_request['grant_type']), token_request,
                                    oauth_error='unsupported_grant_type')
docs: Handles a token request, either for exchanging an authorization code or using a refresh token.
          :param request_body: urlencoded token request
          :param http_headers: http headers
          :param extra_id_token_claims: extra claims to include in the signed ID Token