Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't get refresh token #3

Open
royt-via opened this issue Feb 8, 2021 · 21 comments
Open

Can't get refresh token #3

royt-via opened this issue Feb 8, 2021 · 21 comments

Comments

@royt-via
Copy link

royt-via commented Feb 8, 2021

Followed the steps on the readme file and got to the point where I should paste a login url with code.
Did that and nothing happened.
How should I get a refresh token? and would it be persistent or should I regenerate it?

@royt-via
Copy link
Author

royt-via commented Feb 8, 2021

@daigotanaka would appreciate your help

@daigotanaka
Copy link

Hi @royt-via

Thanks for trying out PyPardotSF!
I updated README.md
Can you please check Get keys and tokens section again and let me know if you solved your problem.

If not, let me know which step in the updated instruction you got stuck.

Thanks,
Daigo

@royt-via
Copy link
Author

royt-via commented Feb 9, 2021

hi @daigotanaka ,
thanks for the fast response.
I followed all the steps and now I see the refresh token (in p.sftoken_refresh) but when trying to query some objects (for example prospects) I get this error - access_token is invalid, unknown, or malformed.
another question - can I use the same refresh token again and again or should I create a new one each time?

@daigotanaka
Copy link

daigotanaka commented Feb 10, 2021

Hi @royt-via

The refresh token by default is valid until you invalidate it on Salesforce. The access token should be refreshed automatically by PyPardotSF using the valid refresh token.

I wonder if your Connected App has all the permission as you'd be instructed to check when you run setup_salesforce_auth_keys() as in README.md instruction:

  • Access and manage your data (api)
  • Perform requests on your behalf at any time (refresh_token, offline_access)
  • Provide access to your data via the Web (web)
  • Access Pardot services (pardot_api)

So PyPardotSF is working for me (ver. 3 API) and at least one other user although I just coded it not too long time ago.
Perhaps you can read up on what I referred to during the development:

@royt-via
Copy link
Author

hey @daigotanaka ,
you were right - I was missing the first permission you mentioned.
so, I followed the Obtain Access & Refresh tokens from Salesforce REST API section on your last comment and got the initial refresh token which I'm using to create an instance of the client API as in README.md instructions but when trying to fetch records I get this error - Exception: Failed to refresh token: {'error': 'invalid_grant', 'error_description': 'expired access/refresh token'}

@royt-via
Copy link
Author

royt-via commented Feb 11, 2021

I have both correct access_token and refresh_token.
using the refresh_token to init the client API I get this error message - pypardot.errors.PardotAPIError: Error #184: access_token is invalid, unknown, or malformed

@skpadgett
Copy link

Hey @royt-via are you still having issues? I had a heck of a time getting past that error. I don't have my notes in front of me, but I think my problem was failure to populate the user_key. I have the following variables set in my call:
p=PardotAPI(email='[email protected]',user_key='fxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx2',sf_consumer_key='3xxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxx_xxxxxxxxxxxxxxxx_xxxxxxxxxxxxxxxxxxxxx',sf_consumer_secret='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',sf_refresh_token='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',business_unit_id='xxxxxxxxxxxxxxxxx',version=4)

@daigotanaka
Copy link

Just wanted to follow up and pasting the original thread on PyPardot4 before I forget: mneedham91#46

There are a handful of people including me succeeded in authenticating with the current version of the code. My testing environment is limited to ver 3, but it seems other people made it work with version 4 as well. It would be great if anyone succeeded share their experience here.

@daigotanaka
Copy link

Now I suspect @royt-via Your refresh token may have been expired?

Screen Shot 2021-03-04 at 7 01 41 PM

It would not work if it is set as "Immediately expire refresh token". I'd first test with "valid until revoked", then make it more strict as needed in your situation.

