What are the best practises using Docusign's 0Auth API? - node.js

I'm using authentication code mechanism through Docusign's API for integration and works as expected.
Have a question regarding the documentation about implementation best practises, described in this page
Questions are related to the diagram at the end:
Question1
In Get the user's account ID, base URL and name (1st square) how do you recommend fetching the user/account information as before consent we don't know who is giving consent?
If it is related to users that may have given consent before, is it even necessary? If tokens already exist for the user, what is the purpose of verifying this scenario?
In the documentation it seems this is reinforced further with what is stated next:
How will we know what is the account/user information before the user gives consent?
Question2 (Similar to above)
In Collect the account ID (GUID) and name of the user, when no access token is found, I'm assuming we should redirect the user immediately so that the use gives consent again. Similar to the question above, in the diagram it indicates we should do this action "Collect account/user info" somehow before redirect for consent? We only know it afterwards as well, so is it needed?
It would be great if it would be possible to clarify the above!

As Inbar commented, that diagram needs some work. I'm sorry for the confusion.
Here's my recommendations for user present (Authorization Code and Implicit grant flows) and user absent (JWT grant flow).
All authorization flows
Determine if your users will typically use your application with a particular eSignature account or with any of their accounts. (It is common for customers to have access to more than one DocuSign eSignature account.)
If a particular account will be used, then provide an installation screen for your app where the admin can enter the account ID (use the guid format).
Your installation screen should also enable the installer to set
the DocuSign OAuth service provider, either production account.docusign.com or demo account-d.docusign.com
User present: Authorization Code and Implicit grant flows
Your app may or may not have its own login sequence for users. Your app needs a DocuSign access token for making API calls to DocuSign APIs.
When your user wants to authenticate with DocuSign:
Start the Authorization Code or Implicit grant flow.
When the flow is done, your app has an access token.
If the Authorization Code grant flow was used then you also have a refresh token.
Use the oauth/userinfo API call to obtain information about the user:
Their name and email
The eSignature accounts they have access too, and which of those accounts is the user's default account
For each account, the name of the account and the baseUrl for making API calls to the account.
If your app's users use a preferred account, then check that the user has access to the preferred account. Else, note the account id of the user's default account. (Also be prepared to handle the cases where there is either no userinfo response, no account or no default account for the user. These are infrequent DocuSign errors and can be fixed by contacting DocuSign Customer Support and referencing this article.
Use the expires_in OAuth response attribute to calculate your expires datetime. Then subtract 10 minutes so you have a buffer between the time you'll last use the access token and when it actually expires. You now have the last_use time.
Store the user's information, including the account id, base url for the account, access token, and last_use datetime.
If you have a refresh token, store it (and the user's information) in non-volatile storage.
When your application wants to make an API call
If you have a current access token for the user (last_use datetime is after the current datetime) then use it.
If the last_use time has passed, then use the refresh token if you have it. When refreshing the toke, you'll receive a new refresh token. Store it in non-volatile storage, overwriting the prior refresh token.
If no refresh token, then your app will need to ask the user to authenticate again.
Do not use oauth/userinfo again after either the token was refreshed or the user authenticated again. Keep and use the userinfo obtained after the person first logged in.
When your user wants to use a different account
Provide a "Switch accounts" feature to enable users to choose which of their accounts should be used. (Only applies if any account can be used with the application.)
User not-present: JWT grant
Your app's configuration screen will also need the user id in guid form. You can either store these values or look them up from DocuSign.
Decide whether a specific account is needed or not (see above).
Decide how the user will grant consent. See this video for more info.
First time your app needs an access token after a reboot
Use the JWT user grant to obtain an access token
As above, calculate the last_use datetime including a 10 minute buffer.
Use oauth/userinfo as above to determine if the user has access
the account or what the user's default account is. Also obtain the account's base_url.
Store the information.
Use the access token to make the API call.
Subsequent API calls
Check the last_use datetime. If it hasn't yet occurred then use the stored access token. If it has occured, then redo the JWT user grant flow but do not make another oauth/userinfo call--use the prior information.

Question 1 - You do not need to remember which user gave consent. That is not something you should do anyway, because users can revoke consent and then your information will be inaccurate. The system will ask for consent if needed (and if you ask for additional scopes it may be needed even if consent was given for example).
Question 2 - You should redirect immediately, whether consent is needed or not is unclear, but the user will either have to login, or just redirected if they have a cookie and consent is also based on their circumstances.
I'll consent (no pun intended) that we can improve this diagram and make it easier to understand. I would suggest implementing a simple scenario first and seeing how it work before moving on to the more advanced scenario (by simple I mean every time a user need to log in as if it was their first time).

Related

Why doesn't Docusign revoke block access to my app?

My app is using JWT with individual consent. When, as a customer, I go to the Connected Apps screen at https://account-d.docusign.com/me/appconsent and revoke access to my app, the app still keeps working fine. No Docusign API calls fail, I can still create envelopes. Why? Is there another way to revoke?
The documentation page at https://developers.docusign.com/platform/auth/consent/ says "In cases where user consent was provided by an organization administrator (such as the JWT Grant), this consent can be revoked with the DocuSign Admin tool." But there is no link with more if about this "Admin tool" and I can't find it, and I don't think this applies in my case since I'm using individual consent.
I believe that the next time the app tries to use JWT to obtain an access token, it will fail.
But the already in use access token will continue to work until it expires at the end of its one hour lifetime.
If your experimentation doesn't support the above, please update your question.

DocuSign: How to get an authorization code programatically

I have a vuejs SPA. Users have their own accounts with a dashboard. On the dashboard, is a section for PDF signing. All users should have the same PDF displayed, but with their name pre-filled on the PDF, and then 4 spots to sign.
Right now I am stuck on the first part for using the API....which is the auth code.
Why does it seem that the tutorial I followed, requires the owner of the DocuSign account to login and grant rights? I had to do something similar to https://account-d.docusign.com/oauth/auth?response_type=code&scope=signature&client_id=5665656-3506-46fa-b46d-f6acf3b59268&redirect_uri=https://www.google.com and I got a code in return....but how am I even suppose to implement this for my web app?
How do I get the auth code in the background....meaning...I cant have all users go to this URL...am I supposed to do it via ajax GET? I was able to use a correctly formatted URL, but I got the response by visiting the URL in my browser...how can I do this programmatically?
I dont get the granting rights part....because there is no way this would be practical where all the users would have to know my private DocuSign account info?
Of the (3) oauth methods, which is best for my scenario? Authorization Code Grant, Implicit Grant, or JWT Grant
Auth Code Grant was meant for interactive scenarios. It requires UI and a web interface. It cannot be used without UI. Once you have the initial access token, there's a refresh token to be able to obtain a new one without UI, but the initial call requires UI.
The users don't have to know your account info, your account info may not be relevant. The user grant a right to your app/integration to make API calls. That is not your account, it is different. It's a clientId/integration key that you use your account to create, but it can be used with any DocuSign user/account.
JWT would allow for what you asked in #1 but only after a one-time consent was provided (What you asked in #2) by the end-user. You have to do that for users to enable DocuSign to make API calls on their behalf.
Final word, signers do not need an account in DocuSign. I don't know what you're building, but if your end-user just signs - they don't need an account and a lot of 1-3 is moot.

Why do access tokens issued by AAD contain information about the user?

I read a lot about OAuth 2.0 and OpenId Connect and in theory I understand both concepts now.
But if I go into practice, some things are still confusing for me and I hope you can enlighten me in some way...
First thing is, that in all code samples how to secure a .net core API in an AAD-environment I find lines like this in the configure-section:
app.UseAuthentication()
and lines like this in the ConfigureServices section:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = "https://login.microsoftonline.com/xxxxxxxx";
options.Audience = "xxxx-xxx-xxx-xxx-xxxx";
});
However, to access my API I am not using an ID token, but an access token what is Authorization, not "Authentication" like in the code samples.
This works - but I do not understand it 100%.
So my first question is:
Is the access token also "authenticating" in some way?
The second thing:
I read that access tokens have no standardized format. They can be JWT or not, can have an audience or not etc. For this reason you could even put user information in the token like microsoft does. The access tokens contain claims like a "family name" or "given name" etc.
Id tokens in contrast have a standardized format to ensure that authentication is done in the same way by everyone.
If people are accessing my apis with an access token, I can read their name or e-mail address with "user.identity.name" for example. This value I can use to store the information who edited something or who inserted something.
So I am fetching information about the user with access tokens!
So my second question is:
Am I doing the right thing here? Or should this be done in another way.
and:
Should access tokens ever contain information about the user?
Is the access token also "authenticating" in some way?
Yes.
Your API is validating the access token when it receives it.
This is the authentication part, when your API verifies that the token signature is valid, came from the Azure AD tenant that you trust, that it is meant for your API and that it has not expired.
The authorization is when you check what permissions the token contains.
Your API can define different permissions that are given to client applications, allowing them different levels of access.
A valid token can pass authentication, but it might not pass authorization if it lacks the necessary permissions.
Am I doing the right thing here? Or should this be done in another way.
Fundamentally your are doing the correct thing.
The token tells you who the user is that is using the client application, and if you need to know who it was who did something, that's the info you use.
However, if you really want to connect an action to a user, I suggest you use their object identifier / object id / oid instead of their name / username as those can change.
Unless you just want their display name.
Should access tokens ever contain information about the user?
In the context of Azure AD, an access token will always contain info about the user if a client application is accessing an API on behalf of a user.
This includes authentication flows like authorization code, device code, implicit, and on-behalf-of.
They all use delegated permissions aka scopes to call APIs on behalf of the user.
Thus the token contains info about the calling app and the user.
If an app acquires an access token using the client credentials flow where a user is not involved, there will be no user info in the token.
In this case, application permissions are used instead of delegated permissions in Azure AD.
An application acts as itself, not on behalf of any user.
If your API supports both of these scenarios, sometimes the tokens contain user info and sometimes not.
The part about token formats is basically correct from a specification standpoint.
OAuth doesn't define a strict format for access tokens, while OpenID Connect does define one for ID tokens.
Using an access token to call your API is definitely correct.
The ID token is only meant for the app that initiated the user authentication, not for any APIs that it calls.
That's what access tokens are for.
if you check here: https://learn.microsoft.com/en-us/azure/active-directory/develop/access-tokens
in the newer access tokens, by default it follows the standard of not having any personal information about the user. which is what the standards suggest, Access tokens should not contain much or any information About the user. rather just information for authorization (things that user can access).
However you can always add the optional claims (and azure lets you do it) for personal info, but best practice suggests you shouldn't.
in terms of the addauthentication: Authentication is basically proving who you say you are. addauthentication(), basically calls microsoft azure ad to perform this task, saying hey aad please ask this person who he is, azure then checks and says ya this is a real person, but i won't tell you anything about him other than an id, and they have access to your api/application. So from your snippit, it's fine.
at this point, your serverside shouldn't have any personal information about the user, just that they have access and what scopes/roles. If it wants info about the user, it should then take that authorization (access token) and request it from whatever endpoint that token has access to (graph)
here's a great read about it: https://auth0.com/blog/why-should-use-accesstokens-to-secure-an-api/
Hopefully this helped clarify somewhat, and not add more confusion to the issue.

