[fractal] API: Remove access_token from BackendData



commit 1b183d3469b26091be83d09968e1e0852476b7a7
Author: Alejandro Domínguez <adomu net-c com>
Date:   Sat Nov 2 00:37:02 2019 +0100

    API: Remove access_token from BackendData

 fractal-gtk/src/actions/account_settings.rs |   3 +
 fractal-gtk/src/actions/room_history.rs     |  31 ++-
 fractal-gtk/src/actions/room_settings.rs    |   3 +
 fractal-gtk/src/app/connect/account.rs      |   3 +-
 fractal-gtk/src/appop/account.rs            |  55 +++--
 fractal-gtk/src/appop/directory.rs          |   8 +-
 fractal-gtk/src/appop/invite.rs             |  15 +-
 fractal-gtk/src/appop/login.rs              |  17 +-
 fractal-gtk/src/appop/media_viewer.rs       |   2 +
 fractal-gtk/src/appop/member.rs             |   4 +-
 fractal-gtk/src/appop/message.rs            |  20 +-
 fractal-gtk/src/appop/mod.rs                |   8 +-
 fractal-gtk/src/appop/room.rs               |  32 ++-
 fractal-gtk/src/appop/room_settings.rs      |   2 +
 fractal-gtk/src/appop/start_chat.rs         |   2 +
 fractal-gtk/src/appop/sync.rs               |   9 +-
 fractal-gtk/src/appop/user.rs               |   6 +
 fractal-gtk/src/passwd.rs                   |  21 +-
 fractal-gtk/src/util.rs                     |   9 +
 fractal-gtk/src/widgets/address.rs          |  32 ++-
 fractal-gtk/src/widgets/media_viewer.rs     |   8 +
 fractal-gtk/src/widgets/room.rs             | 188 +++++++-------
 fractal-gtk/src/widgets/room_settings.rs    |  23 +-
 fractal-matrix-api/src/backend/directory.rs |  46 ++--
 fractal-matrix-api/src/backend/media.rs     |  20 +-
 fractal-matrix-api/src/backend/mod.rs       | 266 +++++++++++++-------
 fractal-matrix-api/src/backend/register.rs  |  33 +--
 fractal-matrix-api/src/backend/room.rs      | 189 +++++++++-----
 fractal-matrix-api/src/backend/stickers.rs  |  60 +++--
 fractal-matrix-api/src/backend/sync.rs      |  14 +-
 fractal-matrix-api/src/backend/types.rs     |  87 +++----
 fractal-matrix-api/src/backend/user.rs      | 365 ++++++++++++----------------
 fractal-matrix-api/src/error.rs             |   1 +
 33 files changed, 937 insertions(+), 645 deletions(-)
---
diff --git a/fractal-gtk/src/actions/account_settings.rs b/fractal-gtk/src/actions/account_settings.rs
index de8928fc..d3d809c0 100644
--- a/fractal-gtk/src/actions/account_settings.rs
+++ b/fractal-gtk/src/actions/account_settings.rs
@@ -1,4 +1,5 @@
 use crate::i18n::i18n;
+use fractal_api::r0::AccessToken;
 use gio::prelude::*;
 use gio::SimpleAction;
 use gio::SimpleActionGroup;
