Skip to content

Commit e315a02

Browse files
committed
feat: Implement one time login qr code
Signed-off-by: Marcel Müller <marcel-mueller@gmx.de>
1 parent e70226f commit e315a02

File tree

3 files changed

+55
-2
lines changed

3 files changed

+55
-2
lines changed

NextcloudTalk/LoginViewController.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,4 +353,20 @@ class LoginViewController: UIViewController, UITextFieldDelegate, CCCertificateD
353353
NCSettingsController.sharedInstance().addNewAccount(forUser: user, withToken: password, inServer: serverURL)
354354
delegate?.loginViewControllerDidFinish()
355355
}
356+
357+
func qrScanner(_ scanner: QRScannerViewController, didScanNextcloudOnetimeLogin serverURL: String, user: String, onetimeToken: String) {
358+
// We received a onetime login token and need to convert it to a permanent one. The token only allows to retrieve a permanent one, no other routes allowed
359+
NCAPIController.sharedInstance().getAppPasswordOnetime(forServer: serverURL, withUsername: user, andOnetimeToken: onetimeToken) { [weak self] permanentAppToken in
360+
guard let permanentAppToken else {
361+
self?.showAlert(
362+
title: NSLocalizedString("Could not login with QR code", comment: ""),
363+
message: NSLocalizedString("The token might be used already or is expired. Please generate a new QR code and retry.", comment: ""))
364+
365+
return
366+
}
367+
368+
NCSettingsController.sharedInstance().addNewAccount(forUser: user, withToken: permanentAppToken, inServer: serverURL)
369+
self?.delegate?.loginViewControllerDidFinish()
370+
}
371+
}
356372
}

NextcloudTalk/NCAPIControllerExtensions.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1274,4 +1274,32 @@ import NextcloudKit
12741274
completionBlock(thread)
12751275
}
12761276
}
1277+
1278+
// MARK: - Core
1279+
1280+
@nonobjc
1281+
func getAppPasswordOnetime(forServer server: String, withUsername username: String, andOnetimeToken onetimeToken: String, completionBlock: @escaping (_ permanentAppToken: String?) -> Void) {
1282+
let appPasswordRoute = "\(server)/ocs/v2.php/core/getapppassword-onetime"
1283+
1284+
let credentialsString = "\(username):\(onetimeToken)"
1285+
let authHeader = "Basic \(credentialsString.data(using: .utf8)!.base64EncodedString())"
1286+
1287+
let configuration = URLSessionConfiguration.default
1288+
let apiSessionManager = NCAPISessionManager(configuration: configuration)
1289+
apiSessionManager.requestSerializer.setValue(authHeader, forHTTPHeaderField: "Authorization")
1290+
1291+
_ = apiSessionManager.get(appPasswordRoute, parameters: nil, progress: nil) { _, result in
1292+
if let resultDict = result as? [String: AnyObject],
1293+
let ocs = resultDict["ocs"] as? [String: AnyObject],
1294+
let data = ocs["data"] as? [String: AnyObject],
1295+
let apppassword = data["apppassword"] as? String {
1296+
1297+
completionBlock(apppassword)
1298+
}
1299+
1300+
completionBlock(nil)
1301+
} failure: { _, _ in
1302+
completionBlock(nil)
1303+
}
1304+
}
12771305
}

NextcloudTalk/QRScannerViewController.swift

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import VisionKit
88

99
@objc protocol QRScannerViewControllerDelegate: AnyObject {
1010
func qrScanner(_ scanner: QRScannerViewController, didScanNextcloudLogin serverURL: String, user: String, password: String)
11+
func qrScanner(_ scanner: QRScannerViewController, didScanNextcloudOnetimeLogin serverURL: String, user: String, onetimeToken: String)
1112
}
1213

1314
@objcMembers
@@ -137,7 +138,10 @@ class QRScannerViewController: UIViewController, DataScannerViewControllerDelega
137138
guard case let .barcode(barcode) = item,
138139
let value = barcode.payloadStringValue else { return }
139140

140-
if let urlComponents = NSURLComponents(string: value), var path = urlComponents.path, urlComponents.scheme == "nc", urlComponents.host == "login" {
141+
if let urlComponents = NSURLComponents(string: value), var path = urlComponents.path, urlComponents.scheme == "nc" {
142+
let isOnetimeLogin = (urlComponents.host == "onetime-login")
143+
guard urlComponents.host == "login" || isOnetimeLogin else { return }
144+
141145
if path.starts(with: "/") {
142146
path.removeFirst()
143147
}
@@ -152,7 +156,12 @@ class QRScannerViewController: UIViewController, DataScannerViewControllerDelega
152156

153157
scannerViewController?.stopScanning()
154158
self.dismiss(animated: true)
155-
self.delegate?.qrScanner(self, didScanNextcloudLogin: serverUrl, user: user, password: password)
159+
160+
if isOnetimeLogin {
161+
self.delegate?.qrScanner(self, didScanNextcloudOnetimeLogin: serverUrl, user: user, onetimeToken: password)
162+
} else {
163+
self.delegate?.qrScanner(self, didScanNextcloudLogin: serverUrl, user: user, password: password)
164+
}
156165

157166
return
158167
}

0 commit comments

Comments
 (0)