Exemple #1
0
def jwt_login(consumer_id, username, private_key, sandbox=False):
    endpoint = ("https://test.salesforce.com"
                if sandbox is True else "https://login.salesforce.com")
    jwt_payload = jwt.encode(
        {
            "exp": datetime.datetime.utcnow() + datetime.timedelta(seconds=30),
            "iss": consumer_id,
            "aud": endpoint,
            "sub": username,
        },
        private_key,
        algorithm="RS256",
    )

    result = requests.post(
        endpoint + "/services/oauth2/token",
        data={
            "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
            "assertion": jwt_payload,
        },
    )
    body = result.json()

    if result.status_code != 200:
        raise SalesforceAuthenticationFailed(body["error"],
                                             body["error_description"])

    return simple_salesforce.Salesforce(
        instance_url=body["instance_url"],
        session_id=body["access_token"],
        version="46.0",
    )
Exemple #2
0
def jwt_login(consumer_id, username, private_key, sandbox=False):
    global session_id, instance, sfurl

    endpoint = 'https://test.salesforce.com' if sandbox is True else 'https://login.salesforce.com'
    jwt_payload = jwt.encode(
        { 
            'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=30),
            'iss': consumer_id,
            'aud': endpoint,
            'sub': username
        },
        private_key,
        algorithm='RS256'
    )

    result = requests.post(
        endpoint + '/services/oauth2/token',
        data={
            'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
            'assertion': jwt_payload
        }
    )
    body = result.json()
    print(body)
    
    if result.status_code != 200:
        raise SalesforceAuthenticationFailed(body['error'], body['error_description'])
    # now set things properly
    session_id = body['access_token']
    instance = body['instance_url']
    sfurl = instance
    
    sf = Salesforce(instance_url=body['instance_url'], session_id=body['access_token'])
    return sf
Exemple #3
0
def jwt_login(consumer_id, username, private_key):
    endpoint = 'https://login.salesforce.com'
    jwt_payload = jwt.encode(
        {
            'iss': consumer_id,
            'sub': username,
            'aud': endpoint,
            'exp': datetime.datetime.utcnow() + datetime.timedelta(seconds=300)
        },
        private_key,
        algorithm='RS256')
    # Send the request to get the TOKEN
    result = requests.post(endpoint + '/services/oauth2/token',
                           data={
                               'grant_type':
                               'urn:ietf:params:oauth:grant-type:jwt-bearer',
                               'assertion': jwt_payload
                           })
    body = result.json()
    sf = Salesforce(instance_url=body['instance_url'],
                    session_id=body['access_token'])
    # Print LOGIN errors
    if result.status_code != 200:
        raise SalesforceAuthenticationFailed(body['error'],
                                             body['error_description'])
    return Salesforce(instance_url=body['instance_url'],
                      session_id=body['access_token'])
Exemple #4
0
def mock_salesforce_auth(is_success: bool) -> Iterator[None]:
    if is_success:
        with patch(
                'simple_salesforce.api.Salesforce.__init__') as mock_sf_init:
            mock_sf_init.return_value = None
            yield
    else:
        with patch('simple_salesforce.api.Salesforce.__init__',
                   side_effect=SalesforceAuthenticationFailed(
                       403, 'auth failed')) as mock_sf_init:
            mock_sf_init.return_value = None
            yield
