diff --git a/src/pam.rs b/src/pam.rs
index 9088c60cf37808452fb71c22771e3cf56ef3b4f7..3c7fda3affe3a67c1ee85934640aaa8f1786ec96 100644
--- a/src/pam.rs
+++ b/src/pam.rs
@@ -50,6 +50,8 @@ struct PamOidc;
 impl PamServiceModule for PamOidc {
     fn authenticate(pamh: Pam, _: PamFlag, argv: Vec<String>) -> PamError {
         let conf = pam_sm_prepare(&argv);
+        debug!("[PAM] authenticate called");
+
         if conf.get_str("pam.flow").unwrap() == "password" {
             debug!("Starting Resource Owner Password Credentials OAuth flow");
 
@@ -104,17 +106,15 @@ impl PamServiceModule for PamOidc {
 
                     // 1. ...mark getpwnam unsafe (prevent cache code from calling it)
                     set_is_getpwnam_safe(false);
-                    // 2. ...store the access token in memory
+                    // 2. ...store the access token in memory, so the NSS part can use it
+                    //    on re-entry through getpwnam
                     get_context_user().set_access_token(t.clone(), false, false).ok();
                     // 3. ...call getpwnam ourselves without having the cache object locked
                     let passwd = getpwnam_safe(username.to_string());
                     if passwd.is_ok() {
-                        // 4. ...if getpwnam was successful, store the token again (this time,
-                        //    modulo other errors, it will go through to $HOME)
+                        // 4. ...if getpwnam was successful, store the result for context user;
+                        //    setcred() will pick it up and write to /run and/or $HOME
                         get_context_user().set_passwd(passwd.unwrap());
-                        let persist_run = conf.get_bool("pam.persist_token.run").unwrap();
-                        let persist_home = conf.get_bool("pam.persist_token.home").unwrap();
-                        get_context_user().set_access_token(t.clone(), persist_run, persist_home).ok();
                     }
                     // 5. ...unlock getpwnam again (somewhat unnecessary)
                     set_is_getpwnam_safe(true);
@@ -133,6 +133,7 @@ impl PamServiceModule for PamOidc {
 
     fn acct_mgmt(pamh: Pam, _: PamFlag, argv: Vec<String>) -> PamError {
         let conf = pam_sm_prepare(&argv);
+        debug!("[PAM] acct_mgmt called");
 
         if conf.get_str("pam.urls.authz").unwrap_or_default() == "" {
             info!("Authorization endpoint not set, granting access by default");
@@ -172,6 +173,53 @@ impl PamServiceModule for PamOidc {
             }
         }
     }
+
+    fn setcred(pamh: Pam, flag: PamFlag, argv: Vec<String>) -> PamError {
+        let conf = pam_sm_prepare(&argv);
+        debug!("[PAM] setcred called");
+
+        let persist_run = conf.get_bool("pam.persist_token.run").unwrap();
+        let persist_home = conf.get_bool("pam.persist_token.home").unwrap();
+
+        let token = match get_context_user().get_access_token() {
+            Some(t) => t,
+            None => {
+                error!("Access token not yet known, cannot persist");
+                return PamError::CRED_UNAVAIL;
+            }
+        };
+
+        let res;
+        if matches!(flag, PamFlag::ESTABLISH_CRED) {
+            set_is_getpwnam_safe(false);
+            let token =
+            res = match get_context_user().set_access_token(token.clone(), persist_run, persist_home) {
+                Ok(_) => {
+                    debug!("Successfully set credentials");
+                    PamError::SUCCESS
+                },
+                Err(e) => {
+                    error!("Failed setting credentials: {}", e);
+                    PamError::CRED_ERR
+                }
+            };
+            set_is_getpwnam_safe(true);
+        } else if matches!(flag, PamFlag::DELETE_CRED) {
+            // FIXME Implement in UserInfo class
+            res = PamError::SERVICE_ERR;
+        } else if matches!(flag, PamFlag::REINITIALIZE_CRED) {
+            // FIXME Implement
+            res = PamError::SERVICE_ERR;
+        } else if matches!(flag, PamFlag::REFRESH_CRED) {
+            // FIXME Implement in UserInfo class (probably)
+            res = PamError::SERVICE_ERR;
+        } else {
+            error!("setcred called with unexpected flag");
+            res = PamError::SERVICE_ERR;
+        }
+
+        res
+    }
 }
 
 pam_module!(PamOidc);