'Perform authentication.'

def authenticate(self, force=False):

    if (not self._is_authentication_needed(force=force)):
        return self
    data = {'auth': {'identity': {'methods': ['password'], 'password': {'user': {'domain': {'name': self.domain_name}, 'name': self.user_id, 'password': self.key}}}}}
    if (self.token_scope == OpenStackIdentityTokenScope.PROJECT):
        data['auth']['scope'] = {'project': {'domain': {'name': self.domain_name}, 'name': self.tenant_name}}
    elif (self.token_scope == OpenStackIdentityTokenScope.DOMAIN):
        data['auth']['scope'] = {'domain': {'name': self.domain_name}}
    elif (self.token_scope == OpenStackIdentityTokenScope.UNSCOPED):
        pass
    else:
        raise ValueError('Token    needs    to    be    scoped    either    to    project    or    a    domain')
    data = json.dumps(data)
    response = self.request('/v3/auth/tokens', data=data, headers={'Content-Type': 'application/json'}, method='POST')
    if (response.status == httplib.UNAUTHORIZED):
        raise InvalidCredsError()
    elif (response.status in [httplib.OK, httplib.CREATED]):
        headers = response.headers
        try:
            body = json.loads(response.body)
        except Exception:
            e = sys.exc_info()[1]
            raise MalformedResponseError('Failed    to    parse    JSON', e)
        try:
            roles = self._to_roles(body['token']['roles'])
        except Exception:
            e = sys.exc_info()[1]
            roles = []
        try:
            expires = body['token']['expires_at']
            self.auth_token = headers['x-subject-token']
            self.auth_token_expires = parse_date(expires)
            self.urls = body['token'].get('catalog', None)
            self.auth_user_info = None
            self.auth_user_roles = roles
        except KeyError:
            e = sys.exc_info()[1]
            raise MalformedResponseError('Auth    JSON    response    is                                                                                                                                                                                        missing    required    elements', e)
        body = ('code:    %s    body:%s' % (response.status, response.body))
    elif (response.status == 300):
        raise LibcloudError('Auth    request    returned    ambiguous    version    error,    tryusing    the    version    specific    URL    to    connect,    e.g.    identity/v3/auth/tokens')
    else:
        body = ('code:    %s    body:%s' % (response.status, response.body))
        raise MalformedResponseError('Malformed    response', body=body, driver=self.driver)
    return self
