diff --git a/server/core/auth.js b/server/core/auth.js
index 87d9fcceb4dfbd4bce01eb02848fc66b1d6c5a08..ca2dd513cf82c9277bd663e86c70d825bbea7861 100644
--- a/server/core/auth.js
+++ b/server/core/auth.js
@@ -19,6 +19,7 @@ module.exports = {
   },
   groups: {},
   validApiKeys: [],
+  revokationList: require('./cache').init(),
 
   /**
    * Initialize the authentication module
@@ -111,10 +112,28 @@ module.exports = {
   authenticate(req, res, next) {
     WIKI.auth.passport.authenticate('jwt', {session: false}, async (err, user, info) => {
       if (err) { return next() }
+      let mustRevalidate = false
 
       // Expired but still valid within N days, just renew
-      if (info instanceof Error && info.name === 'TokenExpiredError' &&
-        moment().subtract(ms(WIKI.config.auth.tokenRenewal), 'ms').isBefore(info.expiredAt)) {
+      if (info instanceof Error && info.name === 'TokenExpiredError' && moment().subtract(ms(WIKI.config.auth.tokenRenewal), 'ms').isBefore(info.expiredAt)) {
+        mustRevalidate = true
+      }
+
+      // Check if user / group is in revokation list
+      if (user) {
+        if (WIKI.auth.revokationList.has(`u${_.toString(user.id)}`)) {
+          mustRevalidate = true
+        }
+        for (const gid of user.groups) {
+          if (WIKI.auth.revokationList.has(`g${_.toString(gid)}`)) {
+            mustRevalidate = true
+          }
+        }
+      }
+
+      // Revalidate and renew token
+      if (mustRevalidate) {
+        console.info('MUST REVALIDATE')
         const jwtPayload = jwt.decode(securityHelper.extractJWT(req))
         try {
           const newToken = await WIKI.models.users.refreshToken(jwtPayload.id)
@@ -380,6 +399,9 @@ module.exports = {
     WIKI.events.inbound.on('reloadAuthStrategies', () => {
       WIKI.auth.activateStrategies()
     })
+    WIKI.events.inbound.on('addAuthRevoke', (args) => {
+      WIKI.auth.revokeUserTokens(args)
+    })
   },
 
   /**
@@ -410,5 +432,13 @@ module.exports = {
         manage: WIKI.auth.checkAccess(req.user, ['manage:system'], page)
       }
     }
+  },
+
+  /**
+   * Add user / group ID to JWT revokation list, forcing all requests to be validated against the latest permissions
+   */
+  revokeUserTokens ({ id, kind = 'u' }) {
+    console.info(Math.ceil(ms(WIKI.config.auth.tokenRenewal) / 1000))
+    WIKI.auth.revokationList.set(`${kind}${_.toString(id)}`, true, Math.ceil(ms(WIKI.config.auth.tokenRenewal) / 1000))
   }
 }
diff --git a/server/graph/resolvers/group.js b/server/graph/resolvers/group.js
index 401ebb9f7cad55796fbb0d339c08b7e10bae6bf9..3f66089dfd9dbfaf5af0343b243f5a11e55ac733 100644
--- a/server/graph/resolvers/group.js
+++ b/server/graph/resolvers/group.js
@@ -42,6 +42,10 @@ module.exports = {
         throw new gql.GraphQLError('User is already assigned to group.')
       }
       await grp.$relatedQuery('users').relate(usr.id)
+
+      WIKI.auth.revokeUserTokens({ id: usr.id, kind: 'u' })
+      WIKI.events.outbound.emit('addAuthRevoke', { id: usr.id, kind: 'u' })
+
       return {
         responseResult: graphHelper.generateSuccess('User has been assigned to group.')
       }
@@ -62,8 +66,13 @@ module.exports = {
     },
     async delete(obj, args) {
       await WIKI.models.groups.query().deleteById(args.id)
+
+      WIKI.auth.revokeUserTokens({ id: args.id, kind: 'g' })
+      WIKI.events.outbound.emit('addAuthRevoke', { id: args.id, kind: 'g' })
+
       await WIKI.auth.reloadGroups()
       WIKI.events.outbound.emit('reloadGroups')
+
       return {
         responseResult: graphHelper.generateSuccess('Group has been deleted.')
       }
@@ -78,6 +87,10 @@ module.exports = {
         throw new gql.GraphQLError('Invalid User ID')
       }
       await grp.$relatedQuery('users').unrelate().where('userId', usr.id)
+
+      WIKI.auth.revokeUserTokens({ id: usr.id, kind: 'u' })
+      WIKI.events.outbound.emit('addAuthRevoke', { id: usr.id, kind: 'u' })
+
       return {
         responseResult: graphHelper.generateSuccess('User has been unassigned from group.')
       }
@@ -95,6 +108,9 @@ module.exports = {
         pageRules: JSON.stringify(args.pageRules)
       }).where('id', args.id)
 
+      WIKI.auth.revokeUserTokens({ id: args.id, kind: 'g' })
+      WIKI.events.outbound.emit('addAuthRevoke', { id: args.id, kind: 'g' })
+
       await WIKI.auth.reloadGroups()
       WIKI.events.outbound.emit('reloadGroups')
 
diff --git a/server/graph/resolvers/user.js b/server/graph/resolvers/user.js
index 78a245aaaf46568bfedf449d2369f19dd890b28f..56a6202b05f05e57f3b546b5f2fef7d60097830b 100644
--- a/server/graph/resolvers/user.js
+++ b/server/graph/resolvers/user.js
@@ -73,6 +73,10 @@ module.exports = {
           throw new WIKI.Error.UserDeleteProtected()
         }
         await WIKI.models.users.deleteUser(args.id, args.replaceId)
+
+        WIKI.auth.revokeUserTokens({ id: args.id, kind: 'u' })
+        WIKI.events.outbound.emit('addAuthRevoke', { id: args.id, kind: 'u' })
+
         return {
           responseResult: graphHelper.generateSuccess('User deleted successfully')
         }
@@ -124,6 +128,9 @@ module.exports = {
         }
         await WIKI.models.users.query().patch({ isActive: false }).findById(args.id)
 
+        WIKI.auth.revokeUserTokens({ id: args.id, kind: 'u' })
+        WIKI.events.outbound.emit('addAuthRevoke', { id: args.id, kind: 'u' })
+
         return {
           responseResult: graphHelper.generateSuccess('User deactivated successfully')
         }