Exemple #5
0
def token_login(token_url, token_data, domain, consumer_key,
                headers, proxies, session=None):
    """Process OAuth 2.0 JWT Bearer Token Flow."""
    response = (session or requests).post(
        token_url, token_data, headers=headers, proxies=proxies)

    try:
        json_response = response.json()
    except JSONDecodeError:
        raise SalesforceAuthenticationFailed(
            response.status_code, response.text
        )

    if response.status_code != 200:
        except_code = json_response.get('error')
        except_msg = json_response.get('error_description')
        if except_msg == "user hasn't approved this consumer":
            auth_url = 'https://{domain}.salesforce.com/services/oauth2/' \
                       'authorize?response_type=code&client_id=' \
                       '{consumer_key}&redirect_uri=<approved URI>'.format(
                            domain=domain,
                            consumer_key=consumer_key
                        )
            warnings.warn("""
    If your connected app policy is set to "All users may 
    self-authorize", you may need to authorize this 
    application first. Browse to 
    %s 
    in order to Allow Access. Check first to ensure you have a valid 
    <approved URI>.""" % auth_url)
        raise SalesforceAuthenticationFailed(except_code, except_msg)

    access_token = json_response.get('access_token')
    instance_url = json_response.get('instance_url')

    sf_instance = instance_url.replace(
        'http://', '').replace(
        'https://', '')

    return access_token, sf_instance
Exemple #6
0
    def connect(self):
        try:
            sf = Salesforce(
                username=Config.DEVELOPMENT_CONF['salesforce']['username'],
                password=Config.DEVELOPMENT_CONF['salesforce']['password'],
                security_token=Config.DEVELOPMENT_CONF['salesforce']['token'])
        except Exception as e:
            if self.retry != 0:
                self.retry -= 1
                self.connect()
            else:
                raise SalesforceAuthenticationFailed(
                    "500", 'Can`t connect to saleforce')

        return sf
Exemple #7
0
def soap_login(soap_url, request_body, headers, proxies, session=None):
    """Process SOAP specific login workflow."""
    response = (session or requests).post(
        soap_url, request_body, headers=headers, proxies=proxies)

    if response.status_code != 200:
        except_code = getUniqueElementValueFromXmlString(
            response.content, 'sf:exceptionCode')
        except_msg = getUniqueElementValueFromXmlString(
            response.content, 'sf:exceptionMessage')
        raise SalesforceAuthenticationFailed(except_code, except_msg)

    session_id = getUniqueElementValueFromXmlString(
        response.content, 'sessionId')
    server_url = getUniqueElementValueFromXmlString(
        response.content, 'serverUrl')

    sf_instance = (server_url
                   .replace('http://', '')
                   .replace('https://', '')
                   .split('/')[0]
                   .replace('-api', ''))

    return session_id, sf_instance
Exemple #8
0
    def convert_lead(self,
                     lead_id: str,
                     account_id: str,
                     converted_lead_status: str = None,
                     create_opp: bool = False,
                     send_email: bool = False):
        sf_instance = self.client.sf_instance
        sf_version = self.client.sf_version
        session_id = self.client.session_id
        session = self.client.session

        if not converted_lead_status and not self.converted_status:
            converted_lead_status = self.converted_status = self.get_converted_status(
            )

        soap_url = f'https://{sf_instance}/services/Soap/u/{sf_version}'

        login_soap_request_headers = {
            'content-type': 'text/xml',
            'charset': 'UTF-8',
            'SOAPAction': 'convertLead'
        }

        login_soap_request_body = f"""
            <soapenv:Envelope
                        xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                        xmlns:urn="urn:partner.soap.sforce.com">
              <soapenv:Header>
                 <urn:SessionHeader>
                    <urn:sessionId>{session_id}</urn:sessionId>
                 </urn:SessionHeader>
              </soapenv:Header>
              <soapenv:Body>
                 <urn:convertLead> 
                    <urn:leadConverts> <!-- Zero or more repetitions -->
                       <urn:convertedStatus>{converted_lead_status}</urn:convertedStatus>
                       <urn:leadId>{lead_id}</urn:leadId>
                       <urn:accountId>{account_id}</urn:accountId>
                       <urn:sendNotificationEmail>{send_email}</urn:sendNotificationEmail>
                       <urn:doNotCreateOpportunity>{not create_opp}</urn:doNotCreateOpportunity>
                    </urn:leadConverts>
                 </urn:convertLead>
              </soapenv:Body>
            </soapenv:Envelope>
            """

        response = session.post(soap_url,
                                login_soap_request_body,
                                headers=login_soap_request_headers)

        if response.status_code != 200:
            except_code = util.getUniqueElementValueFromXmlString(
                response.content, 'sf:exceptionCode')
            except_msg = util.getUniqueElementValueFromXmlString(
                response.content, 'sf:exceptionMessage')
            raise SalesforceAuthenticationFailed(except_code, except_msg)
        else:
            contact_id = util.getUniqueElementValueFromXmlString(
                response.content, 'contactId')
            success = util.getUniqueElementValueFromXmlString(
                response.content, 'success')
            status_code = util.getUniqueElementValueFromXmlString(
                response.content, 'statusCode')

            if success == 'true':
                logging.info(
                    f"Lead Id {lead_id} converted to Contact Id {contact_id}")
                return True, contact_id
            else:
                logging.error(
                    f"Unable to convert Lead Id {lead_id}. Status Code: {status_code}"
                )
                return False, status_code
