diff --git a/src/cache.rs b/src/cache.rs
index cda759b5429409a324a07cad11c0bb7f8218bae1..4f85dbd94b1beaa19c7b81c96ecce8d6e0cf05b8 100644
--- a/src/cache.rs
+++ b/src/cache.rs
@@ -13,20 +13,75 @@
  * limitations under the License.
  */
 
+use lazy_static::lazy_static;
 use std::collections::HashMap;
+use std::convert::From;
+use std::time::SystemTime;
+
+use oauth2::basic::BasicTokenResponse;
+
+const TOKEN_DEFAULT_EXPIRES: u64 = 24 * 60 * 60;
 
 struct UserToken {
     access_token: String,
-    expires_in: u32,
-    refresh_token: String,
-    scope: String,
-    token_type: String,
+    expires_at: u64,
+    refresh_token: Option<String>,
+}
+
+
+impl  UserToken {
+    fn is_expired(&self) -> bool {
+        match SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) {
+            Ok(d) => d.as_secs() >= self.expires_at,
+            Err(_) => true
+        }
+    }
+}
+
+impl From<BasicTokenResponse> for UserToken {
+    fn from(response: BasicTokenResponse) -> Self {
+        UserToken {
+            access_token: response.access_token.secret().to_string(),
+            expires_at: match response.expires_in {
+                Some(duration) => duration,
+                None => TOKEN_DEFAULT_EXPIRES
+            } + SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).ok().unwrap().as_secs(),
+            refresh_token: match response.refresh_token {
+                Some(t) => Some(t.secret().to_string()),
+                None => None
+            }
+        }
+    }
 }
 
-static mut USER_TOKENS: Option<HashMap<String, UserToken>> = None;
+struct Cache {
+    user_tokens: HashMap<String, UserToken>
+}
+
+impl Cache {
+    fn new() -> Cache {
+        Cache {
+            user_tokens: HashMap::new()
+        }
+    }
+
+    fn load_user_token(&self, owner: String) -> Option<&UserToken> {
+        return self.user_tokens.get(&owner);
+    }
 
-fn setup_cache() {
-    unsafe {
-        USER_TOKENS = Some(HashMap::new());
+    fn save_user_token(&self, owner: String, token: UserToken) {
+        self.user_tokens.insert(owner, token);
     }
+
+    fn cleanup_tokens(&self) {
+        for (owner, token) in self.user_tokens {
+            if token.is_expired() {
+                self.user_tokens.remove(&owner);
+            }
+        }
+    }
+}
+
+lazy_static! {
+    static ref CACHE: Cache = Cache::new();
 }