Python script with Bearer Token and App Password

Hi,

I’m working on a python script that allow me to import some data into a plugin with HTTP request.

The script works, I can make my request with Basic Authentication. After several month, one user was not working anymore and I didn’t understand why. When I looked at the log, I understood that it was because of the authentication. Nextcloud wait a “Bearer token” and don’t allow me to use “Basic token” with this user (I don’t know why but I don’t really care)

In my script, i’m using an App password generate by the user, and create the header like this

  username = user_info['user_name'] 
  password = user_info['api_password']
  credentials = base64.b64encode(f"{username}:{password}".encode()).decode()
  headers["Authorization"] = f"Basic {credentials}"

I already check at the documentation here : Login Flow — Nextcloud latest Developer Manual latest documentation
But I don’t understand how can I implement it in my script…

Can you help me to make it works ?

Thanks

Hello,

I want to help you. However, I am unsure, if I get the problem.

I guess this might be due to 2fa/MFA. No basic authentication with a password is allowed.

With an app password or should be working though.

May I ask, where you got this information from? Maybe it was just out of context (basic is typically meant for classical password authentication).

So, this did work? How far did you get this way?

What exactly are you missing here? The basic scheme is described well in the documentation. Where is it failing?

Is this related to the very first questions?

Can you please explain a bit more in depth?

Christian

Thank you for your quick reply ! I’ll try to be as clear as possible

This is from some error log found when I make a try of my script with this user.

"No public access to this resource., Username or password was incorrect, No 'Authorization: Bearer' header found. Either the client didn't send one, or the server is mis-configured, Username or password was incorrect"

The error make sense because i’m not sending à Bearer token, but a Basic auth. (even if I still don’t understand why this specific user need a Bearer token…)

The AppPassword “works” with users who take the basic header.

What I’m missing is how to use the AppPassword to login with a user that need Bearer token with python code. The flow describe in the documentation doesn’t provide any username or password, it seems to me (If i’m not wrong) that’s this kind of login is usefull when u can login manually, but I don’t get how to make it works in a script. Probably that I don’t understand the the url in login should be opened in the default browser, this is where the user will follow the login procedure. The program should directly start polling the poll endpoint: from the documentation.

You can use the token as obtained from the login flow as a Bearer token. That is the way to go.

The idea is similar to OAuth2 if you know that. You know this when you install the desktop sync client:

First, you create a token request using POST to /index.php/login/v2. This will trigger the creation of a new app token. You get both a URL for requesting the token and a URL for user interaction.

In a script, you would then forward the latter to the user. Tell him to confirm login by visiting the URL and clicking on allow access (or similar).
As long as the user did not do that, the endpoint will return 404.

You can start querying the server immediately in regular intervals.
As a result of the user confirming access, the endpoint will return the actual token. This token will be presented only once! So, save that token somewhere secure (consider it a password).


With that, I am able to access the dashboard without any additional password:

Did it get clearer for you?

I guess this should be quite doable in Python. Feel free to get the questions coming.

Really thank your for your help.

This is my blocking point. Can I confirm the login and get the bearer token automatically in my script without user interaction ?

No, this is the point of it.

If the user has 2FA activated, the website allows to ask first for password then for 2FA and then for confirmation that the user wants to allow the script to access the cloud.
By using the token you somehow circumvent the 2FA. Therefore it would be a security issue if you could create one with just a password and no interaction by the user.

Why is this blocking? You can do this authorization step in a setup (pre) step that is done only once. This is the idea behind it.

Please share more details on your problem/use-case. Why is user interaction a breaking point?

I understand the security issue.

I think I misunderstand because I thought that the authorization was needed each time I run the script, but you seems to tell me that I can just do this authorization step one time, and use the token after as long as the user allow me to do it ? (Bearer token have no expiration time ?)

Exactly. You request the token once in your app and store the token securely. Once the user has confirmed access, the token is not expiring (except if the user actively revokes the token or you do it via API).

Once you have the token stored, you use it for any upcoming tasks in the API.

1 Like

Ok perfect. Really thank you for your help and your reactivity :slight_smile: !

1 Like