Lous
Lous

Reputation: 45

How to get an access token with Authorization Code Grant, DocuSign

Im trying to get the token with oauth2 authorization since I will need it to an automation project.

Following Step 1 from the DocuSign webpage tutorial (https://developers.docusign.com/platform/auth/authcode/authcode-get-token/), I have the following code:

get_params = {'response_type': 'code', 'scope': 'signature', 'client_id': 'my_client_id', 'redirect_uri': 'https://localhost:3000'}
get_r = requests.get(url="https://account-d.docusign.com/oauth/auth?", params=get_params)
get_r.raise_for_status()
print(get_r.text)

The response I obtain is an HTML, but I want the URL with the authorization code.

I have seen similar questions (Python Requests library redirect new url), but none of them seem to work form me.

How could I obtain the URL with the authorization code?

EDITED: Right now I have implemented the following code, which returns a token.

from os import getenv
from typing import List

import requests
from dotenv import load_dotenv
from oauthlib.oauth2 import BackendApplicationClient
from requests_oauthlib import OAuth2Session

def get_token() -> str:
    """Get access token from Docusign API using a client ID and its secret.

    More info on https://requests-oauthlib.readthedocs.io/en/latest/oauth2_workflow.html#backend-application-flow
    """
    client_id = getenv("DOCUSIGN_CLIENT_ID")
    client_secret = getenv("DOCUSIGN_CLIENT_SECRET")
    token_url = getenv("DOCUSIGN_TOKEN_URL")
    client = BackendApplicationClient(client_id=client_id)
    oauth = OAuth2Session(client=client)
    token = oauth.fetch_token(
        token_url=token_url,\
        client_id=client_id,
        client_secret=client_secret
    )
    return "Bearer " + token["access_token"]

I am trying to use this token to return the list of the templates a certain user (that corresponds with the given token we have just obtained) has.

def list_templates(token: str) -> List[str]:
    """" Make a list of all the templates that a user, that corresponds to the token proportioned as input, has. """

    get_params = {'search_text': 'Test_3'}
    get_headers = {'Authorization': token}
    get_r = requests.get(url="https://demo.docusign.net/restapi/v2.1/accounts/MY_API_ACCOUNT_ID/templates", params=get_params, headers=get_headers)
    get_r.raise_for_status()
    data = get_r.json()
    data_templates = data['envelopeTemplates']
    list_templates = []

    for inner_data in data_templates:
        for relevant_data_key, relevant_data_value in inner_data.items():
            if relevant_data_key == 'name':
                list_templates.append(relevant_data_value)

    return list_templates

def main():
    load_dotenv(dotenv_path=".env", override=True, verbose=True)

    token = get_token()
    templates = list_templates(token=token)


if __name__ == '__main__':
    main()

NOTE: In function list_templates(), when doing the GET request, we must put the correct API account ID in the URL

But I seems that the token is not valid. On the other hand, when obtaining the token manually and using it as an imput, it works perfectly!

Does someone know why I am not obtaining the correct token?

Thanks :)

Upvotes: 0

Views: 1431

Answers (2)

Larry K
Larry K

Reputation: 49104

The OAuth Authorization Code grant flow is complicated. Security experts recommend that developers should not implement it themselves if a library is available.

See Ben's answer for a suggested library to use.

In addition:

  1. You need to supply your client ID (the integration key). Your code shows that you're supplying the string "my_client_id" instead.
  2. You should be getting back html--that's the authentication page that will be completed by the user. To put it another way, the first step for the Authorization Code grant flow is to redirect the user's browser to the URL that you've constructed. Your code appears to be making its own GET request to the authentication URL, that's not right.
  3. You're missing the state parameter. While it's not required, security experts recommend that it be included, with a nonce value. Your app should also store the state value and compare it with the one returned when you exchange the authorization code for an access token. This prevents one type of attack.

Upvotes: 2

bendowlingtech
bendowlingtech

Reputation: 494

Easiest way to do this is to use Request-OAuthlib There's a full example with the Oauth 2 workflow.

Upvotes: 1

Related Questions