MFA expiration with couchDb

25 views
Skip to first unread message

Anthony Oslund

unread,
Jul 26, 2023, 12:01:59 AM7/26/23
to CAS Community
CAS 6.6.6

Have Simple MFA expiration working in production with couchDb, but had noticed an issue.

No matter how configured, the expiration of the MFA couchDb record is always written at 100 years from record creation date.

Only work around I could find for this was to add a "by_not_processed " view to couchDb that finds newly created MFA cache entries in order modify them with a nightly process to the correct the expiration (to for instance 7 days out).  This does work very nicely in conjunction with multi-device MFA.

Either the timed CAS cleanup, or querying the expired record will cause it to be removed which then triggers the need for the user to re-MFA.

Sharing the following in case others run into this issue, and in the case they also discover the auto-create is not working with couchDb MFA caching.

Added the by_not_processed view, as well as the index (2nd definition)

Combed through every setting I could find from both the documents and the master property lists.  Nothing seemed to affect the expiration.  Perhaps I missed a setting, or there is an undocumented setting, or a problem crept in.  In any case this is a functional work around.

{
  "_id": "_design/CouchDbMultifactorAuthenticationTrustRecord",
  "_rev": "10-f5c3b2d1d2d76830b88fe50965fbbd0c",
  "views": {
    "all": {
      "map": "function(doc) { if (doc.recordKey && doc.principal && doc.deviceFingerprint && doc.recordDate) { emit(doc._id, doc) } }"
    },
    "by_recordKey": {
      "map": "function(doc) { if (doc.principal && doc.deviceFingerprint && doc.recordDate) { emit(doc.recordKey, doc) } }"
    },
    "by_recordDate": {
      "map": "function(doc) { if (doc.principal && doc.deviceFingerprint && doc.recordDate) { emit(doc.recordDate, doc) } }"
    },
    "by_expirationDate": {
      "map": "function(doc) { if (doc.principal && doc.deviceFingerprint && doc.expirationDate) { emit(doc.expirationDate, doc) } }"
    },
    "by_principal": {
      "map": "function(doc) { if (doc.principal && doc.deviceFingerprint && doc.recordDate) { emit(doc.principal, doc) } }"
    },
    "by_id": {
      "map": "function(doc) { if (doc.principal && doc.deviceFingerprint && doc.recordDate) { emit(doc.id, doc) } }"
    },
    "by_principal_date": {
      "map": "function(doc) { if (doc.recordKey && doc.principal && doc.deviceFingerprint && doc.recordDate) { emit([doc.principal, doc.recordDate], doc) } }"
    },
    "by_all": {
      "map": "function(doc) { if (doc.recordKey) { emit([doc.recordKey], doc) } }"
    },
    "by_not_processed": {
      "map": "function(doc) { if (doc.recordKey && !doc.processed) { emit([doc.recordKey], doc) } }"
    }
  },
  "lists": {},
  "shows": {},
  "language": "javascript",
  "filters": {}
}



{
  "_id": "_design/531fa4a2dcce623b3bf528d83ef5a85e0cafffe4",
  "_rev": "3-14798c189251a398d868ae55b8ea2e33",
  "language": "query",
  "views": {
    "processed-json-index": {
      "map": {
        "fields": {
          "processed": "asc"
        },
        "partial_filter_selector": {}
      },
      "reduce": "_count",
      "options": {
        "def": {
          "fields": [
            "processed"
          ]
        }
      }
    }
  }
}


In batch java job have something like the following to update the expiration date.

...
List<CasMfaCache> mfaList = dbClient.view("CouchDbMultifactorAuthenticationTrustRecord/by_not_processed")
      .includeDocs(true)
      .limit(200)
      .query(CasMfaCache.class);

    if ((mfaList != null) && (mfaList.size() > 0)) {

      for (CasMfaCache mfa : mfaList) {

        /*
          sample recordDate, and expirationDates with expected format in record

          "recordDate": "2023-06-17T19:49:39Z",
          "expirationDate": "2123-06-17T19:49:39.000+00:00"
        */

        LocalDate ld = LocalDate.parse(mfa.getRecordDate().substring(0, 10), dateFormatter).plusDays(expireInXDays);
        String expirationDate = ld.format(dateFormatter) + mfa.getRecordDate().substring(10, 19) + ".000+00:00";
 
        mfa.setExpirationDate(expirationDate);
        mfa.setProcessed("Y");

        dbClient.update(mfa);

      }

    }
...
Reply all
Reply to author
Forward
0 new messages