title: oauth2session dynamics365 : keep receiving Error 401 Unatuthorized
body: <h1>The use case</h1>
  <p>I am trying to connect to Microsoft Dynamics 365 - Field Service.</p>
  <p>I am using Python, Falsk and OAuth2Session to perform a Oauth2 authentication</p>
  <p>I have setup the Azure App on Azure.</p>
  <h1>the error message</h1>
  <p>I keep receiving the HTTP Error 401</p>
  <p>Who could help me?</p>
  <h1>the code : config.py</h1>
  <pre class="lang-py prettyprint-override"><code>
  &quot;&quot;&quot;Configuration settings for running the Python auth samples locally.
  
  In a production deployment, this information should be saved in a database or
  other secure storage mechanism.
  &quot;&quot;&quot;
  
  import os
  from dotenv import load_dotenv
  
  load_dotenv()
  
  CLIENT_ID = os.environ[&quot;dynamics365_field_service_application_client_id&quot;]
  CLIENT_SECRET = os.environ[&quot;dynamics365_field_service_client_secrets&quot;]
  REDIRECT_URI = os.environ[&quot;dynamics365_field_service_redirect_path&quot;]
  
  # AUTHORITY_URL ending determines type of account that can be authenticated:
  # /organizations = organizational accounts only
  # /consumers = MSAs only (Microsoft Accounts - Live.com, Hotmail.com, etc.)
  # /common = allow both types of accounts
  
  AUTHORITY_URL = os.environ[&quot;dynamics365_field_service_authority&quot;]
  AUTHORIZATION_BASE_URL = os.environ[&quot;dynamics365_field_service_authorization_base_url&quot;]
  TOKEN_URL = os.environ[&quot;dynamics365_field_service_token_url&quot;]
  
  AUTH_ENDPOINT = &quot;/oauth2/v2.0/authorize&quot;
  
  
  RESOURCE = &quot;https://graph.microsoft.com/&quot;
  API_VERSION = os.environ[&quot;dynamics365_field_service_version&quot;]
  SCOPES = [
      &quot;https://admin.services.crm.dynamics.com/user_impersonation&quot;
  ]
  
  
  
  
  #     &quot;https://dynamics.microsoft.com/business-central/overview/user_impersonation&quot;,
  #     &quot;https://graph.microsoft.com/email&quot;,
  #     &quot;https://graph.microsoft.com/offline_access&quot;,
  #     &quot;https://graph.microsoft.com/openid&quot;,
  #     &quot;https://graph.microsoft.com/profile&quot;,
  #     &quot;https://graph.microsoft.com/User.Read&quot;,
  #     &quot;https://graph.microsoft.com/User.ReadBasic.All&quot;
  # ]  # Add other scopes/permissions as needed.
  
  
  </code></pre>
  <h1>the code : dynamics365_flask_oauth2.py</h1>
  <pre class="lang-py prettyprint-override"><code>
  # *-* coding:utf-8 *-*
  
  # See https://requests-oauthlib.readthedocs.io/en/latest/index.html
  
  from requests_oauthlib import OAuth2Session
  from flask import Flask, request, redirect, session, url_for
  from flask.json import jsonify
  import os
  
  import flaskr.library.dynamics365.field_service.config as config
  
  app = Flask(__name__)
  app.secret_key = os.urandom(24)
  
  # This information is obtained upon registration of a new dynamics
  # client_id = &quot;&lt;your client key&gt;&quot;
  # client_secret = &quot;&lt;your client secret&gt;&quot;
  # authorization_base_url = 'https://dynamics.com/login/oauth/authorize'
  # token_url = 'https://dynamics.com/login/oauth/access_token'
  
  
  @app.route(&quot;/&quot;)
  def index():
      &quot;&quot;&quot;Step 1: User Authorization.
  
      Redirect the user/resource owner to the OAuth provider (i.e. dynamics)
      using an URL with a few key OAuth parameters.
      &quot;&quot;&quot;
      dynamics = OAuth2Session(
          config.CLIENT_ID, scope=config.SCOPES, redirect_uri=config.REDIRECT_URI
      )
      authorization_url, state = dynamics.authorization_url(config.AUTHORIZATION_BASE_URL)
  
      # State is used to prevent CSRF, keep this for later.
      session[&quot;oauth_state&quot;] = state
  
      print(f&quot;Please go here and authorize : {authorization_url}&quot;)
      return redirect(authorization_url)
  
  
  # Step 2: User authorization, this happens on the provider.
  
  
  @app.route(&quot;/login/authorized&quot;, methods=[&quot;GET&quot;])  # callback
  def callback():
      &quot;&quot;&quot; Step 3: Retrieving an access token.
  
      The user has been redirected back from the provider to your registered
      callback URL. With this redirection comes an authorization code included
      in the redirect URL. We will use that to obtain an access token.
      &quot;&quot;&quot;
  
      if session.get(&quot;oauth_state&quot;) is None:
          return redirect(url_for(&quot;.index&quot;))
  
      dynamics = OAuth2Session(
          config.CLIENT_ID, state=session[&quot;oauth_state&quot;], redirect_uri=config.REDIRECT_URI
      )
  
      token = dynamics.fetch_token(
          token_url=config.TOKEN_URL,
          client_secret=config.CLIENT_SECRET,
          authorization_response=request.url,
      )
      print(f&quot;token: {token}&quot;)
      # At this point you can fetch protected resources but lets save
      # the token and show how this is done from a persisted token
      # in /profile.
      session[&quot;oauth_token&quot;] = token
  
      # return redirect(url_for(&quot;.dynamics_get_accounts_postman&quot;))
  
      return redirect(url_for(&quot;.dynamics_get_accounts&quot;))
  
  
  @app.route(&quot;/profile&quot;, methods=[&quot;GET&quot;])
  def profile():
      &quot;&quot;&quot;Fetching a protected resource using an OAuth 2 token.
      &quot;&quot;&quot;
      dynamics = OAuth2Session(config.CLIENT_ID, token=session[&quot;oauth_token&quot;])
      return jsonify(dynamics.get(&quot;https://api.dynamics.com/user&quot;).json())
  
  
  @app.route(&quot;/get_accounts&quot;)
  def dynamics_get_accounts():
  
      if session.get(&quot;oauth_token&quot;) is None:
          return redirect(url_for(&quot;.index&quot;))
  
      dynamics = OAuth2Session(
          client_id=config.CLIENT_ID,
          # token=&quot;Bearer &quot; + session[&quot;oauth_token&quot;][&quot;access_token&quot;]
          token=session[&quot;oauth_token&quot;],
      )
  
      result = dynamics.get(&quot;https://{env_name}.{region}.dynamics.com/api/data/v9.0&quot;)
  
      if result.status_code != 200:
          result = {&quot;status code&quot;: result.status_code, &quot;reason&quot;: result.reason}
      else:
          result = result.json()
  
      result = jsonify(result)
      return result
  
  
  import requests
  
  
  @app.route(&quot;/dynamics_get_accounts_postman&quot;)
  def dynamics_get_accounts_postman():
  
      if session.get(&quot;oauth_token&quot;) is None:
  
          return redirect(url_for(&quot;.index&quot;))
  
      url = &quot;https://{env_name}.{region}.dynamics.com/api/data/v9.0/accounts&quot;
  
      payload = {}
      headers = {
          &quot;Accept&quot;: &quot;application/json&quot;,
          &quot;OData-MaxVersion&quot;: &quot;4.0&quot;,
          &quot;OData-Version&quot;: &quot;4.0&quot;,
          &quot;If-None-Match&quot;: &quot;null&quot;,
          &quot;Authorization&quot;: f'Bearer {session[&quot;oauth_token&quot;][&quot;access_token&quot;]}',
      }
  
      response = requests.request(&quot;GET&quot;, url, headers=headers, data=payload)
  
      result = response.text.encode(&quot;utf8&quot;)
      print(f&quot;result : {result}&quot;)
  
      return jsonify(result)
  
  
  if __name__ == &quot;__main__&quot;:
      # This allows us to use a plain HTTP callback
      os.environ[&quot;DEBUG&quot;] = &quot;1&quot;
  
      app.secret_key = os.urandom(24)
      app.run(debug=True)
  
  </code></pre>