Exemple #9
0
def SalesforceLogin(
        username=None, password=None, security_token=None,
        organizationId=None, sandbox=False, sf_version=DEFAULT_API_VERSION,
        proxies=None, session=None, client_id=None, custom_url=None):
    """Return a tuple of `(session_id, sf_instance)` where `session_id` is the
    session ID to use for authentication to Salesforce and `sf_instance` is
    the domain of the instance of Salesforce to use for the session.

    Arguments:

    * username -- the Salesforce username to use for authentication
    * password -- the password for the username
    * security_token -- the security token for the username
    * organizationId -- the ID of your organization
            NOTE: security_token an organizationId are mutually exclusive
    * sandbox -- True if you want to login to `test.salesforce.com`, False if
                 you want to login to `login.salesforce.com`.
    * sf_version -- the version of the Salesforce API to use, for example
                    "27.0"
    * proxies -- the optional map of scheme to proxy server
    * session -- Custom requests session, created in calling code. This
                 enables the use of requets Session features not otherwise
                 exposed by simple_salesforce.
    * client_id -- the ID of this client
    * custom_url -- Supports Salesforce URL customization
    """

    if custom_url:
        soap_url = ('{custom_url}/services/Soap/u/{sf_version}'
                    .format(custom_url=custom_url, 
                            sf_version=sf_version))
    else:
        soap_url = 'https://{domain}.salesforce.com/services/Soap/u/{sf_version}'
        domain = 'test' if sandbox else 'login'
        soap_url = soap_url.format(domain=domain, sf_version=sf_version)

    if client_id:
        client_id = "{prefix}/{app_name}".format(
            prefix=DEFAULT_CLIENT_ID_PREFIX,
            app_name=client_id)
    else:
        client_id = DEFAULT_CLIENT_ID_PREFIX

    # pylint: disable=E0012,deprecated-method
    username = escape(username)
    password = escape(password)

    # Check if token authentication is used
    if security_token is not None:
        # Security Token Soap request body
        login_soap_request_body = """<?xml version="1.0" encoding="utf-8" ?>
        <env:Envelope
                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
                xmlns:urn="urn:partner.soap.sforce.com">
            <env:Header>
                <urn:CallOptions>
                    <urn:client>{client_id}</urn:client>
                    <urn:defaultNamespace>sf</urn:defaultNamespace>
                </urn:CallOptions>
            </env:Header>
            <env:Body>
                <n1:login xmlns:n1="urn:partner.soap.sforce.com">
                    <n1:username>{username}</n1:username>
                    <n1:password>{password}{token}</n1:password>
                </n1:login>
            </env:Body>
        </env:Envelope>""".format(
            username=username, password=password, token=security_token,
            client_id=client_id)

    # Check if IP Filtering is used in conjunction with organizationId
    elif organizationId is not None:
        # IP Filtering Login Soap request body
        login_soap_request_body = """<?xml version="1.0" encoding="utf-8" ?>
        <soapenv:Envelope
                xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                xmlns:urn="urn:partner.soap.sforce.com">
            <soapenv:Header>
                <urn:CallOptions>
                    <urn:client>{client_id}</urn:client>
                    <urn:defaultNamespace>sf</urn:defaultNamespace>
                </urn:CallOptions>
                <urn:LoginScopeHeader>
                    <urn:organizationId>{organizationId}</urn:organizationId>
                </urn:LoginScopeHeader>
            </soapenv:Header>
            <soapenv:Body>
                <urn:login>
                    <urn:username>{username}</urn:username>
                    <urn:password>{password}</urn:password>
                </urn:login>
            </soapenv:Body>
        </soapenv:Envelope>""".format(
            username=username, password=password, organizationId=organizationId,
            client_id=client_id)
    elif username is not None and password is not None:
        # IP Filtering for non self-service users
        login_soap_request_body = """<?xml version="1.0" encoding="utf-8" ?>
        <soapenv:Envelope
                xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                xmlns:urn="urn:partner.soap.sforce.com">
            <soapenv:Header>
                <urn:CallOptions>
                    <urn:client>{client_id}</urn:client>
                    <urn:defaultNamespace>sf</urn:defaultNamespace>
                </urn:CallOptions>
            </soapenv:Header>
            <soapenv:Body>
                <urn:login>
                    <urn:username>{username}</urn:username>
                    <urn:password>{password}</urn:password>
                </urn:login>
            </soapenv:Body>
        </soapenv:Envelope>""".format(
            username=username, password=password, client_id=client_id)
    else:
        except_code = 'INVALID AUTH'
        except_msg = (
            'You must submit either a security token or organizationId for '
            'authentication'
        )
        raise SalesforceAuthenticationFailed(except_code, except_msg)

    login_soap_request_headers = {
        'content-type': 'text/xml',
        'charset': 'UTF-8',
        'SOAPAction': 'login'
    }
    response = (session or requests).post(
        soap_url, login_soap_request_body, headers=login_soap_request_headers,
        proxies=proxies)

    if response.status_code != 200:
        except_code = getUniqueElementValueFromXmlString(
            response.content, 'sf:exceptionCode')
        except_msg = getUniqueElementValueFromXmlString(
            response.content, 'sf:exceptionMessage')
        raise SalesforceAuthenticationFailed(except_code, except_msg)

    session_id = getUniqueElementValueFromXmlString(
        response.content, 'sessionId')
    server_url = getUniqueElementValueFromXmlString(
        response.content, 'serverUrl')

    sf_instance = (server_url
                   .replace('http://', '')
                   .replace('https://', '')
                   .split('/')[0]
                   .replace('-api', ''))

    return session_id, sf_instance
