xcreds icon indicating copy to clipboard operation
xcreds copied to clipboard

[Feature Request] Add a Password Expire date or Days for OIDC users and more

Open chupsuymang opened this issue 1 year ago • 0 comments

the example is pretty rough I think but it would be nice to also have the password expire Date or better even in Days remaining for OIDC users as well.

Not sure this is the case for other cloud authentications but it is for our Azure & ADFS.

Within the ID Token I noticed we have the claim "pwd_exp" which is the time to pass before the password expires. Using this Unix time in Days Offset + todays Unix timestamp you can calculate the date of when the password will expire.

Kinda like below

func daysBetween(start: Date, end: Date) -> Int {
    return Calendar.current.dateComponents([.day], from: start, to: end).day! 
}

func getOIDPasswordExpire() -> String?{
    
    let keychainUtil = KeychainUtil()

    let idToken = try? keychainUtil.findPassword(serviceName: "xcreds idToken", accountName: "idToken")

    if let idToken = idToken?.1 {
        let idTokenInfo = jwtDecode(value: idToken)
        
        if let idTokenInfo = idTokenInfo, let mapKey = "pwd_exp" as? String, mapKey.count>0, let mapValue = idTokenInfo[mapKey] as? String {
            // TCSLogWithMark("Key pwd_exp found in idToken:\(mapValue)")
            let pwd_exp = Int(mapValue)

            let DateUnixTimeToday = Date(timeIntervalSince1970: TimeInterval(Int(Date().timeIntervalSince1970)))
            let DateUnixTimeExp = Date(timeIntervalSince1970: TimeInterval(Int(Date().timeIntervalSince1970) + pwd_exp!))
            // TCSLogWithMark("DateUnixTimeExp:\(DateUnixTimeExp)")
            
            let pwd_exp_days = daysBetween(start: DateUnixTimeToday, end: DateUnixTimeExp)
            
            return String(pwd_exp_days)
        }
        else {
            TCSLogWithMark("Key pwd_exp not found in idToken")
        }
    }
    return nil
}

and it can be used from the XCreds MainController like this maybe?

func OIDPasswordExpiryUpdate() {

        if let status = self.credentialStatus {
            if status != "Invalid Credentials" {
                if let pwd_exp_days = getOIDPasswordExpire() {
                    let int_pwd_exp_days = Int(pwd_exp_days) ?? 0
                    var message = ""
                    
                    if int_pwd_exp_days > 0 {
                        if int_pwd_exp_days > 1 {
                            message = "in \(pwd_exp_days) Days"
                        } else {
                            message = "in \(pwd_exp_days) Day"
                        }
                        
                        // Update the Password Expires with value grabbed from the ID Token
                        self.passwordExpires = message
                        TCSLogWithMark("OID Password Expires: \(message)")
                        
                        // In case of the password only being valid for X days also prompt an alert message
                        if int_pwd_exp_days <= 7 {
                            let alert = NSAlert()
                            alert.messageText = "Information"
                            alert.informativeText = "Your Password will Expire \(message).\nPlease considder changing it."
                            alert.alertStyle = .informational
                            alert.runModal()
                            TCSLogWithMark("Displayed OID Password Expire Warning: Your Password will Expire \(message). Please considder changing it.")
                        }
                    }
                }
            }
        }
    }

Probably within the "startCredentialCheck" it should also see to evaluate if there's a password expire on the ID token and set it accordingly.

And probably another good thing would be to somehow make XCreds report if a given user did sync his SSO/AD password with the local & when the last sync has been

chupsuymang avatar Feb 07 '24 22:02 chupsuymang