title: Google user listing with service account using Python
body: <p>I have a Json service file, and a service account that already accesses translate and sheets, but it will not access user lists. The result is either 400 showing its confused or 401 saying its not authorized. Examples are usually about client involved OAuth processes, where I need server to server. I have enabled that &quot;Enable G Suite domain-wide delegation&quot; feature on the service account too.</p>
  <p>I read and tried the JWT method, but I get the same error responses.
  <a href="https://developers.google.com/identity/protocols/oauth2/service-account#python_2" rel="nofollow noreferrer">https://developers.google.com/identity/protocols/oauth2/service-account#python_2</a></p>
  <p>My goal is to call either one of these end points
  <a href="https://www.googleapis.com/admin/directory/v1/users" rel="nofollow noreferrer">https://www.googleapis.com/admin/directory/v1/users</a>
  <a href="https://www.googleapis.com/admin/directory/v1/users.readonly" rel="nofollow noreferrer">https://www.googleapis.com/admin/directory/v1/users.readonly</a></p>
  <p>Any direction would be greatly appreciated.</p>
  <p>UPDATE1:
  This is using the Jwt token approach which yields error 401.</p>
  <pre><code>with open(CLIENT_SECRET_FILE, &quot;r+&quot;) as fh:
      config = json.load(fh)
  
  iat = time.time()
  exp = iat + 3600
  payload = {'iss': config['client_email'],
             'sub': config['client_email'],
             'aud': 'https://www.googleapis.com/',
             'iat': iat,
             'exp': exp}
  additional_headers = {'kid': config['private_key_id']}
  signed_jwt = jwt.encode(payload, config['private_key'], headers=additional_headers,
                          algorithm='RS256')
  
  url = 'https://www.googleapis.com/admin/directory/v1/users'        
  headers = {&quot;Authorization&quot;: &quot;Bearer &quot; + signed_jwt}
  r = requests.get(url, headers=headers)
  </code></pre>
  <p>I have also tried</p>
  <pre><code>scopes = ['https://www.googleapis.com/auth/admin.directory.user']
  credentials = ServiceAccountCredentials.from_json_keyfile_name(CLIENT_SECRET_FILE, scopes=scopes)
  service = build('admin', 'directory_v1', credentials=credentials)
  results = service.users().list().execute()
  </code></pre>
  <p>UPDATE2:
  This link has great information and simple code to review. As much as I tried to avoid impersonation, the AdminSDK requires it. That makes integrations a bit awkward in my view. In addition, the issue I also faced was the Domain-Wide-Delegation screen in the Google Workspace Admin can get messed up. Deleting the entry and recreating it fixed the forever 403 error I kept getting no matter what I had tried.
  <a href="https://gist.github.com/lewisrodgers/fa766ebd37c1397d3a014eb73805edd1" rel="nofollow noreferrer">https://gist.github.com/lewisrodgers/fa766ebd37c1397d3a014eb73805edd1</a></p>