Exemple #10
0
def convert_lead(
    session,
    session_id,
    lead_id,
    sf_instance,
    account_id=None,
    lead_status="Closed Won",
    sandbox=False,
    proxies=None,
    sf_version="38.0",
):
    soap_url = "https://{sf_instance}/services/Soap/u/{sf_version}"
    domain = "test" if sandbox else "login"
    soap_url = soap_url.format(domain=domain,
                               sf_version=sf_version,
                               sf_instance=sf_instance)

    account_id_block = ""
    if account_id:
        account_id_block = "<urn:accountId>{account_id}</urn:accountId>".format(
            account_id=account_id)

    login_soap_request_body = """
    <soapenv:Envelope
                xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                xmlns:urn="urn:partner.soap.sforce.com">
      <soapenv:Header>
         <urn:SessionHeader>
            <urn:sessionId>{session_id}</urn:sessionId>
         </urn:SessionHeader>
      </soapenv:Header>
      <soapenv:Body>
         <urn:convertLead> 
            <urn:leadConverts> <!-- Zero or more repetitions -->
               <urn:convertedStatus>{lead_status}</urn:convertedStatus>
               <urn:leadId>{lead_id}</urn:leadId>
               {account_id_block}
               <urn:convertedStatus>{lead_status}</urn:convertedStatus>
               <urn:sendNotificationEmail>true</urn:sendNotificationEmail>
               <urn:doNotCreateOpportunity>true</urn:doNotCreateOpportunity>
            </urn:leadConverts>
         </urn:convertLead>
      </soapenv:Body>
    </soapenv:Envelope>
    """.format(
        lead_id=lead_id,
        account_id_block=account_id_block,
        session_id=session_id,
        lead_status=lead_status,
    )
    login_soap_request_headers = {
        "content-type": "text/xml",
        "charset": "UTF-8",
        "SOAPAction": "convertLead",
    }
    response = session.post(
        soap_url,
        login_soap_request_body,
        headers=login_soap_request_headers,
        proxies=proxies,
    )
    if response.status_code != 200:
        except_code = getUniqueElementValueFromXmlString(
            response.content, "sf:exceptionCode")
        except_msg = getUniqueElementValueFromXmlString(
            response.content, "sf:exceptionMessage")
        raise SalesforceAuthenticationFailed(except_code, except_msg)
    else:
        contact_id = getUniqueElementValueFromXmlString(
            response.content, "contactId")
        success = getUniqueElementValueFromXmlString(response.content,
                                                     "success")
        status_code = getUniqueElementValueFromXmlString(
            response.content, "statusCode")
        if success == "true":
            return True, contact_id
        else:
            return False, status_code
