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

        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')
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