Docusign integration App not allowing to send cross account documents for eSign. INVALID_USER error - docusignapi

We have done one CRM integration where we as an CRM have our own docusign pro account.
We completed the GoLive process successfully and have all required data like Integration key, Account Id, Client Id and Secret Key for App.
Now this CRM integration will be used as an mediator for our clients who will have their own purchased docusign accounts.
So till now we have 2 accounts,
CRM Integration docusign account with GoLive status.
Client account to send their own documents for eSign through our CRM integration.
What we have achieved till now?
We completed the consent flow where we redirect our clients to docusign consent page where they provide consent to our app by login into their docusign account. In this flow we use CRM integration account id in URL which takes our client for consent page. On confirm the client will be redirected back to CRM with auth code attached in redirect URL.
We use this auth code to get access token for this client. We use CRMs account id, Integration App secret key and clients auth code to get the access token. We are successful in this too. We get clients access token. No Issues.
Now when our client is trying to send a document for eSign using the access token received in step 2 above, the docusign throws an error saying INVALID_USER.
I have referred to this post Simillar Issue it kind of approves of what we are trying to achieve but it is failing with error.

Let me try to explain and make sure it's clear.
The IK (Integration Key) is global for the entire environment. By environment I mean either the developer environment, or the production environment. When you went live and completed the process using a production environment - you made your IK available for any account and any user in the production environment.
Now, when you get an access token to make API calls, this token is for a specific userId. The userId can be a member of one ore more accounts as showed in this diagram:
The userId is provided by the user logging in when given the option to consent. So when you doing your consent flow, there's a web browser and user that logs in, that is the userId that consent.
Separately, when you request a token using JWT grant, you provide a userId, that userId is a GUID for a unique user in the system.
This GUID must be for the same exact production user that gave consent. That's first thing to confirm.
Now, if you already have an access token to make API calls, when you make a specific API call, you need to provide an accountID. That's another GUID representing an account, not a user. The userId that was provided to the JWT Grant flow must represent a user that has a membership (it is a member of) in the account for which you provided a GUID (a user can be a member of more than one account). That is the second thing to check.
Lastly, there's a baseURI that is used to make API calls and it can be different for different accounts. You need to also confirm you are using the correct one.

Related

Azure Active Directory: how to get user's object id via auth code flow (MSAL)?

I have developed web application (Python/Django) for my client and he wants me to add SSO via Azure Active Directory that he setup. Also I need to fetch user profile information (email, upn) and update it when it changes in AD.
I managed to get SSO working using MSAL with auth code flow and able to send requests to Graph API on behalf of user to get profile information (/me).
To get profile updates I created subscription (webhook) to /users resource using app identity (client credentials grant flow).
The problem is that I can't understand how to correlate users I get from subscriptions with users I get from auth code flow via MSAL. Notifications from subscriptions give me ids i can find on azure portal (GUID), but profile information requests on behalf of user dont give me same ids. There are ids, but these ids are differenet (something like c66b9ba73bcba166)
As juunas mentioned, the object id is typically oid or sub.
Example using jwt.ms to examine the ID token:
Also, if your app needs to distinguish between app-only access tokens and access tokens for users, you can use use the idtyp optional claim.

How should we go about allowing individual users of our web app to connect to their own DocuSign account?