Exemple #11
0
def SalesforceLogin(
        username=None, password=None, security_token=None,
        organizationId=None, sandbox=None, sf_version=DEFAULT_API_VERSION,
        proxies=None, session=None, client_id=None, domain=None,
        consumer_key=None, privatekey_file=None):
    """Return a tuple of `(session_id, sf_instance)` where `session_id` is the
    session ID to use for authentication to Salesforce and `sf_instance` is
    the domain of the instance of Salesforce to use for the session.

    Arguments:

    * username -- the Salesforce username to use for authentication
    * password -- the password for the username
    * security_token -- the security token for the username
    * organizationId -- the ID of your organization
            NOTE: security_token an organizationId are mutually exclusive
    * sandbox -- DEPRECATED: Use domain instead.
    * sf_version -- the version of the Salesforce API to use, for example
                    "27.0"
    * proxies -- the optional map of scheme to proxy server
    * session -- Custom requests session, created in calling code. This
                 enables the use of requets Session features not otherwise
                 exposed by simple_salesforce.
    * client_id -- the ID of this client
    * domain -- The domain to using for connecting to Salesforce. Use
                common domains, such as 'login' or 'test', or
                Salesforce My domain. If not used, will default to
                'login'.
    * consumer_key -- the consumer key generated for the user
    * privatekey_file -- the path to the private key file used
                         for signing the JWT token
    """
    if (sandbox is not None) and (domain is not None):
        raise ValueError("Both 'sandbox' and 'domain' arguments were "
                         "supplied. Either may be supplied, but not "
                         "both.")

    if sandbox is not None:
        warnings.warn("'sandbox' argument is deprecated. Use "
                      "'domain' instead. Overriding 'domain' "
                      "with 'sandbox' value.",
                      DeprecationWarning)

        domain = 'test' if sandbox else 'login'

    if domain is None:
        domain = 'login'

    soap_url = 'https://{domain}.salesforce.com/services/Soap/u/{sf_version}'

    if client_id:
        client_id = "{prefix}/{app_name}".format(
            prefix=DEFAULT_CLIENT_ID_PREFIX,
            app_name=client_id)
    else:
        client_id = DEFAULT_CLIENT_ID_PREFIX

    soap_url = soap_url.format(domain=domain,
                               sf_version=sf_version)

    # pylint: disable=E0012,deprecated-method
    username = escape(username) if username else None
    password = escape(password) if password else None

    # Check if token authentication is used
    if security_token is not None:
        # Security Token Soap request body
        login_soap_request_body = """<?xml version="1.0" encoding="utf-8" ?>
        <env:Envelope
                xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
                xmlns:urn="urn:partner.soap.sforce.com">
            <env:Header>
                <urn:CallOptions>
                    <urn:client>{client_id}</urn:client>
                    <urn:defaultNamespace>sf</urn:defaultNamespace>
                </urn:CallOptions>
            </env:Header>
            <env:Body>
                <n1:login xmlns:n1="urn:partner.soap.sforce.com">
                    <n1:username>{username}</n1:username>
                    <n1:password>{password}{token}</n1:password>
                </n1:login>
            </env:Body>
        </env:Envelope>""".format(
            username=username, password=password, token=security_token,
            client_id=client_id)

    # Check if IP Filtering is used in conjunction with organizationId
    elif organizationId is not None:
        # IP Filtering Login Soap request body
        login_soap_request_body = """<?xml version="1.0" encoding="utf-8" ?>
        <soapenv:Envelope
                xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                xmlns:urn="urn:partner.soap.sforce.com">
            <soapenv:Header>
                <urn:CallOptions>
                    <urn:client>{client_id}</urn:client>
                    <urn:defaultNamespace>sf</urn:defaultNamespace>
                </urn:CallOptions>
                <urn:LoginScopeHeader>
                    <urn:organizationId>{organizationId}</urn:organizationId>
                </urn:LoginScopeHeader>
            </soapenv:Header>
            <soapenv:Body>
                <urn:login>
                    <urn:username>{username}</urn:username>
                    <urn:password>{password}</urn:password>
                </urn:login>
            </soapenv:Body>
        </soapenv:Envelope>""".format(
            username=username, password=password, organizationId=organizationId,
            client_id=client_id)
    elif username is not None and password is not None:
        # IP Filtering for non self-service users
        login_soap_request_body = """<?xml version="1.0" encoding="utf-8" ?>
        <soapenv:Envelope
                xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                xmlns:urn="urn:partner.soap.sforce.com">
            <soapenv:Header>
                <urn:CallOptions>
                    <urn:client>{client_id}</urn:client>
                    <urn:defaultNamespace>sf</urn:defaultNamespace>
                </urn:CallOptions>
            </soapenv:Header>
            <soapenv:Body>
                <urn:login>
                    <urn:username>{username}</urn:username>
                    <urn:password>{password}</urn:password>
                </urn:login>
            </soapenv:Body>
        </soapenv:Envelope>""".format(
            username=username, password=password, client_id=client_id)
    elif username is not None and \
            consumer_key is not None and \
            privatekey_file is not None:
        header = {'alg': 'RS256'}
        expiration = datetime.utcnow() + timedelta(minutes=3)
        payload = {
            'iss': consumer_key,
            'sub': username,
            'aud': 'https://{domain}.salesforce.com'.format(domain=domain),
            'exp': '{exp:.0f}'.format(
                exp=time.mktime(expiration.timetuple()) +
                    expiration.microsecond / 1e6
            )
        }
        with open(privatekey_file, 'rb') as key:
            assertion = jwt.encode(header, payload, key.read())

        login_token_request_data = {
            'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
            'assertion': assertion
        }

        return token_login(
            'https://{domain}.salesforce.com/services/oauth2/token'.format(
                domain=domain),
            login_token_request_data, domain, consumer_key,
            None, proxies, session)
    else:
        except_code = 'INVALID AUTH'
        except_msg = (
            'You must submit either a security token or organizationId for '
            'authentication'
        )
        raise SalesforceAuthenticationFailed(except_code, except_msg)

    login_soap_request_headers = {
        'content-type': 'text/xml',
        'charset': 'UTF-8',
        'SOAPAction': 'login'
    }

    return soap_login(soap_url, login_soap_request_body,
        login_soap_request_headers, proxies, session)