diff --git a/FitKit/Base.lproj/Main.storyboard b/FitKit/Base.lproj/Main.storyboard index 4203523..2ba3971 100644 --- a/FitKit/Base.lproj/Main.storyboard +++ b/FitKit/Base.lproj/Main.storyboard @@ -36,7 +36,6 @@ - Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda. diff --git a/FitKit/FitbitClient.swift b/FitKit/FitbitClient.swift index 7d2f652..12e75e2 100644 --- a/FitKit/FitbitClient.swift +++ b/FitKit/FitbitClient.swift @@ -9,12 +9,9 @@ import Foundation import Alamofire import OAuthSwift -import Locksmith +import SwiftKeychainWrapper import OAuthSwiftAlamofire -let ACCOUNT_NAME = "FitBit" -let SERVICE_NAME = "FitKit" - class FitbitClient { private enum FitKitRequestError: Error { case unableToParseResults @@ -26,6 +23,7 @@ class FitbitClient { private let callbackUrl = "fitkit://oauth-callback/fitbit" private let authorizeUrl = "https://www.fitbit.com/oauth2/authorize" private let accessTokenUrl = "https://api.fitbit.com/oauth2/token" + private var keychainWrapper: KeychainWrapper init() { // Init inner client @@ -41,19 +39,33 @@ class FitbitClient { let sessionManager = SessionManager.default sessionManager.adapter = self.oauthClient.requestAdapter sessionManager.retrier = self.oauthClient.requestAdapter + + // Use standard KeychainWrapper + self.keychainWrapper = KeychainWrapper.standard + + // Attempt to load tokens + self.loadStoredTokens() } func loadStoredTokens() { - NSLog("Someday we'll load stored credentials here! Today is not that day") - /* - let (oAuthData, _) = Locksmith.loadDataForUserAccount(userAccount: ACCOUNT_NAME, inService: SERVICE_NAME) - if let accessToken = oAuthData?.objectForKey("accessToken") { - // We have the token!! - self.oauthClient.client.credentials.oauthToken = accessToken - } else { - // No token! Boo + if let credential = self.readCredential() { + NSLog("Using credential from Keychain") + self.oauthClient.client.credential.oauthToken = credential.oauthToken + self.oauthClient.client.credential.oauthTokenExpiresAt = credential.oauthTokenExpiresAt } - */ + } + + func readCredential() -> OAuthSwiftCredential? { + if let credential = self.keychainWrapper.object(forKey: "credential") as? OAuthSwiftCredential { + NSLog("Found credential in keychain") + return credential + } + NSLog("No credential found in keychain") + return nil + } + + private func storeCredential(_ credential: OAuthSwiftCredential) -> Bool { + return self.keychainWrapper.set(credential, forKey: "credential") } /// Check if the current client is already authorized @@ -91,7 +103,17 @@ class FitbitClient { state:"FITKIT", // TODO: make CSRF token success: { credential, response, parameters in - NSLog("Succesfully authenticated with credentials %s", credential.oauthToken) + // Verify state is consistent + guard parameters["state"] as? String == "FITKIT", + let scope = parameters["scope"] as? String + else { + NSLog("Invalid authorization response") + failure() + return + } + NSLog("Authorized scope: \(scope)") + NSLog("Succesfully authenticated with credentials \(credential.oauthToken)") + let _ = self.storeCredential(credential) success() }, failure: { @@ -143,13 +165,13 @@ class FitbitClient { NSLog("Got weight! \(response.result.value!)") guard let results = response.result.value as? [String: Any] else { - print("Return result not in form [String: Any]") + NSLog("Return result not in form [String: Any]") callback(nil, FitKitRequestError.unableToParseResults) return } guard let weights = results["weight"] as? [[String: Any]] else { - print("Return result does not contain a list of weights") + NSLog("Return result does not contain a list of weights") callback(nil, FitKitRequestError.unableToParseResults) return } diff --git a/FitKit/ViewController.swift b/FitKit/ViewController.swift index 3909fa4..6687dcf 100644 --- a/FitKit/ViewController.swift +++ b/FitKit/ViewController.swift @@ -45,6 +45,9 @@ class ViewController: UIViewController { // TODO: Do something with the result and error if !self.client.isAuthorized() { self.client.authorize(viewController: self, success: self.authorized, failure: self.unauthroized) + } else { + // TODO: this should be made significantly more clear + self.displayWeight() } } } @@ -65,7 +68,6 @@ class ViewController: UIViewController { self.client.getWeight(start: lastMonth, end: today) { response in FitbitClient.weightResponseHandler(response: response) { fbWeights, error in - if let error = error { NSLog("Unable to get weights: \(error)") return @@ -76,6 +78,7 @@ class ViewController: UIViewController { NSLog("Got Weight: \(fbWeight.logId): \(fbWeight.date) \(fbWeight.weight)") HealthKitHelper.maybeSaveSample(fbWeight, callback: {_,_ in}) } + self.outputText.text = "Health data is synced" } } } diff --git a/Podfile b/Podfile index 602a8b3..7f116c2 100644 --- a/Podfile +++ b/Podfile @@ -8,7 +8,7 @@ target 'FitKit' do use_frameworks! pod "Alamofire" - pod "Locksmith" + pod "SwiftKeychainWrapper" pod 'OAuthSwift', '~> 1.2.0' pod 'OAuthSwiftAlamofire' diff --git a/Podfile.lock b/Podfile.lock index c9d5087..9fe302d 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,23 +1,23 @@ PODS: - Alamofire (4.5.1) - - Locksmith (4.0.0) - OAuthSwift (1.2.0) - OAuthSwiftAlamofire (0.1.0): - Alamofire - OAuthSwift + - SwiftKeychainWrapper (3.0.1) DEPENDENCIES: - Alamofire - - Locksmith - OAuthSwift (~> 1.2.0) - OAuthSwiftAlamofire + - SwiftKeychainWrapper SPEC CHECKSUMS: Alamofire: 2d95912bf4c34f164fdfc335872e8c312acaea4a - Locksmith: e9bebbaaa4cee3c511bc358a44f843c3fe00e21f OAuthSwift: 7fd6855b8e4d58eb5a30d156ea9bed7a8aecd1ca OAuthSwiftAlamofire: 20bb998ac506f82c3bab0625fbc98a9c6fca783f + SwiftKeychainWrapper: 38952a3636320ae61bad3513cadd870929de7a4a -PODFILE CHECKSUM: 114ede9ace3efbf5222b8790a77f72e973a10d2b +PODFILE CHECKSUM: 949ba8ae3b42c5e2974df2d2a6db5effc0cc78a8 COCOAPODS: 1.2.0