Python wrapper of Public API suddenly stopped working


We are using a containerized python tool to automate some collection management stuff, and it suddenly stopped working. The code looks like that :

from oauthlib.oauth2 import BackendApplicationClient
from requests_oauthlib import OAuth2Session
from atolcd import config

class Bitwarden:

  def __init__(self):
    self.organization_id=config.get('bitwarden', 'organization_id')
    self.client_id='organization.' + self.organization_id
    self.client_secret=config.get('bitwarden', 'client_secret')
    # these 3 lines are tasked to retrieve secrets from a local config files. Works just fine, the value is properly retrieved and up to date.

    oauthclient = BackendApplicationClient(client_id=self.client_id)
    self.client.fetch_token(token_url='', client_id=self.client_id, client_secret=self.client_secret, include_client_id=True)

As of today, when executing this, it fails on the last line, with the following stacktrace :

File "/usr/local/lib/python3.11/site-packages/atolcd/", line 21, in __init__
    self.client.fetch_token(token_url='', client_id=self.client_id, client_secret=self.client_secret, include_client_id=True)
  File "/usr/local/lib/python3.11/site-packages/requests_oauthlib/", line 366, in fetch_token
    self._client.parse_request_body_response(r.text, scope=self.scope)
  File "/usr/local/lib/python3.11/site-packages/oauthlib/oauth2/rfc6749/clients/", line 427, in parse_request_body_response
    self.token = parse_token_response(body, scope=scope)
  File "/usr/local/lib/python3.11/site-packages/oauthlib/oauth2/rfc6749/", line 441, in parse_token_response
  File "/usr/local/lib/python3.11/site-packages/oauthlib/oauth2/rfc6749/", line 451, in validate_token_parameters
    raise MissingTokenError(description="Missing access token parameter.")
oauthlib.oauth2.rfc6749.errors.MissingTokenError: (missing_token) Missing access token parameter.

I thought of a change in Bitwarden’s Public API authentication workflow, but it doesn’t seem so. Going through the doc’s CURL call with our own client_id/_secret works just fine. I’m a perfect noob in terms of OAuth and stuff, but from what I understand, the token is delivered for requests with :

  • valid client_id and client_secret (as we saw, it is)
  • grant_type is client_credentials (turns out it is implemented by this BackendApplicationClient thingy in python’s oauthlib)
  • scope is scope=api.organization ==> this might be the missing bit here.

If I understand correctly, the Missing access token parameter simply states that the API’s answer don’t contain the expected field. This is probably due to the API answering 401 unauthorized or something like that. Since I’m using valid client values and apparently valid grant_type, the only thing I’m not explicitly specifying is the scope.

However, removing the scope from the working CURL request does not result in a fail call, the access token is properly sent back. Plus, we never had to specify the scope so far, and the API doc hasnt change for a while now.

What am I missing ?

PS : apologies for the “app:cli” tag, I’m obviously not using the CLI here, but Discourse want me to add at least two tags, and it doesnt seem to have an API tag that I could use.

Hey @ImplicitDny,

If you don’t get a response here from anyone familiar with the API, or you’d just like to go ahead feel free to always reach out and contact the official Bitwarden support team.

Well, I resumed my work on this topic this morning, and it worked first try without changing anything to our code. I guess it was a hiccup of some sort on the API side and is fixed now.

Thanks anyway @cksapp !

Glad to hear it’s working now!
Didn’t see anything specific to the Status page, but like you said could have just been some odd “hiccup” somewhere along the line.