DocuSign Service Integration: Authorization Code human action

One of the steps to authorize our application to access our DocuSign account requires a human to navigate to the oauth service (https://account-d.docusign.com/oauth/auth?response_type=code&scope=signature%20impersonation&client_id=...) then login to the account, and grant it access.
I've seen some references throughout the developer portal about this being something that will need done multiple times, and I've also seen it written on the same site that it only needs to be done once (the site is actually fraught with contradicting information).
Does anyone know if this step will need to be done more than once? It makes sense to me that it should NOT.
Much appreciated!
Chris
You are referring to https://docs.docusign.com/esign/guide/authentication/oa2_auth_code.html and it is a correct place for documentation for DocuSign. Now with above flow, you get two types of tokens i.e AccessToken and Refresh Token. If Access Token expires then you can use refresh token to get new set of access and refresh token and it does not need any consent from the user or a human action, it can be done using DocuSign OAUTH API from backend. But if the response to the refresh operation is an error, or if the new access token’s expires_in value is less than your threshold, you will need to repeat the initial authentication flow. So you need to do proper exception/error handling before taking user back to the consent/OAuth login page.

Manual generating OAuth Access tokens

I am looking to using OAuth to secure some web services. OAuth 2 fits nicely for the use cases I have where the user might access his/her own data using API's or grant access to someone to call API's on his behalf.
However, the initial set of API users are not very technical and they would not want to go through the effort of making API calls just to generate tokens. I am thinking of implementing the following solution but am not sure if this is the right way.
If the user is a developer, then
Have a screen where he/she can register an application. This will generate an API key/secret pair.
To access his/her own data (For 2 legged Auth) have a UI screen where the user can generate a access token for one his registered applications. He can specify the scopes and duration in the form.
If he is a 3rd party developer, then he needs to pass his applications API key to the person on whose behalf he needs to access the API and get an access token in exchange.
If the user wants a another application/developer to access API's on his behalf then
Have a screen where he can enter the third party's API key, scopes and the duration of the authorization. He can pass the generated access token to the developer who'll access the API's
I am going to use same OAuth libraries to generate the token that I would have used if I had gone the web service route. Further, I can also develop services whenever the current situation doesn't scale or the need arises and the existing tokens would still work.
The problem is mainly one of security. By design, duration of access token should not be set by a client. If someone else gets to know the access token and client id during this duration, this user's account will be compromised. Normally this duration is set to be not very long and a second secret value refresh token is used to refresh the current access token. The token refreshing can be automated in code, but in your approach it will need to be done manually.

Resources