diff --git a/Profile Manifest/com.twocanoes.xcreds.plist b/Profile Manifest/com.twocanoes.xcreds.plist
index 9838bb61..ba51a2f4 100644
--- a/Profile Manifest/com.twocanoes.xcreds.plist
+++ b/Profile Manifest/com.twocanoes.xcreds.plist
@@ -5,7 +5,7 @@
pfm_app_url
https://github.com/twocanoes/xcreds
pfm_description
- XCreds 3.3 (5273) OAuth Settings
+ XCreds 3.3 (5310) OAuth Settings
pfm_documentation_url
https://twocanoes.com/knowledge-base/xcreds-admin-guide/#preferences
pfm_domain
@@ -194,6 +194,25 @@ A profile can consist of payloads with different version numbers. For example, c
pfm_type
array
+
+ pfm_description
+ List of claims that should be added to the user local account. Will be prefixed with _xcreds_oidc_. Set as an Array of Strings of the claim.
+ pfm_name
+ claimsToAddToLocalUserAccount
+ pfm_subkeys
+
+
+ pfm_name
+ claim
+ pfm_type
+ string
+
+
+ pfm_title
+ Claims To Add To Local User Account
+ pfm_type
+ array
+
pfm_default
diff --git a/XCreds/PrefKeys.swift b/XCreds/PrefKeys.swift
index a77b9f26..57269e13 100644
--- a/XCreds/PrefKeys.swift
+++ b/XCreds/PrefKeys.swift
@@ -9,7 +9,7 @@ import Foundation
enum PrefKeys: String {
case clientID, clientSecret, password="xcreds local password",discoveryURL, redirectURI, scopes, accessToken, idToken, refreshToken, tokenEndpoint, expirationDate, invalidToken, refreshRateHours,refreshRateMinutes, showDebug, verifyPassword, shouldShowQuitMenu, shouldShowPreferencesOnStart, shouldSetGoogleAccessTypeToOffline, passwordChangeURL, shouldShowAboutMenu, username, idpHostName, passwordElementID, shouldFindPasswordElement, shouldShowVersionInfo, shouldShowSupportStatus,shouldShowConfigureWifiButton,shouldShowMacLoginButton, loginWindowBackgroundImageURL, shouldShowCloudLoginByDefault, shouldPreferLocalLoginInsteadOfCloudLogin, idpHostNames,autoRefreshLoginTimer, loginWindowWidth, loginWindowHeight, shouldShowRefreshBanner, shouldSwitchToLoginWindowWhenLocked,accounts = "Accounts",
- windowSignIn = "WindowSignIn", settingsOverrideScriptPath, localAdminUserName, localAdminPassword, usernamePlaceholder, passwordPlaceholder, shouldShowLocalOnlyCheckbox, shouldShowTokenUpdateStatus, shouldDetectNetworkToDetermineLoginWindow, showLoginWindowDelaySeconds, shouldPromptForMigration, shouldAllowKeyComboForMacLoginWindow, aliasName
+ windowSignIn = "WindowSignIn", settingsOverrideScriptPath, localAdminUserName, localAdminPassword, usernamePlaceholder, passwordPlaceholder, shouldShowLocalOnlyCheckbox, shouldShowTokenUpdateStatus, shouldDetectNetworkToDetermineLoginWindow, showLoginWindowDelaySeconds, shouldPromptForMigration, shouldAllowKeyComboForMacLoginWindow, aliasName,claimsToAddToLocalUserAccount
//, filePathToPreventShowingUI
case ropgClientID
case ropgClientSecret
diff --git a/XCreds/defaults.plist b/XCreds/defaults.plist
index 8aff7e8f..ec21d283 100644
--- a/XCreds/defaults.plist
+++ b/XCreds/defaults.plist
@@ -58,5 +58,9 @@
shouldAllowKeyComboForMacLoginWindow
+ claimsToAddToLocalUserAccount
+
+ groups
+
diff --git a/XCredsLoginPlugIn/ContextAndHintHandling.swift b/XCredsLoginPlugIn/ContextAndHintHandling.swift
index e6133ee2..cc86c985 100644
--- a/XCredsLoginPlugIn/ContextAndHintHandling.swift
+++ b/XCredsLoginPlugIn/ContextAndHintHandling.swift
@@ -31,9 +31,10 @@ enum HintType: String {
// case noMADLast
// case noMADFull
case adGroups
- case oidcSub
- case oidcIssuer
+// case oidcSub
+// case oidcIssuer
case aliasName
+ case claimsToAddToLocalUserAccount
}
diff --git a/XCredsLoginPlugIn/LoginWindow/LoginWebViewWindowController.swift b/XCredsLoginPlugIn/LoginWindow/LoginWebViewWindowController.swift
index 000ce8ed..0f1ca443 100644
--- a/XCredsLoginPlugIn/LoginWindow/LoginWebViewWindowController.swift
+++ b/XCredsLoginPlugIn/LoginWindow/LoginWebViewWindowController.swift
@@ -261,9 +261,9 @@ class LoginWebViewWindowController: WebViewWindowController, DSQueryable {
let standardUsers = try? getAllStandardUsers()
let existingUser = try? getUserRecord(sub: subValue, iss: issuerValue)
- TCSLogWithMark("setting issuer and sub hint from OIDC token")
- delegate.setHint(type: .oidcSub, hint: "\(subValue)")
- delegate.setHint(type: .oidcIssuer, hint: "\(issuerValue)")
+// TCSLogWithMark("setting issuer and sub hint from OIDC token")
+// delegate.setHint(type: .oidcSub, hint: "\(subValue)")
+// delegate.setHint(type: .oidcIssuer, hint: "\(issuerValue)")
let aliasClaim = DefaultsOverride.standardOverride.string(forKey: PrefKeys.aliasName.rawValue)
if let aliasClaim = aliasClaim, let aliasClaimValue = idTokenInfo[aliasClaim] {
TCSLogWithMark("found alias claim: \(aliasClaim):\(aliasClaimValue)")
diff --git a/XCredsLoginPlugIn/Mechanisms/XCredsBaseMechanism.swift b/XCredsLoginPlugIn/Mechanisms/XCredsBaseMechanism.swift
index ce03a476..f8f7cc38 100644
--- a/XCredsLoginPlugIn/Mechanisms/XCredsBaseMechanism.swift
+++ b/XCredsLoginPlugIn/Mechanisms/XCredsBaseMechanism.swift
@@ -274,52 +274,7 @@ protocol XCredsMechanismProtocol {
return true
}
- class func updateOIDCInfo(user: String, iss:String?, sub:String?, groups:[String]?) -> Bool {
- os_log("Checking for local username", log: noLoMechlog, type: .default)
- var records = [ODRecord]()
- let odsession = ODSession.default()
- do {
- let node = try ODNode.init(session: odsession, type: ODNodeType(kODNodeTypeLocalNodes))
- let query = try ODQuery.init(node: node, forRecordTypes: kODRecordTypeUsers, attribute: kODAttributeTypeRecordName, matchType: ODMatchType(kODMatchEqualTo), queryValues: user, returnAttributes: kODAttributeTypeAllAttributes, maximumResults: 0)
- records = try query.resultsAllowingPartial(false) as! [ODRecord]
- } catch {
- let errorText = error.localizedDescription
- os_log("ODError while trying to check for local user: %{public}@", log: noLoMechlog, type: .error, errorText)
- return false
- }
-
- let isLocal = records.isEmpty ? false : true
- os_log("Results of local user check %{public}@", log: noLoMechlog, type: .default, isLocal.description)
-
- if !isLocal {
- return isLocal
- }
-
- // now to update the attribute
-
- do {
- os_log("updating sub",log: noLoMechlog, type: .error)
-
- try records.first?.setValue(sub, forAttribute: "dsAttrTypeNative:_xcreds_oidc_sub")
-
-
- os_log("updating iss",log: noLoMechlog, type: .error)
-
- try records.first?.setValue(iss, forAttribute: "dsAttrTypeNative:_xcreds_oidc_iss")
-
-
- if let groups = groups?.joined(separator: ";") {
- try records.first?.setValue(groups, forAttribute: "dsAttrTypeNative:_xcreds_oidc_groups")
-
- }
- } catch {
- os_log("Unable to add OIDC Info", log: noLoMechlog, type: .error)
- return false
- }
-
- return true
-
- }
+
/// Set one of the known `AuthorizationTags` values to be used during mechanism evaluation.
///
/// - Parameters:
diff --git a/XCredsLoginPlugIn/Mechanisms/XCredsCreateUser.swift b/XCredsLoginPlugIn/Mechanisms/XCredsCreateUser.swift
index 7d5747fa..519f7aa9 100644
--- a/XCredsLoginPlugIn/Mechanisms/XCredsCreateUser.swift
+++ b/XCredsLoginPlugIn/Mechanisms/XCredsCreateUser.swift
@@ -122,12 +122,6 @@ class XCredsCreateUser: XCredsBaseMechanism, DSQueryable {
let currentDate = ISO8601DateFormatter().string(from: Date())
customAttributes["dsAttrTypeNative:\(metaPrefix)_creationDate"] = currentDate
- if let oidcSubHint = getHint(type: .oidcSub) as? String {
- customAttributes["dsAttrTypeNative:\(metaPrefix)_oidc_sub"] = oidcSubHint
- }
- if let oidcIssHint = getHint(type: .oidcIssuer) as? String {
- customAttributes["dsAttrTypeNative:\(metaPrefix)_oidc_iss"] = oidcIssHint
- }
guard let xcredsFirst=xcredsFirst, let xcredsLast = xcredsLast else {
TCSLogErrorWithMark("first or last name not defined. bailing")
@@ -200,24 +194,15 @@ class XCredsCreateUser: XCredsBaseMechanism, DSQueryable {
}
}
-
- var sub:String?
- var iss:String?
var alias:String?
- if let oidcSubHint = getHint(type: .oidcSub) as? String {
- sub=oidcSubHint
- }
- if let oidcIssHint = getHint(type: .oidcIssuer) as? String {
- iss=oidcIssHint
- }
+
if let aliasHint = getHint(type: .aliasName) as? String {
alias=aliasHint
}
// Set the xcreds attributes to stamp this account as the mapped one
setTimestampFor(xcredsUser ?? "")
- if let iss = iss, let sub = sub {
- updateOIDCInfo(xcredsUser ?? "", iss: iss, sub:sub, groups:groups)
- }
+ let _ = updateOIDCInfo(user: xcredsUser ?? "")
+
if let alias = alias, let xcredsUser = xcredsUser {
if XCredsCreateUser.addAlias(name: xcredsUser, alias: alias)==false {
os_log("error adding alias", log: createUserLog, type: .debug)
@@ -245,6 +230,114 @@ class XCredsCreateUser: XCredsBaseMechanism, DSQueryable {
os_log("CreateUser mech complete", log: createUserLog, type: .debug)
}
+ func updateOIDCInfo(user: String) -> Bool {
+ os_log("Checking for local username", log: noLoMechlog, type: .default)
+ var records = [ODRecord]()
+ let odsession = ODSession.default()
+ do {
+ let node = try ODNode.init(session: odsession, type: ODNodeType(kODNodeTypeLocalNodes))
+ let query = try ODQuery.init(node: node, forRecordTypes: kODRecordTypeUsers, attribute: kODAttributeTypeRecordName, matchType: ODMatchType(kODMatchEqualTo), queryValues: user, returnAttributes: kODAttributeTypeAllAttributes, maximumResults: 0)
+ records = try query.resultsAllowingPartial(false) as! [ODRecord]
+ } catch {
+ let errorText = error.localizedDescription
+ os_log("ODError while trying to check for local user: %{public}@", log: noLoMechlog, type: .error, errorText)
+ return false
+ }
+
+ let isLocal = records.isEmpty ? false : true
+ os_log("Results of local user check %{public}@", log: noLoMechlog, type: .default, isLocal.description)
+
+ if !isLocal {
+ return false
+ }
+
+ // now to update the attribute
+ TCSLogWithMark("updating claims in DS")
+ let claimsToDSArray = (DefaultsOverride.standardOverride.array(forKey: PrefKeys.claimsToAddToLocalUserAccount.rawValue) ?? []) as? [String]
+
+ let tokenArray = getHint(type: .tokens) as? Array
+
+ if let tokenArray = tokenArray , tokenArray.count>0{
+ TCSLogWithMark("Found claims")
+ let idToken = tokenArray[0]
+ let idTokenInfo = jwtDecode(value: idToken) //dictionary for mapping
+ if let idTokenInfo = idTokenInfo {
+ TCSLogWithMark("Decoded Claims")
+ if var claimsToDSArray = claimsToDSArray {
+
+ claimsToDSArray.append("iss")
+ claimsToDSArray.append("sub")
+
+ for currClaim in claimsToDSArray {
+ TCSLogWithMark("Found Matching Claim: \(currClaim)")
+ if let value = idTokenInfo[currClaim] as? String {
+ let sanitizedKey = currClaim.oidc_allowed_chars
+ if sanitizedKey.count<20 || value.count<256 {
+ TCSLogWithMark("Adding \(sanitizedKey) = \(value)")
+ try? records.first?.setValue(value, forAttribute: "dsAttrTypeNative:_xcreds_oidc_\(sanitizedKey)")
+
+ }
+ else {
+ TCSLogWithMark("key or value too long to put into DS")
+ }
+
+ }
+ else if let value = idTokenInfo[currClaim] as? Array {
+ let sanitizedKey = currClaim.oidc_allowed_chars
+ let oneLine = value.joined(separator: ";")
+ if sanitizedKey.count<256 || oneLine.count<20 {
+ TCSLogWithMark("Adding \(sanitizedKey) = \(oneLine)")
+
+ try? records.first?.setValue(oneLine, forAttribute: "dsAttrTypeNative:_xcreds_oidc_\(sanitizedKey)")
+ }
+ else {
+ TCSLogWithMark("key or value too long to put into DS")
+ }
+ }
+ }
+ }
+ }
+ }
+
+// var sub:String?
+// var iss:String?
+// if let oidcSubHint = getHint(type: .oidcSub) as? String {
+// sub=oidcSubHint
+// }
+// if let oidcIssHint = getHint(type: .oidcIssuer) as? String {
+// iss=oidcIssHint
+// }
+//
+// if let oidcSubHint = getHint(type: .oidcSub) as? String {
+// customAttributes["dsAttrTypeNative:\(metaPrefix)_oidc_sub"] = oidcSubHint
+// }
+// if let oidcIssHint = getHint(type: .oidcIssuer) as? String {
+// customAttributes["dsAttrTypeNative:\(metaPrefix)_oidc_iss"] = oidcIssHint
+// }
+
+// do {
+// os_log("updating sub",log: noLoMechlog, type: .error)
+//
+// try records.first?.setValue(sub, forAttribute: "dsAttrTypeNative:_xcreds_oidc_sub")
+//
+//
+// os_log("updating iss",log: noLoMechlog, type: .error)
+//
+// try records.first?.setValue(iss, forAttribute: "dsAttrTypeNative:_xcreds_oidc_iss")
+//
+//
+//// if let groups = groups?.joined(separator: ";") {
+//// try records.first?.setValue(groups, forAttribute: "dsAttrTypeNative:_xcreds_oidc_groups")
+////
+//// }
+// } catch {
+// os_log("Unable to add OIDC Info", log: noLoMechlog, type: .error)
+// return false
+// }
+
+ return true
+
+ }
func createHome(xcredsUser:String, uid:String) {
TCSLogWithMark("Creating local homefolder for \(xcredsUser)")
createHomeDirFor(xcredsUser)
@@ -672,13 +765,7 @@ class XCredsCreateUser: XCredsBaseMechanism, DSQueryable {
}
}
- fileprivate func updateOIDCInfo(_ user: String, iss:String, sub:String,groups:[String]?) {
- if XCredsCreateUser.updateOIDCInfo(user:user, iss: iss, sub:sub, groups:groups) {
- os_log("updateOIDCInfo updated", log: createUserLog, type: .default)
- } else {
- os_log("Could not add updateOIDCInfo", log: createUserLog, type: .error)
- }
- }
+
fileprivate func addSecureToken(_ username: String, _ userPass: String?,_ adminUsername: String,_ adminPassword: String?) {
@@ -813,3 +900,11 @@ class XCredsCreateUser: XCredsBaseMechanism, DSQueryable {
// }
}
+extension String {
+ var oidc_allowed_chars: String {
+ var allowed = CharacterSet()
+ allowed.formUnion(CharacterSet.alphanumerics)
+ allowed.insert(charactersIn: "_#")
+ return self.components(separatedBy: allowed.inverted).joined()
+ }
+}
diff --git a/xCreds.xcodeproj/project.pbxproj b/xCreds.xcodeproj/project.pbxproj
index 8067bc9f..ac37a79b 100644
--- a/xCreds.xcodeproj/project.pbxproj
+++ b/xCreds.xcodeproj/project.pbxproj
@@ -1253,7 +1253,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 5300;
+ CURRENT_PROJECT_VERSION = 5310;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = UXP6YEHSPW;
FRAMEWORK_SEARCH_PATHS = (
@@ -1291,7 +1291,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 5300;
+ CURRENT_PROJECT_VERSION = 5310;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = UXP6YEHSPW;
FRAMEWORK_SEARCH_PATHS = (
@@ -1411,7 +1411,7 @@
CODE_SIGN_ENTITLEMENTS = "XCreds Login Overlay/XCreds_Login_Overlay.entitlements";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 5300;
+ CURRENT_PROJECT_VERSION = 5310;
DEVELOPMENT_TEAM = UXP6YEHSPW;
ENABLE_HARDENED_RUNTIME = YES;
FRAMEWORK_SEARCH_PATHS = (
@@ -1448,7 +1448,7 @@
CODE_SIGN_ENTITLEMENTS = "XCreds Login Overlay/XCreds_Login_Overlay.entitlements";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 5300;
+ CURRENT_PROJECT_VERSION = 5310;
DEVELOPMENT_TEAM = UXP6YEHSPW;
ENABLE_HARDENED_RUNTIME = YES;
FRAMEWORK_SEARCH_PATHS = (
@@ -1598,7 +1598,7 @@
CODE_SIGN_ENTITLEMENTS = XCreds/xCreds.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 5300;
+ CURRENT_PROJECT_VERSION = 5310;
DEVELOPMENT_TEAM = UXP6YEHSPW;
ENABLE_HARDENED_RUNTIME = YES;
FRAMEWORK_SEARCH_PATHS = (
@@ -1639,7 +1639,7 @@
CODE_SIGN_ENTITLEMENTS = XCreds/xCreds.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 5300;
+ CURRENT_PROJECT_VERSION = 5310;
DEVELOPMENT_TEAM = UXP6YEHSPW;
ENABLE_HARDENED_RUNTIME = YES;
FRAMEWORK_SEARCH_PATHS = (
diff --git a/xCreds.xcodeproj/project.xcworkspace/xcuserdata/tperfitt.xcuserdatad/UserInterfaceState.xcuserstate b/xCreds.xcodeproj/project.xcworkspace/xcuserdata/tperfitt.xcuserdatad/UserInterfaceState.xcuserstate
index e50b261a..e7044449 100644
Binary files a/xCreds.xcodeproj/project.xcworkspace/xcuserdata/tperfitt.xcuserdatad/UserInterfaceState.xcuserstate and b/xCreds.xcodeproj/project.xcworkspace/xcuserdata/tperfitt.xcuserdatad/UserInterfaceState.xcuserstate differ