Skip to content

Commit

Permalink
issue #100: Detect Offline
Browse files Browse the repository at this point in the history
  • Loading branch information
twocanoes committed Aug 27, 2023
1 parent c5c0cad commit fe804f1
Show file tree
Hide file tree
Showing 8 changed files with 119 additions and 103 deletions.
26 changes: 20 additions & 6 deletions Profile Manifest/com.twocanoes.xcreds.plist
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<key>pfm_app_url</key>
<string>https://github.com/twocanoes/xcreds</string>
<key>pfm_description</key>
<string>XCreds 3.2 (5087) OAuth Settings</string>
<string>XCreds 3.2 (5178) OAuth Settings</string>
<key>pfm_documentation_url</key>
<string>https://twocanoes.com/knowledge-base/xcreds-admin-guide/#preferences</string>
<key>pfm_domain</key>
Expand Down Expand Up @@ -443,7 +443,7 @@ Note that Google does not support the offline_access scope so instead use the pr
<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>Favor using XCreds' local login screen over the cloud login UI.</string>
<string>Favor using XCreds&apos; local login screen over the cloud login UI.</string>
<key>pfm_documentation_url</key>
<string>https://github.com/twocanoes/xcreds/wiki/AdminGuide#shouldpreferlocallogininsteadofcloudlogin</string>
<key>pfm_name</key>
Expand Down Expand Up @@ -661,7 +661,7 @@ Note that Google does not support the offline_access scope so instead use the pr
<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>Reset the keychain without prompting if the login password doesn't match the local password.</string>
<string>Reset the keychain without prompting if the login password doesn&apos;t match the local password.</string>
<key>pfm_documentation_url</key>
<string>https://twocanoes.com/knowledge-base/xcreds-admin-guide/#preferences</string>
<key>pfm_name</key>
Expand Down Expand Up @@ -723,6 +723,20 @@ Note that Google does not support the offline_access scope so instead use the pr
<key>pfm_type</key>
<string>boolean</string>
</dict>
<dict>
<key>pfm_default</key>
<false/>
<key>pfm_description</key>
<string>Check if network is up. If not, select username and password login window.</string>
<key>pfm_documentation_url</key>
<string>https://twocanoes.com/knowledge-base/xcreds-admin-guide/#preferences</string>
<key>pfm_name</key>
<string>shouldDetectNetworkToDetermineLoginWindow</string>
<key>pfm_title</key>
<string>Should Detect Network ToDetermine LoginWindow</string>
<key>pfm_type</key>
<string>boolean</string>
</dict>
<dict>
<key>pfm_description</key>
<string>Hostname of the page that has the password field. When the user submits the form, XCreds will use idpHostName to identify a page it needs to look for the password field. The password value is identified by an HTML id defined by passwordElementID. If this value is not defined. XCreds will look for login.microsoftonline.com and accounts.google.com. This value is commonly set for other IdP’s and for Azure environments that use ADFS.</string>
Expand Down Expand Up @@ -756,9 +770,9 @@ Note that Google does not support the offline_access scope so instead use the pr
</dict>
<dict>
<key>pfm_description</key>
<string>Password element id of the html element that has the password. It is read by using JavaScript to get the value (for example, for Azure, the JavaScript document.getElementById('i0118').value is sent. If this default is not set, standard values for Azure and Google Cloud will be used. To find out this value, use a browser to inspect the source of the page that has the password on it. Find the id of the textfield that has the password. Fill in the password and then open the JavaScript console. Run:
<string>Password element id of the html element that has the password. It is read by using JavaScript to get the value (for example, for Azure, the JavaScript document.getElementById(&apos;i0118&apos;).value is sent. If this default is not set, standard values for Azure and Google Cloud will be used. To find out this value, use a browser to inspect the source of the page that has the password on it. Find the id of the textfield that has the password. Fill in the password and then open the JavaScript console. Run:
document.getElementById('passwordID').value
document.getElementById(&apos;passwordID&apos;).value
changing “passwordID” to the correct element ID. If the value you typed into the textfield is returned, this is the correct ID.</string>
<key>pfm_documentation_url</key>
Expand Down Expand Up @@ -859,6 +873,6 @@ changing “passwordID” to the correct element ID. If the value you typed into
<key>pfm_unique</key>
<false/>
<key>pfm_version</key>
<integer>5087</integer>
<integer>5178</integer>
</dict>
</plist>
2 changes: 1 addition & 1 deletion XCreds/PrefKeys.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
windowSignIn = "WindowSignIn", settingsOverrideScriptPath, localAdminUserName, localAdminPassword, usernamePlaceholder, passwordPlaceholder, shouldShowLocalOnlyCheckbox, shouldShowTokenUpdateStatus, shouldDetectNetworkToDetermineLoginWindow
case actionItemOnly = "ActionItemOnly"
case aDDomain = "ADDomain"
case aDSite = "ADSite"
Expand Down
2 changes: 2 additions & 0 deletions XCreds/defaults.plist
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@
<string>Enter Username</string>
<key>shouldShowLocalOnlyCheckbox</key>
<true/>
<key>shouldDetectNetworkToDetermineLoginWindow</key>
<false/>
<key>passwordPlaceholder</key>
<string>Password</string>
</dict>
Expand Down
61 changes: 15 additions & 46 deletions XCredsLoginPlugIn/LoginWindow/LoginWebViewWindowController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@ import Foundation
import Cocoa
import WebKit
import OIDCLite
import Network
import OpenDirectory

class LoginWebViewWindowController: WebViewWindowController {

let uiLog = "uiLog"
let monitor = NWPathMonitor()
var internalDelegate:XCredsMechanismProtocol?
var delegate:XCredsMechanismProtocol? {
set {
Expand All @@ -28,6 +26,7 @@ class LoginWebViewWindowController: WebViewWindowController {
}
}
var resolutionObserver:Any?
var networkChangeObserver:Any?
var loginProgressWindowController:LoginProgressWindowController?
@IBOutlet weak var backgroundImageView: NSImageView!
@IBOutlet var controlsViewController: ControlsViewController?
Expand Down Expand Up @@ -59,6 +58,15 @@ class LoginWebViewWindowController: WebViewWindowController {
}
}
TCSLogWithMark()
networkChangeObserver = NotificationCenter.default.addObserver(forName:NSNotification.Name("NetworkChanged"), object: nil, queue: nil) { notification in
// TCSLogWithMark("network changed.")
let userInfo = notification.userInfo as? [String:Bool]
if let userInfo = userInfo, let networkStatus = userInfo["online"], networkStatus==true {
self.loadPage()
}
}



resolutionObserver = NotificationCenter.default.addObserver(forName:NSApplication.didChangeScreenParametersNotification, object: nil, queue: nil) { notification in
TCSLogWithMark("Resolution changed. Resetting size")
Expand All @@ -71,48 +79,7 @@ class LoginWebViewWindowController: WebViewWindowController {

TCSLogWithMark("loading page")

monitor.pathUpdateHandler = { path in

TCSLogWithMark("network changed. \(path.debugDescription)")
if path.status != .satisfied {
TCSLogErrorWithMark("not connected")
}
else if path.usesInterfaceType(.cellular) {
TCSLogWithMark("Cellular")
}
else if path.usesInterfaceType(.wifi) {
TCSLogWithMark("Wifi changed")
}
else if path.usesInterfaceType(.wiredEthernet) {
TCSLogWithMark("Ethernet")
}
else if path.usesInterfaceType(.other){
TCSLogWithMark("Other")
}
else if path.usesInterfaceType(.loopback){
TCSLogWithMark("Loop Back")
}
else {
TCSLogWithMark("Unknown interface type")
}


if path.status == .satisfied {

TCSLogWithMark("network changed")
DispatchQueue.main.async {

self.loadPage()
}

} else {
TCSLogErrorWithMark("No connection.")
}

print(path.isExpensive)
}
let queue = DispatchQueue(label: "Monitor")
monitor.start(queue: queue)


loadPage()
}
Expand Down Expand Up @@ -198,11 +165,13 @@ class LoginWebViewWindowController: WebViewWindowController {
//

// }
monitor.pathUpdateHandler=nil

if let resolutionObserver = resolutionObserver {
NotificationCenter.default.removeObserver(resolutionObserver)
}
if let networkChangeObserver = networkChangeObserver {
NotificationCenter.default.removeObserver(networkChangeObserver)

}



Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Cocoa
import Network


@objc class XCredsLoginMechanism: XCredsBaseMechanism {
Expand All @@ -14,6 +15,8 @@ import Cocoa
}
let checkADLog = "checkADLog"
var loginWindowType = LoginWindowType.cloud
let monitor = NWPathMonitor()

override init(mechanism: UnsafePointer<MechanismRecord>) {
let allBundles = Bundle.allBundles
//NSViewController(nibName: NSNib.Name("LoginWindow"), bundle: nil)
Expand Down Expand Up @@ -139,54 +142,80 @@ import Cocoa

return String.init(data: uuid, encoding: String.Encoding.utf8)
}
@objc override func run() {
TCSLogWithMark("XCredsLoginMechanism mech starting")
if useAutologin() {
os_log("Using autologin", log: checkADLog, type: .debug)
os_log("Check autologin complete", log: checkADLog, type: .debug)
allowLogin()
return
}
func selectAndShowLoginWindow(){
TCSLogWithMark()
let discoveryURL=DefaultsOverride.standardOverride.value(forKey: PrefKeys.discoveryURL.rawValue)
let preferLocalLogin = DefaultsOverride.standardOverride.bool(forKey: PrefKeys.shouldPreferLocalLoginInsteadOfCloudLogin.rawValue)

let shouldDetectNetwork = DefaultsOverride.standardOverride.bool(forKey: PrefKeys.shouldDetectNetworkToDetermineLoginWindow.rawValue)
TCSLogWithMark("checking if local login")
if preferLocalLogin == false,
let _ = discoveryURL {
showLoginWindowType(loginWindowType: .cloud)
let _ = discoveryURL {
if shouldDetectNetwork == true,
WifiManager().isConnectedToNetwork()==false {
showLoginWindowType(loginWindowType: .usernamePassword)
}
else {
TCSLogWithMark("network available, showing cloud")
showLoginWindowType(loginWindowType: .cloud)
}
}
else {
TCSLogWithMark("preferring showing local")

showLoginWindowType(loginWindowType: .usernamePassword)

}
}
func startNetworkMonitoring(){
monitor.pathUpdateHandler = { path in

// if (false){
//
// os_log("Activating app", log: checkADLog, type: .debug)
// NSApp.activate(ignoringOtherApps: true)
// os_log("Loading XIB", log: checkADLog, type: .debug)
// signIn = SignIn(windowNibName: NSNib.Name("SignIn"))
// os_log("Set mech for loginwindow", log: checkADLog, type: .debug)
// signIn.mech = mech
//// if let domain = self.managedDomain {
//// os_log("Set managed domain for loginwindow", log: checkADLog, type: .debug)
//// signIn.domainName = domain.uppercased()
//// }
//// if let isSSLRequired = self.isSSLRequired {
//// os_log("Set SSL required", log: checkADLog, type: .debug)
//// signIn.isSSLRequired = isSSLRequired
//// }
// guard signIn.window != nil else {
// os_log("Could not create login window UI", log: checkADLog, type: .default)
// return
// }
// os_log("Displaying window", log: checkADLog, type: .debug)
// if getManagedPreference(key: .NormalWindowLevel) as? Bool == false {
// NSApp.runModal(for: signIn.window!)
// }
//
// os_log("CheckAD mech complete", log: checkADLog, type: .debug)
// return
// }
TCSLogWithMark("network changed. \(path.debugDescription)")
if path.status != .satisfied {
TCSLogErrorWithMark("not connected")
}
else if path.usesInterfaceType(.cellular) {
TCSLogWithMark("Cellular")
}
else if path.usesInterfaceType(.wifi) {
TCSLogWithMark("Wifi changed")
}
else if path.usesInterfaceType(.wiredEthernet) {
TCSLogWithMark("Ethernet")
}
else if path.usesInterfaceType(.other){
TCSLogWithMark("Other")
}
else if path.usesInterfaceType(.loopback){
TCSLogWithMark("Loop Back")
}
else {
TCSLogWithMark("Unknown interface type")
}
self.selectAndShowLoginWindow()
TCSLogWithMark("network changed")
NotificationCenter.default.post(name: NSNotification.Name("NetworkChanged"), object: self, userInfo: ["online":path.status == .satisfied])

}
let queue = DispatchQueue(label: "Monitor")
monitor.start(queue: queue)
}
func stopNetworkMonitoring() {
monitor.cancel()
monitor.pathUpdateHandler=nil

}
@objc override func run() {
TCSLogWithMark("XCredsLoginMechanism mech starting")
if useAutologin() {
os_log("Using autologin", log: checkADLog, type: .debug)
os_log("Check autologin complete", log: checkADLog, type: .debug)
allowLogin()
return
}


selectAndShowLoginWindow()

let isReturning = FileManager.default.fileExists(atPath: "/tmp/xcreds_return")
TCSLogWithMark("Verifying if we should show cloud login.")
Expand Down Expand Up @@ -233,6 +262,7 @@ import Cocoa
// loginWindowControlsWindowController.window?.alphaValue=0.7
}
override func allowLogin() {
stopNetworkMonitoring()
TCSLogWithMark("Allowing Login")
// if loginWindowControlsWindowController != nil {
// TCSLogWithMark("Dismissing controller")
Expand All @@ -248,6 +278,7 @@ import Cocoa
super.allowLogin()
}
override func denyLogin(message:String?) {
stopNetworkMonitoring()
// loginWindowControlsWindowController.close()
loginWebViewWindowController?.loadPage()
TCSLog("***************** DENYING LOGIN FROM LOGIN MECH ********************");
Expand Down

0 comments on commit fe804f1

Please sign in to comment.