For context, we are currently developing a DocuSign integration on our DMS web app product. So far what we have done is that the web app's admin (we assume this would be someone like our customer's IT) can set up the integration by entering API Account ID, Integration Key, Secret Key, Access Token & Refresh Token. All these information was taken/generated using a DocuSign admin account. With this, we see that any user using the DMS can send out signing requests (via API) without logging in to their own DocuSign account.
However, we realised this means that all signing requests will be sent using the common DocuSign admin account, i.e. the envelopes originate from the admin account and all signed documents also stored in the DocuSign admin account. This is not what we want as the DocuSign admin can see confidential signed documents.
I'm quite confused and would like to seek advise on how should we go about this? Ideally, it is that User A of the DMS can associate his DocuSign account with his DMS account. So that when User A sends out the signing request from our DMS, the signer receives the email from DocuSign showing it is from that user instead of the common admin account.
Also, it looks like the go-live process would have to take place for each customer that is using our DMS? Does it mean like each customer need to have their DocuSign developer account so that the integration key can get promoted to production environment? Or am I in the wrong direction & should look at Partner Integration as ISV?
If your DMS system is a SAAS system, then you can have 1 integration key (client id) for your integration with DocuSign. In other words, your individual customers would NOT have their own integration keys, secrets, etc.
One integration key is the best, if your application's architecture can support it. To do so, you'll want to have one or just a few Redirect URIs to enable your users (who also have DocuSign accounts) to authenticate with DocuSign.
Your app then stores the resulting access token, refresh token, and expiration date for each of your users who have authenticated with DocuSign.
This way, as you say, when your users send out an envelope for signing, it will belong to their own DocuSign account, and will show them as the sender.
When your customer wants to send via DocuSign, your app checks the expiration date for the person's access token. If the access token has expired, then use the refresh token to get a new access token and a new refresh token.
The refresh token is stored in your app's non-volatile storage (encrypted is best) so you can use it days or weeks later for the user. That way they don't have to re-authenticate with DocuSign. For this case, use scopes signature%20extended
For the account_id info, use the user's default account and enable them to switch to another account if they wish.
More information:
Getting started for ISVs
API integration guidelines

OAuth Flow for Sender Using Apex Toolkit

I've developed an invokable Apex method that leverages the DocuSign Apex Toolkit for preparing and sending an envelope via a Salesforce flow.
The only issue I'm having is when it is invoked by a Salesforce user, that has been added as a DocuSign user, but has not yet gone through the OAuth flow to connect Salesforce to DocuSign for their user account.
A workaround is that I have that new user click a standard "Send with DocuSign" button an any record, which then shows the "Before you can use DocuSign, you must grant consent for this application to make requests on your behalf." message and a button to start and complete the OAuth flow. Once this is done I can go back to my flow and it will successfully complete as that user.
Any ideas how I can "pre-authorize" users, or check for authorization as part of the flow (is this data stored in Salesforce), or at least find a way to get to this "Authorize" screen in Salesforce without needing to begin the process of sending an envelope?
Thanks
Matt
Yes, the administrator for the account can grant "blanket" consent, known as administrative consent, for the relevant integration key (client id) and scope(s) needed by your application.
To do so:
The account needs the Admin feature Access Management with SSO You can have this feature enabled for your developer sandbox account by email request to go-live#docusign.com. Contact your DocuSign account manager for adding the feature to a production account.
You need to claim the email domain for your users.
Use the Admin tool's Connected Apps tile to grant administrative consent to your users in the claimed to domain to the application.
The above assumes that you are supplying the integration key to your Apex application.
If you're using an integration key supplied by DocuSign, then you also need to use the Admin consent for external applications API.
If you're using an integration key supplied by DocuSign as part of a DocuSign for Salesforce product, then I would first ensure that the product is enabled for everyone in your account; that may take care of your app's consent issue.
Re: detecting if consent is required
DocuSign responds with a specific consent_required error if consent is needed. So check the error response of your call. See APIError

DocuSign - OAuth Authorization Code Grant - Multiple Users - Error while fetching Access and Refresh Token