To go to this screen,

  1. Login to Salesforce. Switch to Lightening Experience if on classic (right-top link).
  2. Cog->Setup (right top)
  3. Type 'app manager' and select App Manager from the Quick Find on the left pane (If you cannot see App Manager, follow this: https://help.salesforce.com/articleView?id=000322274&type=1&mode=1 )
  4. Find your app in the list and select "Manage" in the pulldown menu on the right.
  5. Click "Edit Policies" button.

@iritg1
Copy link

iritg1 commented Mar 15, 2021

I tried to use the PyPardotSF but received an error.

First i ran Salesforce authenticating using SDK:

sf = Salesforce(username=api_settings.get('sf_username')
                       , password=api_settings.get('sf_password')
                       , security_token=api_settings.get('sf_security_token')
                       , version=38
                       )

Then I used the session_id retrieved from it as the sf_refresh_token for PardotAPI parameter.

p= PardotAPI (
sf_consumer_key=api_settings.get('client_id'),
sf_consumer_secret=api_settings.get('client_secret'),
sf_refresh_token= sf.session_id
business_unit_id=api_settings.get('business_unit_id'),
version=4)

I managed to authenticate it p.authenticate() -->>(<pypardot.client.PardotAPI object at 0x12c1e44e0>)

But, when running the actual request for the query. e.g:

p.prospects.query(updated_after=kwargs.get('from')
                                                  , offset=0
                                                  , sort_by='updated_at'
                                                  , sort_order='ascending'
                                                  , fields=kwargs.get('fields')
                                                  )

Received an error of:
pypardot.errors.PardotAPIError: Error #184: access_token is invalid, unknown, or malformed

raise Exception(f"Failed to refresh token: {response}")
Exception: Failed to refresh token: {'error': 'invalid_grant', 'error_description': 'expired access/refresh token'}

I also try to run the steps as described in the readme file of https://github.com/anelendata/PyPardotSF/blob/master/README.md

But the url i retrieved from p.setup_salesforce_auth_keys() call didn't lead to any link.

@daigotanaka
Copy link

daigotanaka commented Mar 15, 2021

Hi @iritg1

First i ran Salesforce authenticating using SDK:

I'm not sure if simple-salesforce's sf.session_id stores the refresh_token we need it here...

But the url i retrieved from p.setup_salesforce_auth_keys() call didn't lead to any link.

Yes, the only way I confirmed it to work is through obtaining the refresh_token through the interactive session of setup_salesforce_auth_keys().

When you said p.setup_salesforce_auth_keys() call didn't lead to any link, where exactly in the console steps did you stop seeing an expected response? The steps should look like this:

  1. Login to Salesforce. Switch to Lightening Experience if on classic (right-top link).
  2. Cog->Setup (right top)
  3. Type 'app manager' and select App Manager from the Quick Find on the left pane (If you cannot see App Manager, follow this: https://help.salesforce.com/articleView?id=000322274&type=1&mode=1 )
  4. Click on the New Connected App (in the upper right corner).
  5. On the New Connected App page, fill the following required fields under Basic Information:
    • Connected App Name
    • API Name
    • Contact Email.
  6. Go to API (Enable OAuth Settings), and select Enable OAuth Settings.
    • In the Callback URL field, enter https://login.salesforce.com/
    • In the Selected OAuth Scopes field, select:
      • Access and manage your data (api)
      • Perform requests on your behalf at any time (refresh_token, offline_access)
      • Provide access to your data via the Web (web)
      • Access Pardot services (pardot_api)
        and then click Add.
  7. Click the Save button to save the new Connected App.

@iritg1
Copy link

iritg1 commented Mar 15, 2021

Thank you @daigotanaka.
We followed your steps and added the relevant permissions to an existing App.

In the setup_salesforce_auth_keys() i used following creds:

instance id:
xxxx from https://xxxx.lightning.force.com/lightning/page/home

Client id & client secret:
as appears in SF connected app.

Business unit id:
from Pardot account setup.

then "Open the following page in a browser" led to a broken path: (This site can’t be reached)
here is the link:
https://instance id.salesforce.com/services/oauth2/authorize?response_type=code&client_id=our client id&redirect_uri=https://login.salesforce.com/

@daigotanaka
Copy link

daigotanaka commented Mar 15, 2021

@iritg1

Does your organization use "My Domain" feature that makes a custom insteand_id?

If yes, I think you have to specify the instance ID as "your_custom_ID.my" (add .my).

If that does not work, can you try:

  1. Go the company information page following this?
  2. Then find "Instance" field in "Organization Detail" section. Use the value instead of ".my" when you follow
    this instruction again.

Unfortunately, I cannot test this on my end. So let me know if this works...

@iritg1
Copy link

iritg1 commented Mar 15, 2021

Yes! we are using My Domain.
I added it to the instance id and managed to connect.

thank you!

@daigotanaka
Copy link

Hi @iritg1

I'm glad it worked!
I'm curious if it worked just by adding .my or you had to switch to the non-my domain instance ID. I want to update the instructions and script so others will benefit. Please let me know. Thx!

@iritg1
Copy link

iritg1 commented Mar 17, 2021

I adde '.my' to the instance_id which solved the problem

@iritg1
Copy link

iritg1 commented Mar 17, 2021

another lesson learned:
uninstall PyPardot4 package first
then install PyPardotSF, otherwise there might be a clash between the two pypardot classes

@royt-via
Copy link
Author

royt-via commented May 26, 2021

Hi @daigotanaka , it's been a while :)

I'm still getting access_token is invalid, unknown, or malformed.

My organization is using "My Domain" but I'm not sure how to follow your suggestion to @iritg1 .
I don't see .my anywhere.
Following the README I'm initializing PardotAPI like this

p = PardotAPI(
    sf_consumer_key=sf_consumer_key,
    sf_consumer_secret=sf_consumer_secret,
    sf_refresh_token=sf_refresh_token,
    business_unit_id=business_unit_id,
    version=3)

The only place I had to use the organization instance ID was when I was fetching the refresh_token.

Should I try adding user_key like @skpadgett suggested?

(btw, I shouldn't be using access_token anywhere, right? just the refresh_token)

@daigotanaka
Copy link

Hey @royt-via Good to hear from you again :)

I don't think you need to use user_key. If you did, I'd think it's a PyPardot4 is conflicting with PyPardotSF like @iritg1 noted.

.my is a hard-coded value something I suggested to add to your "My Domain" when the console prompted to ask you "What is your instance ID?" (original comment). For example, if your custom domain is "acmecompany", you will put "acmecompany.my". If your organization does not use My Domain feature this isn't applicable. Just use the regular instance ID.

Like I noted in my original comment, I don't have the access to My Domain feature, so I'm hoping @iritg1 or someone can give you a tip here.

@royt-via
Copy link
Author

I tried that but it didn't work either :/
(I also uninstalled PyPardot4 but it made no difference)

@daigotanaka
Copy link

I finally had an opportunity to work with an account with my domain. I confirmed that the method of obtaining refresh token with the interactive command-line tool worked. With my domain, You will need to put ".my" as in:

https://<domain>.salesforce.com/services/oauth2/authorize?response_type=code&client_id=xxxxxx&redirect_uri=https://login.salesforce.com/

to

https://<domain>.my.salesforce.com/services/oauth2/authorize?response_type=code&client_id=xxxxxx&redirect_uri=https://login.salesforce.com/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants