sugyan / atrium

Rust libraries for Bluesky's AT Protocol services.
MIT License
230 stars 26 forks source link

xrpc response error: 401 AuthMissing: Authentication Required #246

Closed klausi closed 2 weeks ago

klausi commented 2 weeks ago

Hi,

nice library!

I'm writing a Mastodon to Bluesky sync tool at https://github.com/klausi/mastodon-bluesky-sync (not working yet).

I use the agent to config serialization at https://github.com/klausi/mastodon-bluesky-sync/blob/main/src/registration.rs#L55 and then load it again on subsequent runs https://github.com/klausi/mastodon-bluesky-sync/blob/main/src/lib.rs#L88 . It serializes into my main mastodon-bluesky-sync.toml settings file.

Now when I run this I get the error xrpc response error: 401 AuthMissing: Authentication Required.

How do I store the Bluesky authentication credentials so that they work on future calls? Do I need to invoke the refresh token somehow when I get this error?

Thanks!

sugyan commented 2 weeks ago

Hmmm... I tried to clone and run your repository but could not reproduce the problem. 🤔

The first time I ran it, I entered the identifier and password in the prompt and the mastodon-bluesky-sync.toml was created in the execution directory. The file contains endpoint and session information in the [bluesky.bluesky_config] section, and accessJwt and refreshJwt are also recorded. The second and subsequent runs restore the configuration information without problems, and get_session and get_author_feed succeed in retrieving data.

klausi commented 2 weeks ago

Thanks for checking!

Yep, it works for a couple of hours and then stops working. I assume because the validity of the access token expires.

Do I need to serialize and save the config after every program execution? Currently I only do it once on registration.

klausi commented 2 weeks ago

Ok, I think I found a workaround: instead of storing access tokens I can generate a dedicated app password at https://bsky.app/settings/app-passwords . I can store this app password in my settings and then bootstrap the session again when I see this 401 error and the old access token is broken.

sugyan commented 2 weeks ago

Ah, I finally understood.

It is true that accessJwt & refreshJwt created by agent.login() cannot continue to be used as is, they must be updated. BskyAgent automatically updates the token using refreshJwt when accessJwt has expired. But if you are using the default MemorySessionStore, the updated token is kept only in memory, so it will be lost at program exit unless you write the config to a file. And a token read from a configuration file that has not been updated may no longer be valid.

You can keep the app-password as in your workaround, but other possible options are:

  1. add a process to save the config in various places (after building the Agent, after executing the XRPC request, at program exit, etc.).

For example, in the CLI I created, I save it right after build (it does resume_session inside build(), so if it had been expired, it would have been updated automatically). https://github.com/sugyan/atrium/blob/main/bsky-cli/src/runner.rs#L46

  1. implement SessionStore in Config. The MemorySessionStore is only provided as a default implementation, you can use your own. If your Config directly handles writing and reading session data to and from files as a SessionStore, you may not have to write the process of saving files as many times as described above.
sugyan commented 2 weeks ago

As additional information, the current bsky-sdk's interface may change its API with future OAuth support, etc. We would like to develop an interface that is easier to understand and use than the current one.

klausi commented 2 weeks ago

Thanks for the explanation, makes sense!

I will do both things in the future:

  1. Re-save the config to disk after building the bluesky agent every time
  2. Keep Bluesky app passwords, because then users can easily revoke them in the UI and I can always get access tokens again.

Thanks a lot for this library, a big help for my tool!