We are trying to integrate DocuSign with our product.
Our Scenario: Our organization has a (partner) account. We created an Integrator Key (ClientID) and Secret. We want our clients to use their own accounts (which are not child accounts (Admin - user relationship) to our partner account) for the creation of envelopes and generate signing URLs along with our integrator key and secret.
Steps followed:
Created an account (Partner Account).
Created Integrator Key and Secret.
Our scenario is considered as User Application and using Authorization Code Grant Mechanism to get the auth code.
Clients are redirected to DocuSign portal for getting authenticated. (using authorization code grant mechanism by passing our integrator key as a parameter)
Client grant consent for our application to use their credentials for the creation of envelopes.
Receive the auth code.
Using clients authcode and Partner accounts Integrator Key & Secret, trying to fetch the refresh and access token. But DocuSign API (OAuth/token) is responding back with "Bad Request" (400) as response.
In place of the client account, if we are using same partner account credentials, then API (OAuth/token) is responding back with correct refresh token and access token.
Question: Can an integrator key and secret of one account be used along with the auth code of another account (both accounts doesn't have any relationship(Admin-User)) for fetching the Access token & Refresh Token.
API's Used:
Get Auth Code - https://account-d.docusign.com/oauth/auth (Partner Account (Integrator Key & Secret) & Client user credentials in DocuSign Portal)
Get Access / Refresh Token - https://account-d.docusign.com/oauth/token (Auth Code from previous response & base64(Integrator Key:Secret))
Reason: we don't want to store user credentials or ask users to log in every time when they want to use their DocuSign account in our application. So we want to get consent from a user and store their refresh token with us. Use their refresh token and our integrator key from next time for calling DocuSign API's.
Update
(I work at DocuSign.)
Via additional information supplied to DocuSign, we were able to find our internal logs for the OP's OAuth transaction that failed. We could see from the internal log that, indeed, the problem was that the Authorization Code had expired.
During an OAuth flow, as soon as an application receives an authorization code, it should immediately turn around and use it to get the Access and Refresh tokens, and related information. We will be updating our documentation to state this issue clearly.
Original answer
Everything you're doing sounds exactly right. Especially since the user is receiving the permission screen the first time after logging in to DocuSign via your application.
To answer your question directly: yes, a client id (Integration Key) can be used by an app for any DocuSign user on any DocuSign account.
One idea: is your application requesting the tokens immediately after receiving the authorization code? The authorization code itself times out after a couple of minutes.
You're saying that if User A logs in it works (User A belongs to the account that manages the Client ID), but if User B logs in it doesn't work? I haven't seen that issue before. I'd create a new demo developer sandbox with User C and have them try to login.
Is all of this on demo or production?

Retrieving an access token with admin consent : how access the data of all the users of the organization?

In my third-party web application of Office 365, I want to have access to the contacts, events and emails of all the users from the organizations who installed my app.
The thing is I don't want that all these users have to grant me access, I just want one admin of the org to grant access for my app and then be able to retrieve the data I need for all the users.
To test for one organization, I logged in as the admin and proceed to the Oauth2 authentication to retrieve the access token and in the first request (the GET one to retrieve an authorization code) i add the parameter prompt=admin_consent.
With this access token, I can access the data (emails, contact, event) of the admin
for instance for the contacts
uri: https://outlook.office365.com/ews/odata/Users(adminemail)/Contacts
but not the data of the other users of this org with this uri
uri: https://outlook.office365.com/ews/odata/Users(useremail)/Contacts
The only thing I can do is retrieve an access token for each user but it supposed that each user has to authorize the access to the app but it's very cumbersome.
So, i don't see what enables the parameter prompt=admin_consent and how to use it. Does anybody know what it does?
And my question is: how can I do to access the data of all the users of one organization when the access has been granted by one admin?
Thank you!
Thanks for your question! The scenario you are interested in (an app accessing data of all users of an organization once an admin grants access to the list) is not yet supported but is prioritized high on our list of features to add.
[UPDATE] Support for app accessing data of all users in a tenant is supported for Office 365 Mail, Calendar and Contact REST APIs. Please see Building Daemon or Service Apps with Office 365 Mail, Calendar, and Contacts APIs (OAuth2 client credential flow) for more info.
The scenario prompt=admin_consent is intended for, is different from your scenario. Admin consent simply means that the admin allows this app in the organization without the individual user to see the consent screen after signing on to the app. This special "I as the admin provide consent for this app on behalf of all my users" is triggered by the "prompt=admin_consent" parameter that is passed in during the authorize request. However, this doesn't allow the app to get AccessTokens for any user. Each user still has to get the app, sign in, and the app will hit the authorize endpoint and get a Refresh/AccessToken for the signed in user.
Please let me know if you have any questions or need more info.
Thanks,
Venkat

Resources