@@ -19,6 +20,7 @@ pub fn new(
     window: &gtk::Window,
     backend: &Sender<BKCommand>,
     server_url: Url,
+    access_token: AccessToken,
 ) -> gio::SimpleActionGroup {
     let actions = SimpleActionGroup::new();
     // TODO create two stats loading interaction and connect it to the avatar box
@@ -39,6 +41,7 @@ pub fn new(
                 a.change_state(&ButtonState::Insensitive.into());
                 let _ = backend.send(BKCommand::SetUserAvatar(
                     server_url.clone(),
+                    access_token.clone(),
                     file.to_string(),
                 ));
             } else {
diff --git a/fractal-gtk/src/actions/room_history.rs b/fractal-gtk/src/actions/room_history.rs
index c5ac5dc7..e7232448 100644
--- a/fractal-gtk/src/actions/room_history.rs
+++ b/fractal-gtk/src/actions/room_history.rs
@@ -1,4 +1,5 @@
 use fractal_api::clone;
+use fractal_api::r0::AccessToken;
 use std::fs;
 use std::sync::mpsc::channel;
 use std::sync::mpsc::TryRecvError;
@@ -21,7 +22,12 @@ use crate::widgets::FileDialog::save;
 use crate::widgets::SourceDialog;
 
 /* This creates all actions the room history can perform */
-pub fn new(backend: Sender<BKCommand>, server_url: Url, ui: UI) -> gio::SimpleActionGroup {
+pub fn new(
+    backend: Sender<BKCommand>,
+    server_url: Url,
+    access_token: AccessToken,
+    ui: UI,
+) -> gio::SimpleActionGroup {
     let actions = SimpleActionGroup::new();
     /* Action for each message */
     let reply = SimpleAction::new("reply", glib::VariantTy::new("s").ok());
@@ -169,15 +175,16 @@ pub fn new(backend: Sender<BKCommand>, server_url: Url, ui: UI) -> gio::SimpleAc
 
     let b = backend.clone();
     let u = server_url.clone();
+    let tk = access_token.clone();
     delete.connect_activate(move |_, data| {
         if let Some(m) = get_message(data) {
-            let _ = b.send(BKCommand::SendMsgRedaction(u.clone(), m));
+            let _ = b.send(BKCommand::SendMsgRedaction(u.clone(), tk.clone(), m));
         }
     });
 
-    load_more_messages.connect_activate(clone!(server_url => move |_, data| {
+    load_more_messages.connect_activate(clone!(server_url, access_token => move |_, data| {
         let id = get_room_id(data);
-        request_more_messages(&backend, server_url.clone(), id);
+        request_more_messages(&backend, server_url.clone(), access_token.clone(), id);
     }));
 
     actions
@@ -202,6 +209,7 @@ fn get_room_id(data: Option<&glib::Variant>) -> Option<String> {
 fn request_more_messages(
     backend: &Sender<BKCommand>,
     server_url: Url,
+    access_token: AccessToken,
     id: Option<String>,
 ) -> Option<()> {
     let op = App::get_op()?;
@@ -210,13 +218,19 @@ fn request_more_messages(
     let r = op.rooms.get(&id)?;
     if let Some(prev_batch) = r.prev_batch.clone() {
         backend
-            .send(BKCommand::GetRoomMessages(server_url, id, prev_batch))
+            .send(BKCommand::GetRoomMessages(
+                server_url,
+                access_token,
+                id,
+                prev_batch,
+            ))
             .unwrap();
     } else if let Some(msg) = r.messages.iter().next() {
         // no prev_batch so we use the last message to calculate that in the backend
         backend
             .send(BKCommand::GetRoomMessagesFromMsg(
                 server_url,
+                access_token,
                 id,
                 msg.clone(),
             ))
@@ -224,7 +238,12 @@ fn request_more_messages(
     } else if let Some(from) = op.since.clone() {
         // no messages and no prev_batch so we use the last since
         backend
-            .send(BKCommand::GetRoomMessages(server_url, id, from))
+            .send(BKCommand::GetRoomMessages(
+                server_url,
+                access_token,
+                id,
+                from,
+            ))
             .unwrap();
     }
     None
diff --git a/fractal-gtk/src/actions/room_settings.rs b/fractal-gtk/src/actions/room_settings.rs
index a3ae076e..309d548a 100644
--- a/fractal-gtk/src/actions/room_settings.rs
+++ b/fractal-gtk/src/actions/room_settings.rs
@@ -1,3 +1,4 @@
+use fractal_api::r0::AccessToken;
 use gio::prelude::*;
 use gio::SimpleAction;
 use gio::SimpleActionGroup;
@@ -20,6 +21,7 @@ pub fn new(
     window: &gtk::Window,
     backend: &Sender<BKCommand>,
     server_url: Url,
+    access_token: AccessToken,
 ) -> gio::SimpleActionGroup {
     let actions = SimpleActionGroup::new();
     // TODO create two stats loading interaction and conect it to the avatar box
@@ -44,6 +46,7 @@ pub fn new(
                     a.change_state(&ButtonState::Insensitive.into());
                     let _ = backend.send(BKCommand::SetRoomAvatar(
                         server_url.clone(),
+                        access_token.clone(),
                         id,
                         file.to_string(),
                     ));
diff --git a/fractal-gtk/src/app/connect/account.rs b/fractal-gtk/src/app/connect/account.rs
index b82e4446..d2a16b44 100644
--- a/fractal-gtk/src/app/connect/account.rs
+++ b/fractal-gtk/src/app/connect/account.rs
@@ -11,6 +11,7 @@ use crate::actions::{AccountSettings, StateExt};
 impl App {
     pub fn connect_account_settings(&self) {
         let op = &self.op;
+        let access_token = unwrap_or_unit_return!(op.lock().unwrap().access_token.clone());
         let builder = &self.ui.builder;
         let cancel_password = self
             .ui
@@ -77,7 +78,7 @@ impl App {
         let backend = self.op.lock().unwrap().backend.clone();
         let window = self.main_window.upcast_ref::<gtk::Window>();
         let server_url = self.op.lock().unwrap().server_url.clone();
-        let actions = AccountSettings::new(&window, &backend, server_url);
+        let actions = AccountSettings::new(&window, &backend, server_url, access_token);
         let container = self
             .ui
             .builder
diff --git a/fractal-gtk/src/appop/account.rs b/fractal-gtk/src/appop/account.rs
index 16b2cb2a..3830af0d 100644
--- a/fractal-gtk/src/appop/account.rs
+++ b/fractal-gtk/src/appop/account.rs
@@ -20,8 +20,12 @@ impl AppOp {
     }
 
     pub fn get_three_pid(&self) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         self.backend
-            .send(BKCommand::GetThreePID(self.server_url.clone()))
+            .send(BKCommand::GetThreePID(
+                self.server_url.clone(),
+                access_token,
+            ))
             .unwrap();
     }
 
@@ -30,10 +34,12 @@ impl AppOp {
     }
 
     pub fn valid_phone_token(&self, sid: Option<String>, secret: Option<String>) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         if let Some(sid) = sid {
             if let Some(secret) = secret {
                 let _ = self.backend.send(BKCommand::AddThreePID(
                     self.server_url.clone(),
+                    access_token,
                     self.identity_url.to_string(), // TODO: Change type to Url
                     secret.clone(),
                     sid.clone(),
@@ -110,6 +116,7 @@ impl AppOp {
     }
 
     pub fn show_email_dialog(&self, sid: String, secret: String) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         let parent = self
             .ui
             .builder
@@ -135,6 +142,7 @@ impl AppOp {
                 gtk::ResponseType::Ok => {
                     let _ = backend.send(BKCommand::AddThreePID(
                         server_url.clone(),
+                        access_token.clone(),
                         id_server.clone(), // TODO: Change type to Url
                         secret.clone(),
                         sid.clone(),
@@ -529,6 +537,7 @@ impl AppOp {
     }
 
     pub fn update_username_account_settings(&self) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         let name = self
             .ui
             .builder
@@ -552,7 +561,11 @@ impl AppOp {
             button.set_sensitive(false);
             name.set_editable(false);
             self.backend
-                .send(BKCommand::SetUserName(self.server_url.clone(), username))
+                .send(BKCommand::SetUserName(
+                    self.server_url.clone(),
+                    access_token,
+                    username,
+                ))
                 .unwrap();
         } else {
             button.hide();
@@ -582,6 +595,7 @@ impl AppOp {
     }
 
     pub fn set_new_password(&mut self) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         let old_password = self
             .ui
             .builder
@@ -611,6 +625,7 @@ impl AppOp {
                         password_btn_stack.set_visible_child_name("spinner");
                         let _ = self.backend.send(BKCommand::ChangePassword(
                             self.server_url.clone(),
+                            access_token,
                             mxid,
                             old.to_string(),
                             new.to_string(),
@@ -681,6 +696,7 @@ impl AppOp {
     }
 
     pub fn account_destruction(&self) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         let entry = self
             .ui
             .builder
@@ -712,25 +728,24 @@ impl AppOp {
 
         let _flag = mark.get_active(); // TODO: This is not used, remove from UI?
         let server_url = self.server_url.clone();
-        if let Some(password) = entry.get_text() {
-            if let Some(mxid) = self.uid.clone() {
-                let backend = self.backend.clone();
-                let password = password.to_string();
-                dialog.connect_response(move |w, r| {
-                    match gtk::ResponseType::from(r) {
-                        gtk::ResponseType::Ok => {
-                            let _ = backend.send(BKCommand::AccountDestruction(
-                                server_url.clone(),
-                                mxid.clone(),
-                                password.clone(),
-                            ));
-                        }
-                        _ => {}
+        if let (Some(password), Some(mxid)) = (entry.get_text(), self.uid.clone()) {
+            let backend = self.backend.clone();
+            let password = password.to_string();
+            dialog.connect_response(move |w, r| {
+                match gtk::ResponseType::from(r) {
+                    gtk::ResponseType::Ok => {
+                        let _ = backend.send(BKCommand::AccountDestruction(
+                            server_url.clone(),
+                            access_token.clone(),
+                            mxid.clone(),
+                            password.clone(),
+                        ));
                     }
-                    w.destroy();
-                });
-                dialog.show_all();
-            }
+                    _ => {}
+                }
+                w.destroy();
+            });
+            dialog.show_all();
         }
     }
     pub fn account_destruction_logoff(&self) {
diff --git a/fractal-gtk/src/appop/directory.rs b/fractal-gtk/src/appop/directory.rs
index 513b1910..e7711c34 100644
--- a/fractal-gtk/src/appop/directory.rs
+++ b/fractal-gtk/src/appop/directory.rs
@@ -12,8 +12,12 @@ use fractal_api::r0::thirdparty::get_supported_protocols::ProtocolInstance;
 
 impl AppOp {
     pub fn init_protocols(&self) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         self.backend
-            .send(BKCommand::DirectoryProtocols(self.server_url.clone()))
+            .send(BKCommand::DirectoryProtocols(
+                self.server_url.clone(),
+                access_token,
+            ))
             .unwrap();
     }
 
@@ -31,6 +35,7 @@ impl AppOp {
     }
 
     pub fn search_rooms(&mut self, more: bool) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         let other_protocol_radio = self
             .ui
             .builder
@@ -119,6 +124,7 @@ impl AppOp {
         self.backend
             .send(BKCommand::DirectorySearch(
                 self.server_url.clone(),
+                access_token,
                 homeserver,
                 q.get_text().unwrap().to_string(),
                 protocol,
diff --git a/fractal-gtk/src/appop/invite.rs b/fractal-gtk/src/appop/invite.rs
index 74661c1a..301405ad 100644
--- a/fractal-gtk/src/appop/invite.rs
+++ b/fractal-gtk/src/appop/invite.rs
@@ -156,11 +156,13 @@ impl AppOp {
     }
 
     pub fn invite(&mut self) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         if let &Some(ref r) = &self.active_room {
             for user in &self.invite_list {
                 self.backend
                     .send(BKCommand::Invite(
                         self.server_url.clone(),
+                        access_token.clone(),
                         r.clone(),
                         user.0.uid.clone(),
                     ))
@@ -213,15 +215,24 @@ impl AppOp {
     }
 
     pub fn accept_inv(&mut self, accept: bool) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         let rid = self.invitation_roomid.clone();
         if let Some(rid) = rid {
             if accept {
                 self.backend
-                    .send(BKCommand::AcceptInv(self.server_url.clone(), rid.clone()))
+                    .send(BKCommand::AcceptInv(
+                        self.server_url.clone(),
+                        access_token,
+                        rid.clone(),
+                    ))
                     .unwrap();
             } else {
                 self.backend
-                    .send(BKCommand::RejectInv(self.server_url.clone(), rid.clone()))
+                    .send(BKCommand::RejectInv(
+                        self.server_url.clone(),
+                        access_token,
+                        rid.clone(),
+                    ))
                     .unwrap();
             }
             self.remove_inv(rid);
diff --git a/fractal-gtk/src/appop/login.rs b/fractal-gtk/src/appop/login.rs
index 74efbe8a..901f9553 100644
--- a/fractal-gtk/src/appop/login.rs
+++ b/fractal-gtk/src/appop/login.rs
@@ -1,6 +1,8 @@
 use crate::i18n::i18n;
 use log::error;
 
+use fractal_api::r0::AccessToken;
+
 use gtk;
 use gtk::prelude::*;
 
@@ -24,9 +26,9 @@ use crate::actions::AppState;
 use crate::widgets::ErrorDialog;
 
 impl AppOp {
-    pub fn bk_login(&mut self, uid: String, token: String, device: Option<String>) {
+    pub fn bk_login(&mut self, uid: String, token: Option<AccessToken>, device: Option<String>) {
         self.logged_in = true;
-        if let Err(_) = self.store_token(uid.clone(), token) {
+        if let Err(_) = self.store_token(uid.clone(), token.clone()) {
             error!("Can't store the token using libsecret");
         }
 
@@ -39,6 +41,8 @@ impl AppOp {
         self.set_username(Some(uid));*/
         self.get_username();
 
+        self.set_access_token(token);
+
         // initial sync, we're shoing some feedback to the user
         self.initial_sync(true);
 
@@ -179,15 +183,13 @@ impl AppOp {
 
     pub fn set_token(
         &mut self,
-        token: Option<String>,
+        token: AccessToken,
         uid: Option<String>,
         server: Url,
     ) -> Option<()> {
         self.server_url = server;
 
-        self.backend
-            .send(BKCommand::SetToken(token?, uid?))
-            .unwrap();
+        self.backend.send(BKCommand::SetToken(token, uid?)).unwrap();
         Some(())
     }
 
@@ -205,9 +207,10 @@ impl AppOp {
     }
 
     pub fn logout(&mut self) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         let _ = self.delete_pass("fractal");
         self.backend
-            .send(BKCommand::Logout(self.server_url.clone()))
+            .send(BKCommand::Logout(self.server_url.clone(), access_token))
             .unwrap();
         self.bk_logout();
     }
diff --git a/fractal-gtk/src/appop/media_viewer.rs b/fractal-gtk/src/appop/media_viewer.rs
index 814e4458..e883dff1 100644
--- a/fractal-gtk/src/appop/media_viewer.rs
+++ b/fractal-gtk/src/appop/media_viewer.rs
@@ -11,6 +11,7 @@ use crate::types::Message;
 impl AppOp {
     /* FIXME: take msg by reference and maybe create an action for this */
     pub fn create_media_viewer(&mut self, msg: Message) -> Option<()> {
+        let access_token = self.access_token.clone()?;
         let stack = self
             .ui
             .builder
@@ -37,6 +38,7 @@ impl AppOp {
                 room,
                 &msg,
                 self.server_url.clone(),
+                access_token,
             );
             panel.display_media_viewer(msg);
             let (body, header) = panel.create()?;
diff --git a/fractal-gtk/src/appop/member.rs b/fractal-gtk/src/appop/member.rs
index 0307d945..b4315581 100644
--- a/fractal-gtk/src/appop/member.rs
+++ b/fractal-gtk/src/appop/member.rs
@@ -190,9 +190,9 @@ impl AppOp {
     }
 
     pub fn search_invite_user(&self, term: Option<String>) {
-        if let Some(t) = term {
+        if let (Some(t), Some(token)) = (term, self.access_token.clone()) {
             self.backend
-                .send(BKCommand::UserSearch(self.server_url.clone(), t))
+                .send(BKCommand::UserSearch(self.server_url.clone(), token, t))
                 .unwrap();
         }
     }
diff --git a/fractal-gtk/src/appop/message.rs b/fractal-gtk/src/appop/message.rs
index 92804cb0..119a8af2 100644
--- a/fractal-gtk/src/appop/message.rs
+++ b/fractal-gtk/src/appop/message.rs
@@ -111,6 +111,7 @@ impl AppOp {
     }
 
     pub fn mark_last_message_as_read(&mut self, Force(force): Force) -> Option<()> {
+        let access_token = self.access_token.clone()?;
         let window: gtk::Window = self
             .ui
             .builder
@@ -132,6 +133,7 @@ impl AppOp {
             self.backend
                 .send(BKCommand::MarkAsRead(
                     self.server_url.clone(),
+                    access_token,
                     last_message.room.clone(),
                     last_message.id.clone(),
                 ))
@@ -165,9 +167,10 @@ impl AppOp {
         self.dequeue_message();
     }
 
-    pub fn dequeue_message(&mut self) {
+    pub fn dequeue_message(&mut self) -> Option<()> {
+        let access_token = self.access_token.clone()?;
         if self.sending_message {
-            return;
+            return None;
         }
 
         self.sending_message = true;
@@ -176,18 +179,27 @@ impl AppOp {
             match &next.msg.mtype[..] {
                 "m.image" | "m.file" | "m.audio" => {
                     self.backend
-                        .send(BKCommand::AttachFile(self.server_url.clone(), msg))
+                        .send(BKCommand::AttachFile(
+                            self.server_url.clone(),
+                            access_token,
+                            msg,
+                        ))
                         .unwrap();
                 }
                 _ => {
                     self.backend
-                        .send(BKCommand::SendMsg(self.server_url.clone(), msg))
+                        .send(BKCommand::SendMsg(
+                            self.server_url.clone(),
+                            access_token,
+                            msg,
+                        ))
                         .unwrap();
                 }
             }
         } else {
             self.sending_message = false;
         }
+        None
     }
 
     pub fn send_message(&mut self, msg: String) {
diff --git a/fractal-gtk/src/appop/mod.rs b/fractal-gtk/src/appop/mod.rs
index 02c246e9..c2ae85cf 100644
--- a/fractal-gtk/src/appop/mod.rs
+++ b/fractal-gtk/src/appop/mod.rs
@@ -1,6 +1,8 @@
 use std::collections::HashMap;
 use std::sync::mpsc::Sender;
 
+use fractal_api::r0::AccessToken;
+
 use gtk;
 use gtk::prelude::*;
 
@@ -50,6 +52,7 @@ pub struct AppOp {
     pub msg_queue: Vec<TmpMsg>,
     pub sending_message: bool,
 
+    pub access_token: Option<AccessToken>,
     pub username: Option<String>,
     pub uid: Option<String>,
     pub device_id: Option<String>,
@@ -95,6 +98,7 @@ impl AppOp {
             rooms: HashMap::new(),
             room_settings: None,
             history: None,
+            access_token: None,
             username: None,
             uid: None,
             device_id: None,
@@ -136,8 +140,8 @@ impl AppOp {
         }
 
         if let Ok(pass) = self.get_pass() {
-            if let Ok((token, uid)) = self.get_token() {
-                self.set_token(Some(token), Some(uid), pass.2);
+            if let Ok((Some(token), uid)) = self.get_token() {
+                self.set_token(token, Some(uid), pass.2);
             } else {
                 self.connect(Some(pass.0), Some(pass.1), pass.2, pass.3);
             }
diff --git a/fractal-gtk/src/appop/room.rs b/fractal-gtk/src/appop/room.rs
index 60bde306..c3e8094f 100644
--- a/fractal-gtk/src/appop/room.rs
+++ b/fractal-gtk/src/appop/room.rs
@@ -39,6 +39,7 @@ impl AppOp {
     }
 
     pub fn set_rooms(&mut self, mut rooms: Vec<Room>, clear_room_list: bool) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         if clear_room_list {
             self.rooms.clear();
         }
@@ -74,6 +75,7 @@ impl AppOp {
                 self.backend
                     .send(BKCommand::GetRoomMembers(
                         self.server_url.clone(),
+                        access_token.clone(),
                         room.id.clone(),
                     ))
                     .unwrap();
@@ -82,6 +84,7 @@ impl AppOp {
                 self.backend
                     .send(BKCommand::GetRoomAvatar(
                         self.server_url.clone(),
+                        access_token.clone(),
                         room.id.clone(),
                     ))
                     .unwrap();
@@ -127,6 +130,7 @@ impl AppOp {
             self.roomlist.connect_fav(move |room, tofav| {
                 bk.send(BKCommand::AddToFav(
                     server_url.clone(),
+                    access_token.clone(),
                     room.id.clone(),
                     tofav,
                 ))
@@ -146,6 +150,7 @@ impl AppOp {
     }
 
     pub fn set_active_room_by_id(&mut self, id: String) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         if let Some(room) = self.rooms.get(&id) {
             if let RoomMembership::Invited(ref sender) = room.membership {
                 self.show_inv_dialog(Some(sender), room.name.as_ref());
@@ -214,6 +219,7 @@ impl AppOp {
         self.backend
             .send(BKCommand::SetRoom(
                 self.server_url.clone(),
+                access_token.clone(),
                 active_room.clone(),
             ))
             .unwrap();
@@ -246,6 +252,7 @@ impl AppOp {
         let actions = actions::RoomHistory::new(
             self.backend.clone(),
             self.server_url.clone(),
+            access_token,
             self.ui.clone(),
         );
         let mut history = widgets::RoomHistory::new(actions, active_room.clone(), self);
@@ -260,9 +267,14 @@ impl AppOp {
     }
 
     pub fn really_leave_active_room(&mut self) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         let r = self.active_room.clone().unwrap_or_default();
         self.backend
-            .send(BKCommand::LeaveRoom(self.server_url.clone(), r.clone()))
+            .send(BKCommand::LeaveRoom(
+                self.server_url.clone(),
+                access_token,
+                r.clone(),
+            ))
             .unwrap();
         self.rooms.remove(&r);
         self.active_room = None;
@@ -306,6 +318,7 @@ impl AppOp {
     }
 
     pub fn create_new_room(&mut self) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         let name = self
             .ui
             .builder
@@ -331,6 +344,7 @@ impl AppOp {
         self.backend
             .send(BKCommand::NewRoom(
                 self.server_url.clone(),
+                access_token,
                 n.clone(),
                 p,
                 internal_id.clone(),
@@ -457,6 +471,7 @@ impl AppOp {
     }
 
     pub fn join_to_room(&mut self) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         let name = self
             .ui
             .builder
@@ -470,7 +485,11 @@ impl AppOp {
             .to_string();
 
         self.backend
-            .send(BKCommand::JoinRoom(self.server_url.clone(), n.clone()))
+            .send(BKCommand::JoinRoom(
+                self.server_url.clone(),
+                access_token,
+                n.clone(),
+            ))
             .unwrap();
     }
 
@@ -614,12 +633,17 @@ impl AppOp {
     }
 
     pub fn new_room_avatar(&self, roomid: String) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         if !self.rooms.contains_key(&roomid) {
             return;
         }
 
         self.backend
-            .send(BKCommand::GetRoomAvatar(self.server_url.clone(), roomid))
+            .send(BKCommand::GetRoomAvatar(
+                self.server_url.clone(),
+                access_token,
+                roomid,
+            ))
             .unwrap();
     }
 
@@ -655,6 +679,7 @@ impl AppOp {
     }
 
     pub fn send_typing(&mut self) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         if let Some(ref active_room) = self.active_room {
             let now = Instant::now();
             if let Some(last_typing) = self.typing.get(active_room) {
@@ -667,6 +692,7 @@ impl AppOp {
             self.backend
                 .send(BKCommand::SendTyping(
                     self.server_url.clone(),
+                    access_token,
                     active_room.clone(),
                 ))
                 .unwrap();
diff --git a/fractal-gtk/src/appop/room_settings.rs b/fractal-gtk/src/appop/room_settings.rs
index 7c22d9f4..f994a8f0 100644
--- a/fractal-gtk/src/appop/room_settings.rs
+++ b/fractal-gtk/src/appop/room_settings.rs
@@ -8,6 +8,7 @@ use crate::widgets;
 
 impl AppOp {
     pub fn create_room_settings(&mut self) -> Option<()> {
+        let access_token = self.access_token.clone()?;
         let window = self
             .ui
             .builder
@@ -32,6 +33,7 @@ impl AppOp {
                 self.uid.clone(),
                 room.clone(),
                 self.server_url.clone(),
+                access_token,
             );
             let (body, header) = panel.create()?;
 
diff --git a/fractal-gtk/src/appop/start_chat.rs b/fractal-gtk/src/appop/start_chat.rs
index 1bdfca39..0c6d9c70 100644
--- a/fractal-gtk/src/appop/start_chat.rs
+++ b/fractal-gtk/src/appop/start_chat.rs
@@ -13,6 +13,7 @@ use rand::{thread_rng, Rng};
 
 impl AppOp {
     pub fn start_chat(&mut self) {
+        let access_token = unwrap_or_unit_return!(self.access_token.clone());
         if self.invite_list.len() != 1 {
             return;
         }
@@ -23,6 +24,7 @@ impl AppOp {
         self.backend
             .send(BKCommand::DirectChat(
                 self.server_url.clone(),
+                access_token,
                 user.0.clone(),
                 internal_id.clone(),
             ))
diff --git a/fractal-gtk/src/appop/sync.rs b/fractal-gtk/src/appop/sync.rs
index ab36f39a..1ad66b98 100644
--- a/fractal-gtk/src/appop/sync.rs
+++ b/fractal-gtk/src/appop/sync.rs
@@ -14,7 +14,7 @@ impl AppOp {
     }
 
     pub fn sync(&mut self, initial: bool) {
-        if !self.syncing && self.logged_in {
+        if let (Some(token), true) = (self.access_token.clone(), !self.syncing && self.logged_in) {
             self.syncing = true;
             // for the initial sync we set the since to None to avoid long syncing
             // the since can be a very old value and following the spec we should
@@ -22,7 +22,12 @@ impl AppOp {
             // https://matrix.org/docs/spec/client_server/latest.html#syncing
             let since = if initial { None } else { self.since.clone() };
             self.backend
-                .send(BKCommand::Sync(self.server_url.clone(), since, initial))
+                .send(BKCommand::Sync(
+                    self.server_url.clone(),
+                    token.clone(),
+                    since,
+                    initial,
+                ))
                 .unwrap();
         }
     }
diff --git a/fractal-gtk/src/appop/user.rs b/fractal-gtk/src/appop/user.rs
index 8e92dd0d..f19fc558 100644
--- a/fractal-gtk/src/appop/user.rs
+++ b/fractal-gtk/src/appop/user.rs
@@ -1,3 +1,5 @@
+use fractal_api::r0::AccessToken;
+
 use gtk;
 use gtk::prelude::*;
 
@@ -96,6 +98,10 @@ impl AppOp {
         eb.connect_button_press_event(move |_, _| Inhibit(false));
     }
 
+    pub fn set_access_token(&mut self, access_token: Option<AccessToken>) {
+        self.access_token = access_token;
+    }
+
     pub fn set_username(&mut self, username: Option<String>) {
         self.username = username;
         self.show_user_info();
diff --git a/fractal-gtk/src/passwd.rs b/fractal-gtk/src/passwd.rs
index 52a986ea..518ddfa1 100644
--- a/fractal-gtk/src/passwd.rs
+++ b/fractal-gtk/src/passwd.rs
@@ -1,4 +1,5 @@
 use fractal_api::derror;
+use fractal_api::r0::AccessToken;
 use secret_service;
 use url::ParseError;
 use url::Url;
@@ -36,17 +37,18 @@ pub trait PasswordStorage {
         ss_storage::get_pass()
     }
 
-    fn store_token(&self, uid: String, token: String) -> Result<(), Error> {
+    fn store_token(&self, uid: String, token: Option<AccessToken>) -> Result<(), Error> {
         ss_storage::store_token(uid, token)
     }
 
-    fn get_token(&self) -> Result<(String, String), Error> {
+    fn get_token(&self) -> Result<(Option<AccessToken>, String), Error> {
         ss_storage::get_token()
     }
 }
 
 mod ss_storage {
     use super::Error;
+    use fractal_api::r0::AccessToken;
     use url::Url;
 
     use super::secret_service::EncryptionType;
@@ -71,7 +73,7 @@ mod ss_storage {
         Ok(())
     }
 
-    pub fn store_token(uid: String, token: String) -> Result<(), Error> {
+    pub fn store_token(uid: String, token: Option<AccessToken>) -> Result<(), Error> {
         let ss = SecretService::new(EncryptionType::Dh)?;
         let collection = ss.get_default_collection()?;
         let key = "fractal-token";
@@ -84,7 +86,12 @@ mod ss_storage {
         collection.create_item(
             key,                 // label
             vec![("uid", &uid)], // properties
-            token.as_bytes(),    //secret
+            token
+                .as_ref()
+                .map(ToString::to_string)
+                .as_ref()
+                .map(String::as_bytes)
+                .unwrap_or_default(), //secret
             true,                // replace item with same attributes
             "text/plain",        // secret content type
         )?;
@@ -92,7 +99,7 @@ mod ss_storage {
         Ok(())
     }
 
-    pub fn get_token() -> Result<(String, String), Error> {
+    pub fn get_token() -> Result<(Option<AccessToken>, String), Error> {
         let ss = SecretService::new(EncryptionType::Dh)?;
         let collection = ss.get_default_collection()?;
         let allpass = collection.get_all_items()?;
@@ -110,7 +117,9 @@ mod ss_storage {
         p.unlock()?;
         let attrs = p.get_attributes()?;
         let secret = p.get_secret()?;
-        let token = String::from_utf8(secret).unwrap();
+        let token = Some(String::from_utf8(secret).unwrap())
+            .filter(|tk| !tk.is_empty())
+            .map(AccessToken::from);
 
         let attr = attrs
             .iter()
diff --git a/fractal-gtk/src/util.rs b/fractal-gtk/src/util.rs
index 62f3af55..0e2797e5 100644
--- a/fractal-gtk/src/util.rs
+++ b/fractal-gtk/src/util.rs
@@ -88,3 +88,12 @@ macro_rules! upgrade_weak {
         upgrade_weak!($x, ())
     };
 }
+
+macro_rules! unwrap_or_unit_return {
+    ($x:expr) => {
+        match $x {
+            Some(a) => a,
+            None => return,
+        }
+    };
+}
diff --git a/fractal-gtk/src/widgets/address.rs b/fractal-gtk/src/widgets/address.rs
index 697d29d5..99995b1b 100644
--- a/fractal-gtk/src/widgets/address.rs
+++ b/fractal-gtk/src/widgets/address.rs
@@ -1,3 +1,4 @@
+use fractal_api::r0::AccessToken;
 use fractal_api::r0::Medium;
 use glib::signal;
 use gtk;
@@ -130,6 +131,7 @@ impl<'a> Address<'a> {
     }
 
     fn connect(&mut self) {
+        let access_token = unwrap_or_unit_return!(self.op.access_token.clone());
         let button = self.button.clone();
         let medium = self.medium.clone();
         self.entry.connect_property_text_notify(move |w| {
@@ -181,7 +183,13 @@ impl<'a> Address<'a> {
 
             match action {
                 Some(AddressAction::Delete) => {
-                    delete_address(&backend, medium, address.clone(), server_url.clone());
+                    delete_address(
+                        &backend,
+                        medium,
+                        address.clone(),
+                        server_url.clone(),
+                        access_token.clone(),
+                    );
                 }
                 Some(AddressAction::Add) => {
                     add_address(
@@ -190,6 +198,7 @@ impl<'a> Address<'a> {
                         id_server.clone(), // TODO: Change type to Url
                         entry.get_text().map_or(None, |gstr| Some(gstr.to_string())),
                         server_url.clone(),
+                        access_token.clone(),
                     );
                 }
                 _ => {}
@@ -203,9 +212,15 @@ fn delete_address(
     medium: Medium,
     address: Option<String>,
     server_url: Url,
+    access_token: AccessToken,
 ) -> Option<String> {
     backend
-        .send(BKCommand::DeleteThreePID(server_url, medium, address?))
+        .send(BKCommand::DeleteThreePID(
+            server_url,
+            access_token,
+            medium,
+            address?,
+        ))
         .unwrap();
     None
 }
@@ -216,20 +231,29 @@ fn add_address(
     id_server: String,
     address: Option<String>,
     server_url: Url,
+    access_token: AccessToken,
 ) -> Option<String> {
     let secret: String = thread_rng().sample_iter(&Alphanumeric).take(36).collect();
     match medium {
         Medium::MsIsdn => {
             backend
                 .send(BKCommand::GetTokenPhone(
-                    server_url, id_server, address?, secret,
+                    server_url,
+                    access_token,
+                    id_server,
+                    address?,
+                    secret,
                 ))
                 .unwrap();
         }
         Medium::Email => {
             backend
                 .send(BKCommand::GetTokenEmail(
-                    server_url, id_server, address?, secret,
+                    server_url,
+                    access_token,
+                    id_server,
+                    address?,
+                    secret,
                 ))
                 .unwrap();
         }
diff --git a/fractal-gtk/src/widgets/media_viewer.rs b/fractal-gtk/src/widgets/media_viewer.rs
index 5c55214b..60147234 100644
--- a/fractal-gtk/src/widgets/media_viewer.rs
+++ b/fractal-gtk/src/widgets/media_viewer.rs
@@ -1,4 +1,5 @@
 use fractal_api::clone;
+use fractal_api::r0::AccessToken;
 use gdk;
 
 use std::cell::RefCell;
@@ -42,6 +43,7 @@ struct Data {
     main_window: gtk::Window,
     backend: Sender<BKCommand>,
     server_url: Url,
+    access_token: AccessToken,
 
     pub image: Option<image::Image>,
     media_list: Vec<Message>,
@@ -58,6 +60,7 @@ impl Data {
     pub fn new(
         backend: Sender<BKCommand>,
         server_url: Url,
+        access_token: AccessToken,
         media_list: Vec<Message>,
         current_media_index: usize,
         main_window: gtk::Window,
@@ -74,6 +77,7 @@ impl Data {
             builder,
             backend,
             server_url,
+            access_token,
             main_window,
             signal_id: None,
         }
@@ -260,6 +264,7 @@ impl MediaViewer {
         room: &Room,
         current_media_msg: &Message,
         server_url: Url,
+        access_token: AccessToken,
     ) -> MediaViewer {
         let builder = gtk::Builder::new();
         builder
@@ -285,6 +290,7 @@ impl MediaViewer {
             data: Rc::new(RefCell::new(Data::new(
                 backend.clone(),
                 server_url,
+                access_token,
                 media_list,
                 current_media_index,
                 main_window,
@@ -594,6 +600,7 @@ fn load_more_media(data: Rc<RefCell<Data>>, builder: gtk::Builder, backend: Send
     let first_media_id = Some(msg.id.clone());
     let prev_batch = data.borrow().prev_batch.clone();
     let server_url = data.borrow().server_url.clone();
+    let access_token = data.borrow().access_token.clone();
 
     let (tx, rx): (
         Sender<(Vec<Message>, String)>,
@@ -602,6 +609,7 @@ fn load_more_media(data: Rc<RefCell<Data>>, builder: gtk::Builder, backend: Send
     backend
         .send(BKCommand::GetMediaListAsync(
             server_url,
+            access_token,
             roomid,
             first_media_id,
             prev_batch,
diff --git a/fractal-gtk/src/widgets/room.rs b/fractal-gtk/src/widgets/room.rs
index 244cf6c4..96b3f9fd 100644
--- a/fractal-gtk/src/widgets/room.rs
+++ b/fractal-gtk/src/widgets/room.rs
@@ -42,100 +42,106 @@ impl<'a> RoomBox<'a> {
     }
 
     fn build_room_box(&self) -> gtk::Box {
-        let room = self.room;
-
         let widget_box = gtk::Box::new(gtk::Orientation::Horizontal, 0);
 
-        let avatar = widgets::Avatar::avatar_new(Some(AVATAR_SIZE));
-        avatar.circle(room.id.clone(), room.name.clone(), AVATAR_SIZE, None, None);
-        widget_box.pack_start(&avatar, false, false, 18);
-
-        let details_box = gtk::Box::new(gtk::Orientation::Vertical, 6);
-
-        let name = match room.name {
-            ref n if n.is_none() || n.clone().unwrap().is_empty() => room.alias.clone(),
-            ref n => n.clone(),
-        };
-
-        let name_label = gtk::Label::new(None);
-        name_label.set_line_wrap(true);
-        name_label.set_line_wrap_mode(pango::WrapMode::WordChar);
-        name_label.set_markup(&format!(
-            "<b>{}</b>",
-            markup_text(&name.unwrap_or_default())
-        ));
-        name_label.set_justify(gtk::Justification::Left);
-        name_label.set_halign(gtk::Align::Start);
-        name_label.set_valign(gtk::Align::Start);
-        name_label.set_xalign(0.0);
-
-        let topic_label = gtk::Label::new(None);
-        if !room.topic.clone().unwrap_or_default().is_empty() {
-            topic_label.set_line_wrap(true);
-            topic_label.set_line_wrap_mode(pango::WrapMode::WordChar);
-            topic_label.set_lines(2);
-            topic_label.set_ellipsize(pango::EllipsizeMode::End);
-            topic_label.set_markup(&markup_text(&room.topic.clone().unwrap_or_default()));
-            topic_label.set_justify(gtk::Justification::Left);
-            topic_label.set_halign(gtk::Align::Start);
-            topic_label.set_valign(gtk::Align::Start);
-            topic_label.set_xalign(0.0);
-        }
-
-        let alias_label = gtk::Label::new(None);
-        alias_label.set_line_wrap(true);
-        alias_label.set_line_wrap_mode(pango::WrapMode::WordChar);
-        alias_label.set_markup(&format!(
-            "<span alpha=\"60%\">{}</span>",
-            room.alias.clone().unwrap_or_default()
-        ));
-        alias_label.set_justify(gtk::Justification::Left);
-        alias_label.set_halign(gtk::Align::Start);
-        alias_label.set_valign(gtk::Align::Start);
-        alias_label.set_xalign(0.0);
-
-        details_box.add(&name_label);
-        if !topic_label
-            .get_text()
-            .map_or(String::new(), |gstr| gstr.to_string())
-            .is_empty()
-        {
-            details_box.add(&topic_label);
+        if let Some(access_token) = self.op.access_token.clone() {
+            let room = self.room;
+
+            let avatar = widgets::Avatar::avatar_new(Some(AVATAR_SIZE));
+            avatar.circle(room.id.clone(), room.name.clone(), AVATAR_SIZE, None, None);
+            widget_box.pack_start(&avatar, false, false, 18);
+
+            let details_box = gtk::Box::new(gtk::Orientation::Vertical, 6);
+
+            let name = match room.name {
+                ref n if n.is_none() || n.clone().unwrap().is_empty() => room.alias.clone(),
+                ref n => n.clone(),
+            };
+
+            let name_label = gtk::Label::new(None);
+            name_label.set_line_wrap(true);
+            name_label.set_line_wrap_mode(pango::WrapMode::WordChar);
+            name_label.set_markup(&format!(
+                "<b>{}</b>",
+                markup_text(&name.unwrap_or_default())
+            ));
+            name_label.set_justify(gtk::Justification::Left);
+            name_label.set_halign(gtk::Align::Start);
+            name_label.set_valign(gtk::Align::Start);
+            name_label.set_xalign(0.0);
+
+            let topic_label = gtk::Label::new(None);
+            if !room.topic.clone().unwrap_or_default().is_empty() {
+                topic_label.set_line_wrap(true);
+                topic_label.set_line_wrap_mode(pango::WrapMode::WordChar);
+                topic_label.set_lines(2);
+                topic_label.set_ellipsize(pango::EllipsizeMode::End);
+                topic_label.set_markup(&markup_text(&room.topic.clone().unwrap_or_default()));
+                topic_label.set_justify(gtk::Justification::Left);
+                topic_label.set_halign(gtk::Align::Start);
+                topic_label.set_valign(gtk::Align::Start);
+                topic_label.set_xalign(0.0);
+            }
+
+            let alias_label = gtk::Label::new(None);
+            alias_label.set_line_wrap(true);
+            alias_label.set_line_wrap_mode(pango::WrapMode::WordChar);
+            alias_label.set_markup(&format!(
+                "<span alpha=\"60%\">{}</span>",
+                room.alias.clone().unwrap_or_default()
+            ));
+            alias_label.set_justify(gtk::Justification::Left);
+            alias_label.set_halign(gtk::Align::Start);
+            alias_label.set_valign(gtk::Align::Start);
+            alias_label.set_xalign(0.0);
+
+            details_box.add(&name_label);
+            if !topic_label
+                .get_text()
+                .map_or(String::new(), |gstr| gstr.to_string())
+                .is_empty()
+            {
+                details_box.add(&topic_label);
+            }
+            details_box.add(&alias_label);
+
+            let membership_grid = gtk::Grid::new();
+            membership_grid.set_column_spacing(6);
+
+            let members_icon = gtk::Image::new_from_icon_name(
+                Some("system-users-symbolic"),
+                gtk::IconSize::Menu.into(),
+            );
+            members_icon.get_style_context().add_class("dim-label");
+
+            let members_count = gtk::Label::new(Some(&format!("{}", room.n_members)[..]));
+            members_count.get_style_context().add_class("dim-label");
+
+            let join_button = gtk::Button::new_with_label(i18n("Join").as_str());
+            let room_id = room.id.clone();
+            let backend = self.op.backend.clone();
+            let server_url = self.op.server_url.clone();
+            join_button.connect_clicked(move |_| {
+                backend
+                    .send(BKCommand::JoinRoom(
+                        server_url.clone(),
+                        access_token.clone(),
+                        room_id.clone(),
+                    ))
+                    .unwrap();
+            });
+            join_button.set_property_width_request(JOIN_BUTTON_WIDTH);
+
+            membership_grid.attach(&join_button, 0, 0, 4, 1);
+            membership_grid.attach(&members_icon, 5, 0, 1, 1);
+            membership_grid.attach(&members_count, 6, 0, 1, 1);
+
+            details_box.add(&membership_grid);
+
+            widget_box.pack_start(&details_box, true, true, 0);
+
+            widget_box.show_all();
         }
-        details_box.add(&alias_label);
-
-        let membership_grid = gtk::Grid::new();
-        membership_grid.set_column_spacing(6);
-
-        let members_icon = gtk::Image::new_from_icon_name(
-            Some("system-users-symbolic"),
-            gtk::IconSize::Menu.into(),
-        );
-        members_icon.get_style_context().add_class("dim-label");
-
-        let members_count = gtk::Label::new(Some(&format!("{}", room.n_members)[..]));
-        members_count.get_style_context().add_class("dim-label");
-
-        let join_button = gtk::Button::new_with_label(i18n("Join").as_str());
-        let room_id = room.id.clone();
-        let backend = self.op.backend.clone();
-        let server_url = self.op.server_url.clone();
-        join_button.connect_clicked(move |_| {
-            backend
-                .send(BKCommand::JoinRoom(server_url.clone(), room_id.clone()))
-                .unwrap();
-        });
-        join_button.set_property_width_request(JOIN_BUTTON_WIDTH);
-
-        membership_grid.attach(&join_button, 0, 0, 4, 1);
-        membership_grid.attach(&members_icon, 5, 0, 1, 1);
-        membership_grid.attach(&members_count, 6, 0, 1, 1);
-
-        details_box.add(&membership_grid);
-
-        widget_box.pack_start(&details_box, true, true, 0);
-
-        widget_box.show_all();
         widget_box
     }
 }
diff --git a/fractal-gtk/src/widgets/room_settings.rs b/fractal-gtk/src/widgets/room_settings.rs
index 24ed4cc5..56f52991 100644
--- a/fractal-gtk/src/widgets/room_settings.rs
+++ b/fractal-gtk/src/widgets/room_settings.rs
@@ -1,4 +1,5 @@
 use fractal_api::clone;
+use fractal_api::r0::AccessToken;
 use std::cell::RefCell;
 use std::rc::Rc;
 use std::sync::mpsc::Sender;
@@ -29,6 +30,7 @@ pub struct RoomSettings {
     members_list: Option<MembersList>,
     backend: Sender<BKCommand>,
     server_url: Url,
+    access_token: AccessToken,
 }
 
 impl RoomSettings {
@@ -38,6 +40,7 @@ impl RoomSettings {
         uid: Option<String>,
         room: Room,
         server_url: Url,
+        access_token: AccessToken,
     ) -> RoomSettings {
         let builder = gtk::Builder::new();
 
@@ -49,7 +52,8 @@ impl RoomSettings {
             .get_object::<gtk::Stack>("room_settings_stack")
             .expect("Can't find room_settings_stack in ui file.");
 
-        let actions = actions::RoomSettings::new(&window, &backend, server_url.clone());
+        let actions =
+            actions::RoomSettings::new(&window, &backend, server_url.clone(), access_token.clone());
         stack.insert_action_group("room-settings", Some(&actions));
 
         RoomSettings {
@@ -60,6 +64,7 @@ impl RoomSettings {
             members_list: None,
             backend,
             server_url,
+            access_token,
         }
     }
 
@@ -492,8 +497,12 @@ impl RoomSettings {
         button.set_sensitive(false);
         entry.set_editable(false);
 
-        let command =
-            BKCommand::SetRoomName(self.server_url.clone(), room.id.clone(), new_name.clone());
+        let command = BKCommand::SetRoomName(
+            self.server_url.clone(),
+            self.access_token.clone(),
+            room.id.clone(),
+            new_name.clone(),
+        );
         self.backend.send(command).unwrap();
 
         None
@@ -540,8 +549,12 @@ impl RoomSettings {
         button.set_sensitive(false);
         name.set_editable(false);
 
-        let command =
-            BKCommand::SetRoomTopic(self.server_url.clone(), room.id.clone(), topic.clone());
+        let command = BKCommand::SetRoomTopic(
+            self.server_url.clone(),
+            self.access_token.clone(),
+            room.id.clone(),
+            topic.clone(),
+        );
         self.backend.send(command).unwrap();
 
         None
diff --git a/fractal-matrix-api/src/backend/directory.rs b/fractal-matrix-api/src/backend/directory.rs
index e7e18615..6c58aaa7 100644
--- a/fractal-matrix-api/src/backend/directory.rs
+++ b/fractal-matrix-api/src/backend/directory.rs
@@ -21,41 +21,36 @@ use crate::r0::directory::post_public_rooms::Response as PublicRoomsResponse;
 use crate::r0::directory::post_public_rooms::ThirdPartyNetworks;
 use crate::r0::thirdparty::get_supported_protocols::request as get_supported_protocols;
 use crate::r0::thirdparty::get_supported_protocols::Parameters as SupportedProtocolsParameters;
+use crate::r0::thirdparty::get_supported_protocols::ProtocolInstance;
 use crate::r0::thirdparty::get_supported_protocols::Response as SupportedProtocolsResponse;
+use crate::r0::AccessToken;
 use crate::types::Room;
 
-pub fn protocols(bk: &Backend, base: Url) {
-    let tx = bk.tx.clone();
-    let access_token = bk.get_access_token();
-
+pub fn protocols(base: Url, access_token: AccessToken) -> Result<Vec<ProtocolInstance>, Error> {
     let params = SupportedProtocolsParameters { access_token };
 
-    thread::spawn(move || {
-        let query = get_supported_protocols(base, &params)
-            .map_err(Into::into)
-            .and_then(|request| {
-                HTTP_CLIENT
-                    .get_client()?
-                    .execute(request)?
-                    .json::<SupportedProtocolsResponse>()
-                    .map_err(Into::into)
-            })
-            .map(|response| {
-                response
-                    .into_iter()
-                    .flat_map(|(_, protocol)| protocol.instances.into_iter())
-                    .collect()
-            });
-
-        tx.send(BKResponse::DirectoryProtocols(query))
-            .expect_log("Connection closed");
-    });
+    get_supported_protocols(base, &params)
+        .map_err(Into::into)
+        .and_then(|request| {
+            HTTP_CLIENT
+                .get_client()?
+                .execute(request)?
+                .json::<SupportedProtocolsResponse>()
+                .map_err(Into::into)
+        })
+        .map(|response| {
+            response
+                .into_iter()
+                .flat_map(|(_, protocol)| protocol.instances.into_iter())
+                .collect()
+        })
 }
 
 pub fn room_search(
     bk: &Backend,
     base: Url,
-    homeserver: Option<String>,
+    access_token: AccessToken,
+    homeserver: Option<String>, // TODO: Use Url or HostAndPort?
     generic_search_term: Option<String>,
     third_party: Option<String>,
     more: bool,
@@ -78,7 +73,6 @@ pub fn room_search(
         })
         .unwrap_or(Ok(None))?;
 
-    let access_token = bk.get_access_token();
     let since = if more {
         Some(data.lock().unwrap().rooms_since.clone())
     } else {
diff --git a/fractal-matrix-api/src/backend/media.rs b/fractal-matrix-api/src/backend/media.rs
index 81ae7998..52f45f30 100644
--- a/fractal-matrix-api/src/backend/media.rs
+++ b/fractal-matrix-api/src/backend/media.rs
@@ -1,4 +1,3 @@
-use crate::backend::types::BKResponse;
 use crate::backend::types::Backend;
 use crate::error::Error;
 use crate::globals;
@@ -40,19 +39,17 @@ pub fn get_media_async(bk: &Backend, baseu: Url, media: String, tx: Sender<Strin
 pub fn get_media_list_async(
     bk: &Backend,
     baseu: Url,
-    roomid: &str,
+    access_token: AccessToken,
+    roomid: String,
     first_media_id: Option<String>,
     prev_batch: Option<String>,
     tx: Sender<(Vec<Message>, String)>,
 ) {
-    let tk = bk.get_access_token();
-    let room = String::from(roomid);
-
     semaphore(bk.limit_threads.clone(), move || {
         let media_list = get_room_media_list(
             &baseu,
-            &tk,
-            &room,
+            &access_token,
+            &roomid,
             globals::PAGE_LIMIT,
             first_media_id,
             &prev_batch,
@@ -62,15 +59,6 @@ pub fn get_media_list_async(
     });
 }
 
-pub fn get_media(bk: &Backend, baseu: Url, media: String) {
-    let tx = bk.tx.clone();
-    thread::spawn(move || {
-        let fname = dw_media(&baseu, &media, ContentType::Download, None);
-        tx.send(BKResponse::Media(fname))
-            .expect_log("Connection closed");
-    });
-}
-
 pub fn get_media_url(bk: &Backend, baseu: Url, media: String, tx: Sender<String>) {
     semaphore(bk.limit_threads.clone(), move || {
         let uri = resolve_media_url(&baseu, &media, ContentType::Download)
diff --git a/fractal-matrix-api/src/backend/mod.rs b/fractal-matrix-api/src/backend/mod.rs
index 24d8ccb7..99b349cb 100644
--- a/fractal-matrix-api/src/backend/mod.rs
+++ b/fractal-matrix-api/src/backend/mod.rs
@@ -7,6 +7,8 @@ use std::thread;
 use url::Url;
 
 use crate::util::client_url;
+use crate::util::dw_media;
+use crate::util::ContentType;
 use crate::util::ResultExpectLog;
 
 use crate::error::Error;
@@ -36,7 +38,6 @@ impl Backend {
     pub fn new(tx: Sender<BKResponse>) -> Backend {
         let data = BackendData {
             user_id: String::from("Guest"),
-            access_token: String::new(),
             scalar_token: None,
             scalar_url: Url::parse("https://scalar.vector.im";)
                 .expect("Wrong scalar_url value in BackendData"),
@@ -55,10 +56,6 @@ impl Backend {
         }
     }
 
-    fn get_access_token(&self) -> AccessToken {
-        AccessToken::from(self.data.lock().unwrap().access_token.clone())
-    }
-
     fn url(
         &self,
         base: Url,
@@ -94,7 +91,9 @@ impl Backend {
                 let r = register::login(self, user, passwd, &server);
                 bkerror!(r, tx, BKResponse::LoginError);
             }
-            Ok(BKCommand::Logout(server)) => register::logout(self, server),
+            Ok(BKCommand::Logout(server, access_token)) => {
+                register::logout(self, server, access_token)
+            }
             Ok(BKCommand::Register(user, passwd, server)) => {
                 let r = register::register(self, user, passwd, &server);
                 bkerror!(r, tx, BKResponse::LoginError);
@@ -107,34 +106,84 @@ impl Backend {
 
             // User module
             Ok(BKCommand::GetUsername(server)) => user::get_username(self, server),
-            Ok(BKCommand::SetUserName(server, name)) => user::set_username(self, server, name),
-            Ok(BKCommand::GetThreePID(server)) => user::get_threepid(self, server),
-            Ok(BKCommand::GetTokenEmail(server, identity, email, client_secret)) => {
-                let r = user::get_email_token(self, server, identity, email, client_secret);
-                bkerror2!(r, tx, BKResponse::GetTokenEmail);
+            Ok(BKCommand::SetUserName(server, access_token, name)) => {
+                user::set_username(self, server, access_token, name)
             }
-            Ok(BKCommand::GetTokenPhone(server, identity, phone, client_secret)) => {
-                let r = user::get_phone_token(self, server, identity, phone, client_secret);
-                bkerror2!(r, tx, BKResponse::GetTokenPhone);
+            Ok(BKCommand::GetThreePID(server, access_token)) => {
+                thread::spawn(move || {
+                    let query = user::get_threepid(server, access_token);
+                    tx.send(BKResponse::GetThreePID(query))
+                        .expect_log("Connection closed");
+                });
             }
-            Ok(BKCommand::SubmitPhoneToken(server, client_secret, sid, token)) => {
-                user::submit_phone_token(self, server, client_secret, sid, token)
+            Ok(BKCommand::GetTokenEmail(server, access_token, identity, email, client_secret)) => {
+                thread::spawn(move || {
+                    let query =
+                        user::get_email_token(server, access_token, identity, email, client_secret);
+                    tx.send(BKResponse::GetTokenEmail(query))
+                        .expect_log("Connection closed");
+                });
             }
-            Ok(BKCommand::AddThreePID(server, identity, client_secret, sid)) => {
-                let r = user::add_threepid(self, server, identity, client_secret, sid);
-                bkerror2!(r, tx, BKResponse::AddThreePID);
+            Ok(BKCommand::GetTokenPhone(server, access_token, identity, phone, client_secret)) => {
+                thread::spawn(move || {
+                    let query =
+                        user::get_phone_token(server, access_token, identity, phone, client_secret);
+                    tx.send(BKResponse::GetTokenPhone(query))
+                        .expect_log("Connection closed");
+                });
             }
-            Ok(BKCommand::DeleteThreePID(server, medium, address)) => {
-                user::delete_three_pid(self, server, medium, address)
+            Ok(BKCommand::SubmitPhoneToken(server, client_secret, sid, token)) => {
+                thread::spawn(move || {
+                    let query = user::submit_phone_token(server, client_secret, sid, token);
+                    tx.send(BKResponse::SubmitPhoneToken(query))
+                        .expect_log("Connection closed");
+                });
             }
-            Ok(BKCommand::ChangePassword(server, username, old_password, new_password)) => {
-                user::change_password(self, server, username, old_password, new_password)
+            Ok(BKCommand::AddThreePID(server, access_token, identity, client_secret, sid)) => {
+                thread::spawn(move || {
+                    let query =
+                        user::add_threepid(server, access_token, identity, client_secret, sid);
+                    tx.send(BKResponse::AddThreePID(query))
+                        .expect_log("Connection closed");
+                });
             }
-            Ok(BKCommand::AccountDestruction(server, username, password)) => {
-                user::account_destruction(self, server, username, password)
+            Ok(BKCommand::DeleteThreePID(server, access_token, medium, address)) => {
+                thread::spawn(move || {
+                    let query = user::delete_three_pid(server, access_token, medium, address);
+                    tx.send(BKResponse::DeleteThreePID(query))
+                        .expect_log("Connection closed");
+                });
+            }
+            Ok(BKCommand::ChangePassword(
+                server,
+                access_token,
+                username,
+                old_password,
+                new_password,
+            )) => {
+                thread::spawn(move || {
+                    let query = user::change_password(
+                        server,
+                        access_token,
+                        username,
+                        old_password,
+                        new_password,
+                    );
+                    tx.send(BKResponse::ChangePassword(query))
+                        .expect_log("Connection closed");
+                });
+            }
+            Ok(BKCommand::AccountDestruction(server, access_token, username, password)) => {
+                thread::spawn(move || {
+                    let query = user::account_destruction(server, access_token, username, password);
+                    tx.send(BKResponse::AccountDestruction(query))
+                        .expect_log("Connection closed");
+                });
             }
             Ok(BKCommand::GetAvatar(server)) => user::get_avatar(self, server),
-            Ok(BKCommand::SetUserAvatar(server, file)) => user::set_user_avatar(self, server, file),
+            Ok(BKCommand::SetUserAvatar(server, access_token, file)) => {
+                user::set_user_avatar(self, server, access_token, file)
+            }
             Ok(BKCommand::GetAvatarAsync(server, member, ctx)) => {
                 user::get_avatar_async(self, server, member, ctx)
             }
@@ -142,106 +191,126 @@ impl Backend {
                 user::get_user_info_async(self, server, sender, ctx)
             }
             Ok(BKCommand::GetUserNameAsync(server, sender, ctx)) => {
-                user::get_username_async(server, sender, ctx)
+                thread::spawn(move || {
+                    let query = user::get_username_async(server, sender);
+                    ctx.send(query).expect_log("Connection closed");
+                });
+            }
+            Ok(BKCommand::UserSearch(server, access_token, term)) => {
+                thread::spawn(move || {
+                    let query = user::search(server, access_token, term);
+                    tx.send(BKResponse::UserSearch(query))
+                        .expect_log("Connection closed");
+                });
             }
-            Ok(BKCommand::UserSearch(server, term)) => user::search(self, server, term),
 
             // Sync module
-            Ok(BKCommand::Sync(server, since, initial)) => sync::sync(self, server, since, initial),
-            Ok(BKCommand::SyncForced(server)) => sync::force_sync(self, server),
+            Ok(BKCommand::Sync(server, access_token, since, initial)) => {
+                sync::sync(self, server, access_token, since, initial)
+            }
+            Ok(BKCommand::SyncForced(server, access_token)) => {
+                sync::force_sync(self, server, access_token)
+            }
 
             // Room module
-            Ok(BKCommand::GetRoomMembers(server, room)) => {
-                let r = room::get_room_members(self, server, room);
+            Ok(BKCommand::GetRoomMembers(server, access_token, room)) => {
+                let r = room::get_room_members(self, server, access_token, room);
                 bkerror2!(r, tx, BKResponse::RoomMembers);
             }
-            Ok(BKCommand::GetRoomMessages(server, room, from)) => {
-                let r = room::get_room_messages(self, server, room, from);
+            Ok(BKCommand::GetRoomMessages(server, access_token, room, from)) => {
+                let r = room::get_room_messages(self, server, access_token, room, from);
                 bkerror2!(r, tx, BKResponse::RoomMessagesTo);
             }
-            Ok(BKCommand::GetRoomMessagesFromMsg(server, room, from)) => {
-                room::get_room_messages_from_msg(self, server, room, from)
+            Ok(BKCommand::GetRoomMessagesFromMsg(server, access_token, room, from)) => {
+                room::get_room_messages_from_msg(self, server, access_token, room, from)
             }
-            Ok(BKCommand::GetMessageContext(server, message)) => {
-                let r = room::get_message_context(self, server, message);
+            Ok(BKCommand::GetMessageContext(server, access_token, message)) => {
+                let r = room::get_message_context(self, server, access_token, message);
                 bkerror2!(r, tx, BKResponse::RoomMessagesTo);
             }
-            Ok(BKCommand::SendMsg(server, msg)) => {
-                let r = room::send_msg(self, server, msg);
+            Ok(BKCommand::SendMsg(server, access_token, msg)) => {
+                let r = room::send_msg(self, server, access_token, msg);
                 bkerror2!(r, tx, BKResponse::SentMsg);
             }
-            Ok(BKCommand::SendMsgRedaction(server, msg)) => {
-                let r = room::redact_msg(self, server, &msg);
+            Ok(BKCommand::SendMsgRedaction(server, access_token, msg)) => {
+                let r = room::redact_msg(self, server, access_token, &msg);
                 bkerror2!(r, tx, BKResponse::SentMsgRedaction);
             }
-            Ok(BKCommand::SendTyping(server, room)) => {
-                let r = room::send_typing(self, server, room);
+            Ok(BKCommand::SendTyping(server, access_token, room)) => {
+                let r = room::send_typing(self, server, access_token, room);
                 bkerror!(r, tx, BKResponse::SendTypingError);
             }
-            Ok(BKCommand::SetRoom(server, id)) => {
-                let r = room::set_room(self, server, id);
+            Ok(BKCommand::SetRoom(server, access_token, id)) => {
+                let r = room::set_room(self, server, access_token, id);
                 bkerror!(r, tx, BKResponse::SetRoomError);
             }
-            Ok(BKCommand::GetRoomAvatar(server, room)) => {
-                let r = room::get_room_avatar(self, server, room);
+            Ok(BKCommand::GetRoomAvatar(server, access_token, room)) => {
+                let r = room::get_room_avatar(self, server, access_token, room);
                 bkerror2!(r, tx, BKResponse::RoomAvatar);
             }
-            Ok(BKCommand::JoinRoom(server, roomid)) => {
-                let r = room::join_room(self, server, roomid);
+            Ok(BKCommand::JoinRoom(server, access_token, roomid)) => {
+                let r = room::join_room(self, server, access_token, roomid);
                 bkerror2!(r, tx, BKResponse::JoinRoom);
             }
-            Ok(BKCommand::LeaveRoom(server, roomid)) => {
-                let r = room::leave_room(self, server, &roomid);
+            Ok(BKCommand::LeaveRoom(server, access_token, roomid)) => {
+                let r = room::leave_room(self, server, access_token, roomid);
                 bkerror2!(r, tx, BKResponse::LeaveRoom);
             }
-            Ok(BKCommand::MarkAsRead(server, roomid, evid)) => {
-                let r = room::mark_as_read(self, server, &roomid, &evid);
+            Ok(BKCommand::MarkAsRead(server, access_token, roomid, evid)) => {
+                let r = room::mark_as_read(self, server, access_token, roomid, evid);
                 bkerror2!(r, tx, BKResponse::MarkedAsRead);
             }
-            Ok(BKCommand::SetRoomName(server, roomid, name)) => {
-                let r = room::set_room_name(self, server, &roomid, &name);
+            Ok(BKCommand::SetRoomName(server, access_token, roomid, name)) => {
+                let r = room::set_room_name(self, server, access_token, roomid, name);
                 bkerror2!(r, tx, BKResponse::SetRoomName);
             }
-            Ok(BKCommand::SetRoomTopic(server, roomid, topic)) => {
-                let r = room::set_room_topic(self, server, &roomid, &topic);
+            Ok(BKCommand::SetRoomTopic(server, access_token, roomid, topic)) => {
+                let r = room::set_room_topic(self, server, access_token, roomid, topic);
                 bkerror2!(r, tx, BKResponse::SetRoomTopic);
             }
-            Ok(BKCommand::SetRoomAvatar(server, roomid, fname)) => {
-                let r = room::set_room_avatar(self, server, &roomid, &fname);
+            Ok(BKCommand::SetRoomAvatar(server, access_token, roomid, fname)) => {
+                let r = room::set_room_avatar(self, server, access_token, roomid, fname);
                 bkerror2!(r, tx, BKResponse::SetRoomAvatar);
             }
-            Ok(BKCommand::AttachFile(server, msg)) => {
-                let r = room::attach_file(self, server, msg);
+            Ok(BKCommand::AttachFile(server, access_token, msg)) => {
+                let r = room::attach_file(self, server, access_token, msg);
                 bkerror2!(r, tx, BKResponse::AttachedFile);
             }
-            Ok(BKCommand::NewRoom(server, name, privacy, internalid)) => {
-                let r = room::new_room(self, server, &name, privacy, internalid.clone());
+            Ok(BKCommand::NewRoom(server, access_token, name, privacy, internalid)) => {
+                let r = room::new_room(
+                    self,
+                    server,
+                    access_token,
+                    name,
+                    privacy,
+                    internalid.clone(),
+                );
                 if let Err(e) = r {
                     tx.send(BKResponse::NewRoom(Err(e), internalid))
                         .expect_log("Connection closed");
                 }
             }
-            Ok(BKCommand::DirectChat(server, user, internalid)) => {
-                let r = room::direct_chat(self, server, &user, internalid.clone());
+            Ok(BKCommand::DirectChat(server, access_token, user, internalid)) => {
+                let r = room::direct_chat(self, server, access_token, user, internalid.clone());
                 if let Err(e) = r {
                     tx.send(BKResponse::NewRoom(Err(e), internalid))
                         .expect_log("Connection closed");
                 }
             }
-            Ok(BKCommand::AddToFav(server, roomid, tofav)) => {
-                let r = room::add_to_fav(self, server, roomid, tofav);
+            Ok(BKCommand::AddToFav(server, access_token, roomid, tofav)) => {
+                let r = room::add_to_fav(self, server, access_token, roomid, tofav);
                 bkerror2!(r, tx, BKResponse::AddedToFav);
             }
-            Ok(BKCommand::AcceptInv(server, roomid)) => {
-                let r = room::join_room(self, server, roomid);
+            Ok(BKCommand::AcceptInv(server, access_token, roomid)) => {
+                let r = room::join_room(self, server, access_token, roomid);
                 bkerror2!(r, tx, BKResponse::JoinRoom);
             }
-            Ok(BKCommand::RejectInv(server, roomid)) => {
-                let r = room::leave_room(self, server, &roomid);
+            Ok(BKCommand::RejectInv(server, access_token, roomid)) => {
+                let r = room::leave_room(self, server, access_token, roomid);
                 bkerror2!(r, tx, BKResponse::LeaveRoom);
             }
-            Ok(BKCommand::Invite(server, room, userid)) => {
-                let r = room::invite(self, server, &room, &userid);
+            Ok(BKCommand::Invite(server, access_token, room, userid)) => {
+                let r = room::invite(self, server, access_token, room, userid);
                 bkerror!(r, tx, BKResponse::InviteError);
             }
 
@@ -252,10 +321,29 @@ impl Backend {
             Ok(BKCommand::GetMediaAsync(server, media, ctx)) => {
                 media::get_media_async(self, server, media, ctx)
             }
-            Ok(BKCommand::GetMediaListAsync(server, roomid, first_media_id, prev_batch, ctx)) => {
-                media::get_media_list_async(self, server, &roomid, first_media_id, prev_batch, ctx)
+            Ok(BKCommand::GetMediaListAsync(
+                server,
+                access_token,
+                roomid,
+                first_media_id,
+                prev_batch,
+                ctx,
+            )) => media::get_media_list_async(
+                self,
+                server,
+                access_token,
+                roomid,
+                first_media_id,
+                prev_batch,
+                ctx,
+            ),
+            Ok(BKCommand::GetMedia(server, media)) => {
+                thread::spawn(move || {
+                    let fname = dw_media(&server, &media, ContentType::Download, None);
+                    tx.send(BKResponse::Media(fname))
+                        .expect_log("Connection closed");
+                });
             }
-            Ok(BKCommand::GetMedia(server, media)) => media::get_media(self, server, media),
             Ok(BKCommand::GetMediaUrl(server, media, ctx)) => {
                 media::get_media_url(self, server, media, ctx)
             }
@@ -265,8 +353,14 @@ impl Backend {
             }
 
             // Directory module
-            Ok(BKCommand::DirectoryProtocols(server)) => directory::protocols(self, server),
-            Ok(BKCommand::DirectorySearch(server, dhs, dq, dtp, more)) => {
+            Ok(BKCommand::DirectoryProtocols(server, access_token)) => {
+                thread::spawn(move || {
+                    let query = directory::protocols(server, access_token);
+                    tx.send(BKResponse::DirectoryProtocols(query))
+                        .expect_log("Connection closed");
+                });
+            }
+            Ok(BKCommand::DirectorySearch(server, access_token, dhs, dq, dtp, more)) => {
                 let hs = match dhs {
                     ref a if a.is_empty() => None,
                     b => Some(b),
@@ -282,21 +376,21 @@ impl Backend {
                     b => Some(b),
                 };
 
-                let r = directory::room_search(self, server, hs, q, tp, more);
+                let r = directory::room_search(self, server, access_token, hs, q, tp, more);
                 bkerror2!(r, tx, BKResponse::DirectorySearch);
             }
 
             // Stickers module
-            Ok(BKCommand::ListStickers) => {
-                let r = stickers::list(self);
+            Ok(BKCommand::ListStickers(access_token)) => {
+                let r = stickers::list(self, access_token);
                 bkerror2!(r, tx, BKResponse::Stickers);
             }
-            Ok(BKCommand::SendSticker(server, room, sticker)) => {
-                let r = stickers::send(self, server, &room, &sticker);
+            Ok(BKCommand::SendSticker(server, access_token, room, sticker)) => {
+                let r = stickers::send(self, server, access_token, room, sticker);
                 bkerror2!(r, tx, BKResponse::Stickers);
             }
-            Ok(BKCommand::PurchaseSticker(group)) => {
-                let r = stickers::purchase(self, &group);
+            Ok(BKCommand::PurchaseSticker(access_token, group)) => {
+                let r = stickers::purchase(self, access_token, group);
                 bkerror2!(r, tx, BKResponse::Stickers);
             }
 
diff --git a/fractal-matrix-api/src/backend/register.rs b/fractal-matrix-api/src/backend/register.rs
index 385a0e87..32ffd90d 100644
--- a/fractal-matrix-api/src/backend/register.rs
+++ b/fractal-matrix-api/src/backend/register.rs
@@ -19,6 +19,7 @@ use crate::r0::account::Identifier;
 use crate::r0::account::UserIdentifier;
 use crate::r0::server::domain_info::request as domain_info;
 use crate::r0::server::domain_info::Response as DomainInfoResponse;
+use crate::r0::AccessToken;
 use crate::r0::Medium;
 use crate::util::ResultExpectLog;
 use crate::util::HTTP_CLIENT;
@@ -51,15 +52,10 @@ pub fn guest(bk: &Backend, server: &str) -> Result<(), Error> {
         match query {
             Ok(response) => {
                 let uid = response.user_id.to_string();
-                let tk = response
-                    .access_token
-                    .as_ref()
-                    .map(ToString::to_string)
-                    .unwrap_or_default();
+                let tk = response.access_token;
                 let dev = response.device_id;
 
                 data.lock().unwrap().user_id = uid.clone();
-                data.lock().unwrap().access_token = tk.clone();
                 data.lock().unwrap().since = None;
                 tx.send(BKResponse::Token(uid, tk, dev))  // TODO: Use UserId and DeviceId
                     .expect_log("Connection closed");
@@ -119,19 +115,14 @@ pub fn login(bk: &Backend, user: String, password: String, server: &str) -> Resu
                     .as_ref()
                     .map(ToString::to_string)
                     .unwrap_or(user);
-                let tk = response
-                    .access_token
-                    .as_ref()
-                    .map(ToString::to_string)
-                    .unwrap_or_default();
+                let tk = response.access_token;
                 let dev = response.device_id;
 
-                if uid.is_empty() || tk.is_empty() {
+                if uid.is_empty() || tk.is_none() {
                     tx.send(BKResponse::LoginError(Error::BackendError))
                         .expect_log("Connection closed");
                 } else {
                     data.lock().unwrap().user_id = uid.clone();
-                    data.lock().unwrap().access_token = tk.clone();
                     data.lock().unwrap().since = None;
                     tx.send(BKResponse::Token(uid, tk, dev))  // TODO: Use UserId and DeviceId
                         .expect_log("Connection closed");
@@ -147,19 +138,17 @@ pub fn login(bk: &Backend, user: String, password: String, server: &str) -> Resu
     Ok(())
 }
 
-pub fn set_token(bk: &Backend, token: String, uid: String) {
-    bk.data.lock().unwrap().access_token = token.clone();
+pub fn set_token(bk: &Backend, token: AccessToken, uid: String) {
     bk.data.lock().unwrap().user_id = uid.clone();
     bk.data.lock().unwrap().since = None;
     bk.tx
-        .send(BKResponse::Token(uid, token, None))
+        .send(BKResponse::Token(uid, Some(token), None))
         .expect_log("Connection closed");
 }
 
-pub fn logout(bk: &Backend, server: Url) {
+pub fn logout(bk: &Backend, server: Url, access_token: AccessToken) {
     let data = bk.data.clone();
     let tx = bk.tx.clone();
-    let access_token = bk.get_access_token();
 
     let params = LogoutParameters { access_token };
 
@@ -176,7 +165,6 @@ pub fn logout(bk: &Backend, server: Url) {
 
         if query.is_ok() {
             data.lock().unwrap().user_id = Default::default();
-            data.lock().unwrap().access_token = Default::default();
             data.lock().unwrap().since = None;
         }
 
@@ -211,15 +199,10 @@ pub fn register(bk: &Backend, user: String, password: String, server: &str) -> R
         match query {
             Ok(response) => {
                 let uid = response.user_id.to_string();
-                let tk = response
-                    .access_token
-                    .as_ref()
-                    .map(ToString::to_string)
-                    .unwrap_or_default();
+                let tk = response.access_token;
                 let dev = response.device_id;
 
                 data.lock().unwrap().user_id = uid.clone();
-                data.lock().unwrap().access_token = tk.clone();
                 data.lock().unwrap().since = None;
                 tx.send(BKResponse::Token(uid, tk, dev))  // TODO: Use UserId
                     .expect_log("Connection closed");
diff --git a/fractal-matrix-api/src/backend/room.rs b/fractal-matrix-api/src/backend/room.rs
index ff0e8dda..fa96bd26 100644
--- a/fractal-matrix-api/src/backend/room.rs
+++ b/fractal-matrix-api/src/backend/room.rs
@@ -40,16 +40,26 @@ use serde_json::Value as JsonValue;
 
 // FIXME: Remove this function, this is used only to request information we should already have
 // when opening a room
-pub fn set_room(bk: &Backend, base: Url, id: String) -> Result<(), Error> {
+pub fn set_room(
+    bk: &Backend,
+    base: Url,
+    access_token: AccessToken,
+    id: String,
+) -> Result<(), Error> {
     /* FIXME: remove clone and pass id by reference */
-    get_room_avatar(bk, base.clone(), id.clone())?;
-    get_room_detail(bk, base, id.clone(), String::from("m.room.topic"))?;
+    get_room_avatar(bk, base.clone(), access_token.clone(), id.clone())?;
+    get_room_detail(bk, base, access_token, id, String::from("m.room.topic"))?;
 
     Ok(())
 }
 
-pub fn get_room_detail(bk: &Backend, base: Url, roomid: String, key: String) -> Result<(), Error> {
-    let access_token = bk.get_access_token();
+pub fn get_room_detail(
+    bk: &Backend,
+    base: Url,
+    access_token: AccessToken,
+    roomid: String,
+    key: String,
+) -> Result<(), Error> {
     let url = bk.url(
         base,
         &access_token,
@@ -77,8 +87,12 @@ pub fn get_room_detail(bk: &Backend, base: Url, roomid: String, key: String) ->
     Ok(())
 }
 
-pub fn get_room_avatar(bk: &Backend, baseu: Url, roomid: String) -> Result<(), Error> {
-    let access_token = bk.get_access_token();
+pub fn get_room_avatar(
+    bk: &Backend,
+    baseu: Url,
+    access_token: AccessToken,
+    roomid: String,
+) -> Result<(), Error> {
     let url = bk.url(
         baseu.clone(),
         &access_token,
@@ -119,8 +133,12 @@ pub fn get_room_avatar(bk: &Backend, baseu: Url, roomid: String) -> Result<(), E
     Ok(())
 }
 
-pub fn get_room_members(bk: &Backend, base: Url, roomid: String) -> Result<(), Error> {
-    let access_token = bk.get_access_token();
+pub fn get_room_members(
+    bk: &Backend,
+    base: Url,
+    access_token: AccessToken,
+    roomid: String,
+) -> Result<(), Error> {
     let url = bk.url(
         base,
         &access_token,
@@ -159,10 +177,10 @@ pub fn get_room_members(bk: &Backend, base: Url, roomid: String) -> Result<(), E
 pub fn get_room_messages(
     bk: &Backend,
     base: Url,
+    access_token: AccessToken,
     roomid: String,
     from: String,
 ) -> Result<(), Error> {
-    let access_token = bk.get_access_token();
     let params = vec![
         ("from", from),
         ("dir", String::from("b")),
@@ -202,16 +220,21 @@ pub fn get_room_messages(
     Ok(())
 }
 
-pub fn get_room_messages_from_msg(bk: &Backend, baseu: Url, roomid: String, msg: Message) {
+pub fn get_room_messages_from_msg(
+    bk: &Backend,
+    baseu: Url,
+    tk: AccessToken,
+    roomid: String,
+    msg: Message,
+) {
     // first of all, we calculate the from param using the context api, then we call the
     // normal get_room_messages
-    let tk = bk.get_access_token();
     let itx = bk.internal_tx.clone();
 
     thread::spawn(move || {
         if let Ok(from) = get_prev_batch_from(&baseu, &tk, &roomid, &msg.id) {
             if let Some(t) = itx {
-                t.send(BKCommand::GetRoomMessages(baseu, roomid, from))
+                t.send(BKCommand::GetRoomMessages(baseu, tk, roomid, from))
                     .expect_log("Connection closed");
             }
         }
@@ -277,19 +300,27 @@ fn parse_context(
     Ok(())
 }
 
-pub fn get_message_context(bk: &Backend, baseu: Url, msg: Message) -> Result<(), Error> {
+pub fn get_message_context(
+    bk: &Backend,
+    baseu: Url,
+    tk: AccessToken,
+    msg: Message,
+) -> Result<(), Error> {
     let tx = bk.tx.clone();
     let roomid = msg.room.clone();
-    let tk = bk.get_access_token();
 
     parse_context(tx, tk, baseu, roomid, &msg.id, globals::PAGE_LIMIT)?;
 
     Ok(())
 }
 
-pub fn send_msg(bk: &Backend, base: Url, msg: Message) -> Result<(), Error> {
+pub fn send_msg(
+    bk: &Backend,
+    base: Url,
+    access_token: AccessToken,
+    msg: Message,
+) -> Result<(), Error> {
     let roomid = msg.room.clone();
-    let access_token = bk.get_access_token();
 
     let url = bk.url(
         base,
@@ -339,8 +370,12 @@ pub fn send_msg(bk: &Backend, base: Url, msg: Message) -> Result<(), Error> {
     Ok(())
 }
 
-pub fn send_typing(bk: &Backend, base: Url, roomid: String) -> Result<(), Error> {
-    let access_token = bk.get_access_token();
+pub fn send_typing(
+    bk: &Backend,
+    base: Url,
+    access_token: AccessToken,
+    roomid: String,
+) -> Result<(), Error> {
     let userid = bk.data.lock().unwrap().user_id.clone();
     let url = bk.url(
         base,
@@ -363,10 +398,14 @@ pub fn send_typing(bk: &Backend, base: Url, roomid: String) -> Result<(), Error>
     Ok(())
 }
 
-pub fn redact_msg(bk: &Backend, base: Url, msg: &Message) -> Result<(), Error> {
+pub fn redact_msg(
+    bk: &Backend,
+    base: Url,
+    access_token: AccessToken,
+    msg: &Message,
+) -> Result<(), Error> {
     let roomid = msg.room.clone();
     let txnid = msg.id.clone();
-    let access_token = bk.get_access_token();
 
     let url = bk.url(
         base,
@@ -401,8 +440,12 @@ pub fn redact_msg(bk: &Backend, base: Url, msg: &Message) -> Result<(), Error> {
     Ok(())
 }
 
-pub fn join_room(bk: &Backend, base: Url, roomid: String) -> Result<(), Error> {
-    let access_token = bk.get_access_token();
+pub fn join_room(
+    bk: &Backend,
+    base: Url,
+    access_token: AccessToken,
+    roomid: String,
+) -> Result<(), Error> {
     let url = bk.url(
         base,
         &access_token,
@@ -428,8 +471,12 @@ pub fn join_room(bk: &Backend, base: Url, roomid: String) -> Result<(), Error> {
     Ok(())
 }
 
-pub fn leave_room(bk: &Backend, base: Url, roomid: &str) -> Result<(), Error> {
-    let access_token = bk.get_access_token();
+pub fn leave_room(
+    bk: &Backend,
+    base: Url,
+    access_token: AccessToken,
+    roomid: String,
+) -> Result<(), Error> {
     let url = bk.url(
         base,
         &access_token,
@@ -453,8 +500,13 @@ pub fn leave_room(bk: &Backend, base: Url, roomid: &str) -> Result<(), Error> {
     Ok(())
 }
 
-pub fn mark_as_read(bk: &Backend, base: Url, roomid: &str, eventid: &str) -> Result<(), Error> {
-    let access_token = bk.get_access_token();
+pub fn mark_as_read(
+    bk: &Backend,
+    base: Url,
+    access_token: AccessToken,
+    roomid: String,
+    eventid: String,
+) -> Result<(), Error> {
     let url = bk.url(
         base.clone(),
         &access_token,
@@ -462,9 +514,9 @@ pub fn mark_as_read(bk: &Backend, base: Url, roomid: &str, eventid: &str) -> Res
         vec![],
     )?;
 
+    let r = roomid.clone();
+    let e = eventid.clone();
     let tx = bk.tx.clone();
-    let r = String::from(roomid);
-    let e = String::from(eventid);
     post!(
         &url,
         move |_: JsonValue| {
@@ -496,8 +548,13 @@ pub fn mark_as_read(bk: &Backend, base: Url, roomid: &str, eventid: &str) -> Res
     Ok(())
 }
 
-pub fn set_room_name(bk: &Backend, base: Url, roomid: &str, name: &str) -> Result<(), Error> {
-    let access_token = bk.get_access_token();
+pub fn set_room_name(
+    bk: &Backend,
+    base: Url,
+    access_token: AccessToken,
+    roomid: String,
+    name: String,
+) -> Result<(), Error> {
     let url = bk.url(
         base,
         &access_token,
@@ -527,8 +584,13 @@ pub fn set_room_name(bk: &Backend, base: Url, roomid: &str, name: &str) -> Resul
     Ok(())
 }
 
-pub fn set_room_topic(bk: &Backend, base: Url, roomid: &str, topic: &str) -> Result<(), Error> {
-    let access_token = bk.get_access_token();
+pub fn set_room_topic(
+    bk: &Backend,
+    base: Url,
+    access_token: AccessToken,
+    roomid: String,
+    topic: String,
+) -> Result<(), Error> {
     let url = bk.url(
         base,
         &access_token,
@@ -558,8 +620,13 @@ pub fn set_room_topic(bk: &Backend, base: Url, roomid: &str, topic: &str) -> Res
     Ok(())
 }
 
-pub fn set_room_avatar(bk: &Backend, baseu: Url, roomid: &str, avatar: &str) -> Result<(), Error> {
-    let tk = bk.get_access_token();
+pub fn set_room_avatar(
+    bk: &Backend,
+    baseu: Url,
+    tk: AccessToken,
+    roomid: String,
+    avatar: String,
+) -> Result<(), Error> {
     let params = &[("access_token", tk.to_string())];
     let mediaurl = media_url(&baseu, "upload", params)?;
     let roomurl = bk.url(
@@ -602,7 +669,12 @@ pub fn set_room_avatar(bk: &Backend, baseu: Url, roomid: &str, avatar: &str) ->
     Ok(())
 }
 
-pub fn attach_file(bk: &Backend, baseu: Url, mut msg: Message) -> Result<(), Error> {
+pub fn attach_file(
+    bk: &Backend,
+    baseu: Url,
+    tk: AccessToken,
+    mut msg: Message,
+) -> Result<(), Error> {
     let fname = msg.url.clone().unwrap_or_default();
     let extra_content: Option<ExtraContent> = {
         msg.clone()
@@ -616,15 +688,14 @@ pub fn attach_file(bk: &Backend, baseu: Url, mut msg: Message) -> Result<(), Err
 
     let tx = bk.tx.clone();
     let itx = bk.internal_tx.clone();
-    let tk = bk.get_access_token();
 
     if fname.starts_with("mxc://") && thumb.starts_with("mxc://") {
-        return send_msg(bk, baseu, msg);
+        return send_msg(bk, baseu, tk, msg);
     }
 
     thread::spawn(move || {
         if thumb != "" {
-            match upload_file(&tk, &baseu, &thumb) {
+            match upload_file(&baseu, &tk, &thumb) {
                 Err(err) => {
                     tx.send(BKResponse::AttachedFile(Err(err)))
                         .expect_log("Connection closed");
@@ -640,7 +711,7 @@ pub fn attach_file(bk: &Backend, baseu: Url, mut msg: Message) -> Result<(), Err
             }
         }
 
-        match upload_file(&tk, &baseu, &fname) {
+        match upload_file(&baseu, &tk, &fname) {
             Err(err) => {
                 tx.send(BKResponse::AttachedFile(Err(err)))
                     .expect_log("Connection closed");
@@ -648,7 +719,7 @@ pub fn attach_file(bk: &Backend, baseu: Url, mut msg: Message) -> Result<(), Err
             Ok(uri) => {
                 msg.url = Some(uri.to_string());
                 if let Some(t) = itx {
-                    t.send(BKCommand::SendMsg(baseu, msg.clone()))
+                    t.send(BKCommand::SendMsg(baseu, tk, msg.clone()))
                         .expect_log("Connection closed");
                 }
                 tx.send(BKResponse::AttachedFile(Ok(msg)))
@@ -660,7 +731,7 @@ pub fn attach_file(bk: &Backend, baseu: Url, mut msg: Message) -> Result<(), Err
     Ok(())
 }
 
-fn upload_file(tk: &AccessToken, baseu: &Url, fname: &str) -> Result<String, Error> {
+fn upload_file(baseu: &Url, tk: &AccessToken, fname: &str) -> Result<String, Error> {
     let mut file = File::open(fname)?;
     let mut contents: Vec<u8> = vec![];
     file.read_to_end(&mut contents)?;
@@ -677,11 +748,11 @@ fn upload_file(tk: &AccessToken, baseu: &Url, fname: &str) -> Result<String, Err
 pub fn new_room(
     bk: &Backend,
     base: Url,
-    name: &str,
+    access_token: AccessToken,
+    name: String,
     privacy: RoomType,
     internal_id: String,
 ) -> Result<(), Error> {
-    let access_token = bk.get_access_token();
     let url = bk.url(base, &access_token, "createRoom", vec![])?;
     let attrs = json!({
         "invite": [],
@@ -698,7 +769,6 @@ pub fn new_room(
         },
     });
 
-    let n = String::from(name);
     let tx = bk.tx.clone();
     post!(
         &url,
@@ -706,7 +776,7 @@ pub fn new_room(
         move |r: JsonValue| {
             let id = String::from(r["room_id"].as_str().unwrap_or_default());
             let mut r = Room::new(id, RoomMembership::Joined(RoomTag::None));
-            r.name = Some(n);
+            r.name = Some(name);
             tx.send(BKResponse::NewRoom(Ok(r), internal_id))
                 .expect_log("Connection closed");
         },
@@ -756,10 +826,10 @@ pub fn update_direct_chats(url: Url, data: Arc<Mutex<BackendData>>, user: String
 pub fn direct_chat(
     bk: &Backend,
     base: Url,
-    user: &Member,
+    access_token: AccessToken,
+    user: Member,
     internal_id: String,
 ) -> Result<(), Error> {
-    let access_token = bk.get_access_token();
     let url = bk.url(base.clone(), &access_token, "createRoom", vec![])?;
     let attrs = json!({
         "invite": [user.uid.clone()],
@@ -783,7 +853,6 @@ pub fn direct_chat(
         vec![],
     )?;
 
-    let m = user.clone();
     let tx = bk.tx.clone();
     let data = bk.data.clone();
     post!(
@@ -792,12 +861,12 @@ pub fn direct_chat(
         move |r: JsonValue| {
             let id = String::from(r["room_id"].as_str().unwrap_or_default());
             let mut r = Room::new(id.clone(), RoomMembership::Joined(RoomTag::None));
-            r.name = m.alias.clone();
+            r.name = user.alias.clone();
             r.direct = true;
             tx.send(BKResponse::NewRoom(Ok(r), internal_id))
                 .expect_log("Connection closed");
 
-            update_direct_chats(direct_url, data, m.uid.clone(), id);
+            update_direct_chats(direct_url, data, user.uid.clone(), id);
         },
         |err| {
             tx.send(BKResponse::NewRoom(Err(err), internal_id))
@@ -808,8 +877,13 @@ pub fn direct_chat(
     Ok(())
 }
 
-pub fn add_to_fav(bk: &Backend, base: Url, roomid: String, tofav: bool) -> Result<(), Error> {
-    let access_token = bk.get_access_token();
+pub fn add_to_fav(
+    bk: &Backend,
+    base: Url,
+    access_token: AccessToken,
+    roomid: String,
+    tofav: bool,
+) -> Result<(), Error> {
     let userid = bk.data.lock().unwrap().user_id.clone();
     let url = bk.url(
         base,
@@ -841,8 +915,13 @@ pub fn add_to_fav(bk: &Backend, base: Url, roomid: String, tofav: bool) -> Resul
     Ok(())
 }
 
-pub fn invite(bk: &Backend, base: Url, roomid: &str, userid: &str) -> Result<(), Error> {
-    let access_token = bk.get_access_token();
+pub fn invite(
+    bk: &Backend,
+    base: Url,
+    access_token: AccessToken,
+    roomid: String,
+    userid: String,
+) -> Result<(), Error> {
     let url = bk.url(
         base,
         &access_token,
diff --git a/fractal-matrix-api/src/backend/stickers.rs b/fractal-matrix-api/src/backend/stickers.rs
index bcc65444..86424db6 100644
--- a/fractal-matrix-api/src/backend/stickers.rs
+++ b/fractal-matrix-api/src/backend/stickers.rs
@@ -14,15 +14,20 @@ use crate::error::Error;
 use crate::backend::types::BKCommand;
 use crate::backend::types::BKResponse;
 use crate::backend::types::Backend;
+use crate::r0::AccessToken;
 use crate::types::Sticker;
 use crate::types::StickerGroup;
 use serde_json::Value as JsonValue;
 
 /// Queries scalar.vector.im to list all the stickers
-pub fn list(bk: &Backend) -> Result<(), Error> {
+pub fn list(bk: &Backend, access_token: AccessToken) -> Result<(), Error> {
     let widget = bk.data.lock().unwrap().sticker_widget.clone();
     if widget.is_none() {
-        get_sticker_widget_id(bk, BKCommand::ListStickers)?;
+        get_sticker_widget_id(
+            bk,
+            access_token.clone(),
+            BKCommand::ListStickers(access_token),
+        )?;
         return Ok(());
     }
 
@@ -32,7 +37,7 @@ pub fn list(bk: &Backend) -> Result<(), Error> {
         ("widget_id", widget_id),
         ("filter_unpurchased", "true".to_string()),
     ];
-    let url = vurl(&bk.data, "widgets/assets", data)?;
+    let url = vurl(&bk.data, &access_token, "widgets/assets", data)?;
 
     let tx = bk.tx.clone();
     get!(
@@ -55,7 +60,11 @@ pub fn list(bk: &Backend) -> Result<(), Error> {
     Ok(())
 }
 
-pub fn get_sticker_widget_id(bk: &Backend, then: BKCommand) -> Result<(), Error> {
+pub fn get_sticker_widget_id(
+    bk: &Backend,
+    access_token: AccessToken,
+    then: BKCommand,
+) -> Result<(), Error> {
     let data = json!({
         "data": {},
         "type": "m.stickerpicker",
@@ -63,7 +72,7 @@ pub fn get_sticker_widget_id(bk: &Backend, then: BKCommand) -> Result<(), Error>
     let d = bk.data.clone();
     let itx = bk.internal_tx.clone();
 
-    let url = vurl(&d, "widgets/request", vec![]).unwrap();
+    let url = vurl(&d, &access_token, "widgets/request", vec![]).unwrap();
     post!(
         &url,
         &data,
@@ -103,8 +112,13 @@ pub fn get_sticker_widget_id(bk: &Backend, then: BKCommand) -> Result<(), Error>
     Ok(())
 }
 
-pub fn send(bk: &Backend, base: Url, roomid: &str, sticker: &Sticker) -> Result<(), Error> {
-    let access_token = bk.get_access_token();
+pub fn send(
+    bk: &Backend,
+    base: Url,
+    access_token: AccessToken,
+    roomid: String,
+    sticker: Sticker,
+) -> Result<(), Error> {
     let now = Local::now();
     let msg = format!("{}{}{}", roomid, sticker.name, now.to_string());
     let digest = md5::compute(msg.as_bytes());
@@ -147,10 +161,14 @@ pub fn send(bk: &Backend, base: Url, roomid: &str, sticker: &Sticker) -> Result<
     Ok(())
 }
 
-pub fn purchase(bk: &Backend, group: &StickerGroup) -> Result<(), Error> {
+pub fn purchase(bk: &Backend, access_token: AccessToken, group: StickerGroup) -> Result<(), Error> {
     let widget = bk.data.lock().unwrap().sticker_widget.clone();
     if widget.is_none() {
-        get_sticker_widget_id(bk, BKCommand::PurchaseSticker(group.clone()))?;
+        get_sticker_widget_id(
+            bk,
+            access_token.clone(),
+            BKCommand::PurchaseSticker(access_token, group.clone()),
+        )?;
         return Ok(());
     }
 
@@ -161,13 +179,13 @@ pub fn purchase(bk: &Backend, group: &StickerGroup) -> Result<(), Error> {
         ("widget_id", widget_id.clone()),
         ("widget_type", "m.stickerpicker".to_string()),
     ];
-    let url = vurl(&bk.data, "widgets/purchase_asset", data)?;
+    let url = vurl(&bk.data, &access_token, "widgets/purchase_asset", data)?;
     let tx = bk.tx.clone();
     let itx = bk.internal_tx.clone();
     get!(
         &url,
         |_| if let Some(t) = itx {
-            t.send(BKCommand::ListStickers)
+            t.send(BKCommand::ListStickers(access_token))
                 .expect_log("Connection closed");
         },
         |err| {
@@ -179,12 +197,14 @@ pub fn purchase(bk: &Backend, group: &StickerGroup) -> Result<(), Error> {
     Ok(())
 }
 
-fn get_scalar_token(data: &Arc<Mutex<BackendData>>) -> Result<String, Error> {
+fn get_scalar_token(
+    data: &Arc<Mutex<BackendData>>,
+    access_token: &AccessToken,
+) -> Result<String, Error> {
     let base = data.lock().unwrap().scalar_url.clone();
     let uid = data.lock().unwrap().user_id.clone();
-    let tk = data.lock().unwrap().access_token.clone();
 
-    let params = &[("access_token", tk)];
+    let params = &[("access_token", access_token.to_string())];
     let path = &format!("user/{}/openid/request_token", uid);
     let url = client_url(&base, path, params)?;
     let js = json_q("post", &url, &json!({}))?;
@@ -205,15 +225,17 @@ fn get_scalar_token(data: &Arc<Mutex<BackendData>>) -> Result<String, Error> {
 
 fn vurl(
     data: &Arc<Mutex<BackendData>>,
+    access_token: &AccessToken,
     path: &str,
     mut params: Vec<(&str, String)>,
 ) -> Result<Url, Error> {
     let base = data.lock().unwrap().scalar_url.clone();
-    let token = data.lock().unwrap().scalar_token.clone();
-    let tk = match token {
-        None => get_scalar_token(data)?,
-        Some(t) => t.clone(),
-    };
+    let tk = data
+        .lock()
+        .unwrap()
+        .scalar_token
+        .clone()
+        .unwrap_or(get_scalar_token(data, access_token)?);
 
     params.push(("scalar_token", tk));
 
diff --git a/fractal-matrix-api/src/backend/sync.rs b/fractal-matrix-api/src/backend/sync.rs
index 169f089e..e50163b3 100644
--- a/fractal-matrix-api/src/backend/sync.rs
+++ b/fractal-matrix-api/src/backend/sync.rs
@@ -11,6 +11,7 @@ use crate::r0::sync::sync_events::IncludeState;
 use crate::r0::sync::sync_events::Parameters as SyncParameters;
 use crate::r0::sync::sync_events::Response as SyncResponse;
 use crate::r0::sync::sync_events::UnreadNotificationsCount;
+use crate::r0::AccessToken;
 use crate::types::Event;
 use crate::types::Member;
 use crate::types::Message;
@@ -29,11 +30,16 @@ use std::{
 };
 use url::Url;
 
-pub fn sync(bk: &Backend, base: Url, new_since: Option<String>, initial: bool) {
+pub fn sync(
+    bk: &Backend,
+    base: Url,
+    access_token: AccessToken,
+    new_since: Option<String>,
+    initial: bool,
+) {
     let tx = bk.tx.clone();
     let data = bk.data.clone();
     let userid = bk.data.lock().unwrap().user_id.clone();
-    let access_token = bk.get_access_token();
 
     let since = bk
         .data
@@ -255,7 +261,7 @@ pub fn sync(bk: &Backend, base: Url, new_since: Option<String>, initial: bool) {
     });
 }
 
-pub fn force_sync(bk: &Backend, base: Url) {
+pub fn force_sync(bk: &Backend, base: Url, access_token: AccessToken) {
     bk.data.lock().unwrap().since = None;
-    sync(bk, base, None, true)
+    sync(bk, base, access_token, None, true)
 }
diff --git a/fractal-matrix-api/src/backend/types.rs b/fractal-matrix-api/src/backend/types.rs
index bc63d0bd..ae1392f5 100644
--- a/fractal-matrix-api/src/backend/types.rs
+++ b/fractal-matrix-api/src/backend/types.rs
@@ -6,6 +6,7 @@ use crate::error::Error;
 
 use crate::r0::contact::get_identifiers::ThirdPartyIdentifier;
 use crate::r0::thirdparty::get_supported_protocols::ProtocolInstance;
+use crate::r0::AccessToken;
 use crate::r0::Medium;
 use crate::types::Event;
 use crate::types::Member;
@@ -20,35 +21,36 @@ use url::Url;
 #[derive(Debug)]
 pub enum BKCommand {
     Login(String, String, String),
-    SetToken(String, String),
-    Logout(Url),
+    SetToken(AccessToken, String),
+    Logout(Url, AccessToken),
     #[allow(dead_code)]
     Register(String, String, String),
     #[allow(dead_code)]
     Guest(String),
     GetUsername(Url),
-    SetUserName(Url, String),
-    GetThreePID(Url),
-    GetTokenEmail(Url, String, String, String),
-    GetTokenPhone(Url, String, String, String),
+    SetUserName(Url, AccessToken, String),
+    GetThreePID(Url, AccessToken),
+    GetTokenEmail(Url, AccessToken, String, String, String),
+    GetTokenPhone(Url, AccessToken, String, String, String),
     SubmitPhoneToken(Url, String, String, String),
-    AddThreePID(Url, String, String, String),
-    DeleteThreePID(Url, Medium, String),
-    ChangePassword(Url, String, String, String),
-    AccountDestruction(Url, String, String),
+    AddThreePID(Url, AccessToken, String, String, String),
+    DeleteThreePID(Url, AccessToken, Medium, String),
+    ChangePassword(Url, AccessToken, String, String, String),
+    AccountDestruction(Url, AccessToken, String, String),
     GetAvatar(Url),
-    SetUserAvatar(Url, String),
-    Sync(Url, Option<String>, bool),
-    SyncForced(Url),
-    GetRoomMembers(Url, String),
-    GetRoomMessages(Url, String, String),
-    GetRoomMessagesFromMsg(Url, String, Message),
-    GetMessageContext(Url, Message),
-    GetRoomAvatar(Url, String),
+    SetUserAvatar(Url, AccessToken, String),
+    Sync(Url, AccessToken, Option<String>, bool),
+    SyncForced(Url, AccessToken),
+    GetRoomMembers(Url, AccessToken, String),
+    GetRoomMessages(Url, AccessToken, String, String),
+    GetRoomMessagesFromMsg(Url, AccessToken, String, Message),
+    GetMessageContext(Url, AccessToken, Message),
+    GetRoomAvatar(Url, AccessToken, String),
     GetThumbAsync(Url, String, Sender<String>),
     GetMediaAsync(Url, String, Sender<String>),
     GetMediaListAsync(
         Url,
+        AccessToken,
         String,
         Option<String>,
         Option<String>,
@@ -60,36 +62,36 @@ pub enum BKCommand {
     GetMediaUrl(Url, String, Sender<String>),
     GetUserInfoAsync(Url, String, Option<Sender<(String, String)>>),
     GetUserNameAsync(Url, String, Sender<String>),
-    SendMsg(Url, Message),
-    SendMsgRedaction(Url, Message),
-    SendTyping(Url, String),
-    SetRoom(Url, String),
+    SendMsg(Url, AccessToken, Message),
+    SendMsgRedaction(Url, AccessToken, Message),
+    SendTyping(Url, AccessToken, String),
+    SetRoom(Url, AccessToken, String),
     ShutDown,
-    DirectoryProtocols(Url),
-    DirectorySearch(Url, String, String, String, bool),
-    JoinRoom(Url, String),
-    MarkAsRead(Url, String, String),
-    LeaveRoom(Url, String),
-    SetRoomName(Url, String, String),
-    SetRoomTopic(Url, String, String),
-    SetRoomAvatar(Url, String, String),
-    AttachFile(Url, Message),
-    NewRoom(Url, String, RoomType, String),
-    DirectChat(Url, Member, String),
-    AddToFav(Url, String, bool),
-    AcceptInv(Url, String),
-    RejectInv(Url, String),
-    UserSearch(Url, String),
-    Invite(Url, String, String),
-    ListStickers,
-    SendSticker(Url, String, Sticker),
-    PurchaseSticker(StickerGroup),
+    DirectoryProtocols(Url, AccessToken),
+    DirectorySearch(Url, AccessToken, String, String, String, bool),
+    JoinRoom(Url, AccessToken, String),
+    MarkAsRead(Url, AccessToken, String, String),
+    LeaveRoom(Url, AccessToken, String),
+    SetRoomName(Url, AccessToken, String, String),
+    SetRoomTopic(Url, AccessToken, String, String),
+    SetRoomAvatar(Url, AccessToken, String, String),
+    AttachFile(Url, AccessToken, Message),
+    NewRoom(Url, AccessToken, String, RoomType, String),
+    DirectChat(Url, AccessToken, Member, String),
+    AddToFav(Url, AccessToken, String, bool),
+    AcceptInv(Url, AccessToken, String),
+    RejectInv(Url, AccessToken, String),
+    UserSearch(Url, AccessToken, String),
+    Invite(Url, AccessToken, String, String),
+    ListStickers(AccessToken),
+    SendSticker(Url, AccessToken, String, Sticker),
+    PurchaseSticker(AccessToken, StickerGroup),
 }
 
 #[derive(Debug)]
 pub enum BKResponse {
     ShutDown,
-    Token(String, String, Option<String>),
+    Token(String, Option<AccessToken>, Option<String>),
     Logout(Result<(), Error>),
     Name(Result<String, Error>),
     SetUserName(Result<String, Error>),
@@ -152,7 +154,6 @@ pub enum RoomType {
 
 pub struct BackendData {
     pub user_id: String,
-    pub access_token: String,
     pub scalar_token: Option<String>,
     pub scalar_url: Url,
     pub sticker_widget: Option<String>,
diff --git a/fractal-matrix-api/src/backend/user.rs b/fractal-matrix-api/src/backend/user.rs
index a54b26a6..79171909 100644
--- a/fractal-matrix-api/src/backend/user.rs
+++ b/fractal-matrix-api/src/backend/user.rs
@@ -39,6 +39,7 @@ use crate::r0::contact::delete::Parameters as DeleteThreePIDParameters;
 use crate::r0::contact::get_identifiers::request as get_identifiers;
 use crate::r0::contact::get_identifiers::Parameters as ThirdPartyIDParameters;
 use crate::r0::contact::get_identifiers::Response as ThirdPartyIDResponse;
+use crate::r0::contact::get_identifiers::ThirdPartyIdentifier;
 use crate::r0::contact::request_verification_token_email::request as 
request_contact_verification_token_email;
 use crate::r0::contact::request_verification_token_email::Body as EmailTokenBody;
 use crate::r0::contact::request_verification_token_email::Parameters as EmailTokenParameters;
@@ -62,6 +63,7 @@ use crate::r0::search::user::request as user_directory;
 use crate::r0::search::user::Body as UserDirectoryBody;
 use crate::r0::search::user::Parameters as UserDirectoryParameters;
 use crate::r0::search::user::Response as UserDirectoryResponse;
+use crate::r0::AccessToken;
 use crate::r0::Medium;
 use crate::r0::ThreePIDCredentials;
 use crate::types::Member;
@@ -89,29 +91,24 @@ pub fn get_username(bk: &Backend, base: Url) {
 
 // FIXME: This function manages errors *really* wrong and isn't more async
 // than the normal function. It should be removed.
-pub fn get_username_async(base: Url, uid: String, tx: Sender<String>) {
-    thread::spawn(move || {
-        let query = get_display_name(base, &encode_uid(&uid))
-            .map_err::<Error, _>(Into::into)
-            .and_then(|request| {
-                HTTP_CLIENT
-                    .get_client()?
-                    .execute(request)?
-                    .json::<GetDisplayNameResponse>()
-                    .map_err(Into::into)
-            })
-            .ok()
-            .and_then(|response| response.displayname)
-            .unwrap_or(uid);
-
-        tx.send(query).expect_log("Connection closed");
-    });
+pub fn get_username_async(base: Url, uid: String) -> String {
+    get_display_name(base, &encode_uid(&uid))
+        .map_err::<Error, _>(Into::into)
+        .and_then(|request| {
+            HTTP_CLIENT
+                .get_client()?
+                .execute(request)?
+                .json::<GetDisplayNameResponse>()
+                .map_err(Into::into)
+        })
+        .ok()
+        .and_then(|response| response.displayname)
+        .unwrap_or(uid)
 }
 
-pub fn set_username(bk: &Backend, base: Url, name: String) {
+pub fn set_username(bk: &Backend, base: Url, access_token: AccessToken, name: String) {
     let tx = bk.tx.clone();
 
-    let access_token = bk.get_access_token();
     let uid = bk.data.lock().unwrap().user_id.clone();
     let params = SetDisplayNameParameters { access_token };
     let body = SetDisplayNameBody {
@@ -134,39 +131,31 @@ pub fn set_username(bk: &Backend, base: Url, name: String) {
     });
 }
 
-pub fn get_threepid(bk: &Backend, base: Url) {
-    let tx = bk.tx.clone();
-
-    let access_token = bk.get_access_token();
+pub fn get_threepid(
+    base: Url,
+    access_token: AccessToken,
+) -> Result<Vec<ThirdPartyIdentifier>, Error> {
     let params = ThirdPartyIDParameters { access_token };
 
-    thread::spawn(move || {
-        let query = get_identifiers(base, &params)
-            .map_err(Into::into)
-            .and_then(|request| {
-                HTTP_CLIENT
-                    .get_client()?
-                    .execute(request)?
-                    .json::<ThirdPartyIDResponse>()
-                    .map_err(Into::into)
-            })
-            .map(|response| response.threepids);
-
-        tx.send(BKResponse::GetThreePID(query))
-            .expect_log("Connection closed");
-    });
+    get_identifiers(base, &params)
+        .map_err(Into::into)
+        .and_then(|request| {
+            HTTP_CLIENT
+                .get_client()?
+                .execute(request)?
+                .json::<ThirdPartyIDResponse>()
+                .map_err(Into::into)
+        })
+        .map(|response| response.threepids)
 }
 
 pub fn get_email_token(
-    bk: &Backend,
     base: Url,
+    access_token: AccessToken,
     identity: String,
     email: String,
     client_secret: String,
-) -> Result<(), Error> {
-    let tx = bk.tx.clone();
-
-    let access_token = bk.get_access_token();
+) -> Result<(String, String), Error> {
     let params = EmailTokenParameters { access_token };
     let body = EmailTokenBody {
         id_server: Url::parse(&identity)?.try_into()?,
@@ -176,45 +165,35 @@ pub fn get_email_token(
         next_link: None,
     };
 
-    thread::spawn(move || {
-        let query = request_contact_verification_token_email(base, &params, &body)
-            .map_err(Into::into)
-            .and_then(|request| {
-                HTTP_CLIENT
-                    .get_client()?
-                    .execute(request)?
-                    .json::<EmailTokenResponse>()
-                    .map_err(Into::into)
-            })
-            .and_then(|response| match response {
-                EmailTokenResponse::Passed(info) => Ok(info.sid),
-                EmailTokenResponse::Failed(info) => {
-                    if info.errcode == "M_THREEPID_IN_USE" {
-                        Err(Error::TokenUsed)
-                    } else {
-                        Err(Error::Denied)
-                    }
+    request_contact_verification_token_email(base, &params, &body)
+        .map_err(Into::into)
+        .and_then(|request| {
+            HTTP_CLIENT
+                .get_client()?
+                .execute(request)?
+                .json::<EmailTokenResponse>()
+                .map_err(Into::into)
+        })
+        .and_then(|response| match response {
+            EmailTokenResponse::Passed(info) => Ok(info.sid),
+            EmailTokenResponse::Failed(info) => {
+                if info.errcode == "M_THREEPID_IN_USE" {
+                    Err(Error::TokenUsed)
+                } else {
+                    Err(Error::Denied)
                 }
-            })
-            .map(|response| (response, client_secret));
-
-        tx.send(BKResponse::GetTokenEmail(query))
-            .expect_log("Connection closed");
-    });
-
-    Ok(())
+            }
+        })
+        .map(|response| (response, client_secret))
 }
 
 pub fn get_phone_token(
-    bk: &Backend,
     base: Url,
+    access_token: AccessToken,
     identity: String,
     phone: String,
     client_secret: String,
-) -> Result<(), Error> {
-    let tx = bk.tx.clone();
-
-    let access_token = bk.get_access_token();
+) -> Result<(String, String), Error> {
     let params = PhoneTokenParameters { access_token };
     let body = PhoneTokenBody {
         id_server: Url::parse(&identity)?.try_into()?,
@@ -225,45 +204,35 @@ pub fn get_phone_token(
         next_link: None,
     };
 
-    thread::spawn(move || {
-        let query = request_contact_verification_token_msisdn(base, &params, &body)
-            .map_err(Into::into)
-            .and_then(|request| {
-                HTTP_CLIENT
-                    .get_client()?
-                    .execute(request)?
-                    .json::<PhoneTokenResponse>()
-                    .map_err(Into::into)
-            })
-            .and_then(|response| match response {
-                PhoneTokenResponse::Passed(info) => Ok(info.sid),
-                PhoneTokenResponse::Failed(info) => {
-                    if info.errcode == "M_THREEPID_IN_USE" {
-                        Err(Error::TokenUsed)
-                    } else {
-                        Err(Error::Denied)
-                    }
+    request_contact_verification_token_msisdn(base, &params, &body)
+        .map_err(Into::into)
+        .and_then(|request| {
+            HTTP_CLIENT
+                .get_client()?
+                .execute(request)?
+                .json::<PhoneTokenResponse>()
+                .map_err(Into::into)
+        })
+        .and_then(|response| match response {
+            PhoneTokenResponse::Passed(info) => Ok(info.sid),
+            PhoneTokenResponse::Failed(info) => {
+                if info.errcode == "M_THREEPID_IN_USE" {
+                    Err(Error::TokenUsed)
+                } else {
+                    Err(Error::Denied)
                 }
-            })
-            .map(|response| (response, client_secret));
-
-        tx.send(BKResponse::GetTokenPhone(query))
-            .expect_log("Connection closed");
-    });
-
-    Ok(())
+            }
+        })
+        .map(|response| (response, client_secret))
 }
 
 pub fn add_threepid(
-    bk: &Backend,
     base: Url,
+    access_token: AccessToken,
     identity: String,
     client_secret: String,
     sid: String,
 ) -> Result<(), Error> {
-    let tx = bk.tx.clone();
-
-    let access_token = bk.get_access_token();
     let params = AddThreePIDParameters { access_token };
     let body = AddThreePIDBody {
         three_pid_creds: ThreePIDCredentials {
@@ -274,89 +243,68 @@ pub fn add_threepid(
         bind: true,
     };
 
-    thread::spawn(move || {
-        let query = create_contact(base, &params, &body)
-            .map_err(Into::into)
-            .and_then(|request| {
-                HTTP_CLIENT
-                    .get_client()?
-                    .execute(request)
-                    .map_err(Into::into)
-            })
-            .and(Ok(()));
-
-        tx.send(BKResponse::AddThreePID(query))
-            .expect_log("Connection closed");
-    });
-
-    Ok(())
+    create_contact(base, &params, &body)
+        .map_err(Into::into)
+        .and_then(|request| {
+            HTTP_CLIENT
+                .get_client()?
+                .execute(request)
+                .map_err(Into::into)
+        })
+        .and(Ok(()))
 }
 
 pub fn submit_phone_token(
-    bk: &Backend,
     base: Url,
     client_secret: String,
     sid: String,
     token: String,
-) {
-    let tx = bk.tx.clone();
-
+) -> Result<(Option<String>, String), Error> {
     let body = SubmitPhoneTokenBody {
         sid: sid.clone(),
         client_secret: client_secret.clone(),
         token,
     };
 
-    thread::spawn(move || {
-        let query = submit_phone_token_req(base, &body)
-            .map_err(Into::into)
-            .and_then(|request| {
-                HTTP_CLIENT
-                    .get_client()?
-                    .execute(request)?
-                    .json::<SubmitPhoneTokenResponse>()
-                    .map_err(Into::into)
-            })
-            .map(|response| (Some(sid).filter(|_| response.success), client_secret));
-
-        tx.send(BKResponse::SubmitPhoneToken(query))
-            .expect_log("Connection closed");
-    });
+    submit_phone_token_req(base, &body)
+        .map_err(Into::into)
+        .and_then(|request| {
+            HTTP_CLIENT
+                .get_client()?
+                .execute(request)?
+                .json::<SubmitPhoneTokenResponse>()
+                .map_err(Into::into)
+        })
+        .map(|response| (Some(sid).filter(|_| response.success), client_secret))
 }
 
-pub fn delete_three_pid(bk: &Backend, base: Url, medium: Medium, address: String) {
-    let tx = bk.tx.clone();
-
-    let access_token = bk.get_access_token();
+pub fn delete_three_pid(
+    base: Url,
+    access_token: AccessToken,
+    medium: Medium,
+    address: String,
+) -> Result<(), Error> {
     let params = DeleteThreePIDParameters { access_token };
     let body = DeleteThreePIDBody { address, medium };
 
-    thread::spawn(move || {
-        let query = delete_contact(base, &params, &body)
-            .map_err(Into::into)
-            .and_then(|request| {
-                HTTP_CLIENT
-                    .get_client()?
-                    .execute(request)
-                    .map_err(Into::into)
-            })
-            .and(Ok(()));
-
-        tx.send(BKResponse::DeleteThreePID(query))
-            .expect_log("Connection closed");
-    });
+    delete_contact(base, &params, &body)
+        .map_err(Into::into)
+        .and_then(|request| {
+            HTTP_CLIENT
+                .get_client()?
+                .execute(request)
+                .map_err(Into::into)
+        })
+        .and(Ok(()))
 }
 
 pub fn change_password(
-    bk: &Backend,
     base: Url,
+    access_token: AccessToken,
     user: String,
     old_password: String,
     new_password: String,
-) {
-    let tx = bk.tx.clone();
-
-    let access_token = bk.get_access_token();
+) -> Result<(), Error> {
     let params = ChangePasswordParameters { access_token };
     let body = ChangePasswordBody {
         new_password,
@@ -367,26 +315,23 @@ pub fn change_password(
         }),
     };
 
-    thread::spawn(move || {
-        let query = change_password_req(base, &params, &body)
-            .map_err(Into::into)
-            .and_then(|request| {
-                HTTP_CLIENT
-                    .get_client()?
-                    .execute(request)
-                    .map_err(Into::into)
-            })
-            .and(Ok(()));
-
-        tx.send(BKResponse::ChangePassword(query))
-            .expect_log("Connection closed");
-    });
+    change_password_req(base, &params, &body)
+        .map_err(Into::into)
+        .and_then(|request| {
+            HTTP_CLIENT
+                .get_client()?
+                .execute(request)
+                .map_err(Into::into)
+        })
+        .and(Ok(()))
 }
 
-pub fn account_destruction(bk: &Backend, base: Url, user: String, password: String) {
-    let tx = bk.tx.clone();
-
-    let access_token = bk.get_access_token();
+pub fn account_destruction(
+    base: Url,
+    access_token: AccessToken,
+    user: String,
+    password: String,
+) -> Result<(), Error> {
     let params = DeactivateParameters { access_token };
     let body = DeactivateBody {
         auth: Some(AuthenticationData::Password {
@@ -396,20 +341,15 @@ pub fn account_destruction(bk: &Backend, base: Url, user: String, password: Stri
         }),
     };
 
-    thread::spawn(move || {
-        let query = deactivate(base, &params, &body)
-            .map_err(Into::into)
-            .and_then(|request| {
-                HTTP_CLIENT
-                    .get_client()?
-                    .execute(request)
-                    .map_err(Into::into)
-            })
-            .and(Ok(()));
-
-        tx.send(BKResponse::AccountDestruction(query))
-            .expect_log("Connection closed");
-    });
+    deactivate(base, &params, &body)
+        .map_err(Into::into)
+        .and_then(|request| {
+            HTTP_CLIENT
+                .get_client()?
+                .execute(request)
+                .map_err(Into::into)
+        })
+        .and(Ok(()))
 }
 
 pub fn get_avatar(bk: &Backend, base: Url) {
@@ -437,11 +377,10 @@ pub fn get_avatar_async(bk: &Backend, base: Url, member: Option<Member>, tx: Sen
     }
 }
 
-pub fn set_user_avatar(bk: &Backend, base: Url, avatar: String) {
+pub fn set_user_avatar(bk: &Backend, base: Url, access_token: AccessToken, avatar: String) {
     let tx = bk.tx.clone();
 
     let id = bk.data.lock().unwrap().user_id.clone();
-    let access_token = bk.get_access_token();
     let params_upload = CreateContentParameters {
         access_token: access_token.clone(),
         filename: None,
@@ -519,31 +458,27 @@ pub fn get_user_info_async(
     });
 }
 
-pub fn search(bk: &Backend, base: Url, search_term: String) {
-    let tx = bk.tx.clone();
-
-    let access_token = bk.get_access_token();
+pub fn search(
+    base: Url,
+    access_token: AccessToken,
+    search_term: String,
+) -> Result<Vec<Member>, Error> {
     let params = UserDirectoryParameters { access_token };
     let body = UserDirectoryBody {
         search_term,
         ..Default::default()
     };
 
-    thread::spawn(move || {
-        let query = user_directory(base, &params, &body)
-            .map_err(Into::into)
-            .and_then(|request| {
-                HTTP_CLIENT
-                    .get_client()?
-                    .execute(request)?
-                    .json::<UserDirectoryResponse>()
-                    .map_err(Into::into)
-            })
-            .map(|response| response.results.into_iter().map(Into::into).collect());
-
-        tx.send(BKResponse::UserSearch(query))
-            .expect_log("Connection closed");
-    });
+    user_directory(base, &params, &body)
+        .map_err(Into::into)
+        .and_then(|request| {
+            HTTP_CLIENT
+                .get_client()?
+                .execute(request)?
+                .json::<UserDirectoryResponse>()
+                .map_err(Into::into)
+        })
+        .map(|response| response.results.into_iter().map(Into::into).collect())
 }
 
 fn get_user_avatar_img(baseu: &Url, userid: &str, avatar: &str) -> Result<String, Error> {
diff --git a/fractal-matrix-api/src/error.rs b/fractal-matrix-api/src/error.rs
index 7c83938a..13f82f65 100644
--- a/fractal-matrix-api/src/error.rs
+++ b/fractal-matrix-api/src/error.rs
@@ -14,6 +14,7 @@ pub enum Error {
     SendMsgRedactionError(String),
     TokenUsed,
     Denied,
+    NotLoggedIn,
 }
 
 impl From<reqwest::Error> for Error {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]