Commit 650573e8 authored by Jose Blaya's avatar Jose Blaya
Browse files

- Update API login services to v2

- Use Auth Token instead of user/password authentication
- Update viewcontrollers to use the new token service
parent 09dd28ca
Pod::Spec.new do |s|
s.name = "PIALibrary"
s.version = "1.1.6"
s.version = "1.1.7"
s.summary = "PIA client library in Swift."
s.homepage = "https://www.privateinternetaccess.com/"
s.license = { :type => "MIT", :file => "LICENSE" }
s.author = { "Davide De Rosa" => "davide@londontrustmedia.com" }
s.author = { "Jose Blaya" => "joseblaya@londontrustmedia.com" }
s.source = { :git => "https://github.com/pia-foss/client-library-apple.git", :tag => "v#{s.version}" }
s.ios.deployment_target = "9.0"
......@@ -38,7 +38,7 @@ Pod::Spec.new do |s|
p.frameworks = "NetworkExtension"
p.pod_target_xcconfig = { "APPLICATION_EXTENSION_API_ONLY" => "YES" }
p.dependency "PIATunnel", "~> 1.1.7"
p.dependency "PIATunnel", "~> 1.1.8"
p.dependency "PIALibrary/Library"
end
......
......@@ -248,6 +248,7 @@
843C67C32122EA13005A3FDA /* AccountInfoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 843C67C12122E714005A3FDA /* AccountInfoTests.swift */; };
84D5DA702126CE2900F753F8 /* QRCameraScannerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84D5DA6F2126CE2900F753F8 /* QRCameraScannerViewController.swift */; };
A6680249A33738280B9AD733 /* Pods_PIALibrary_PIALibraryHost_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 566B62D4C21DD5A90EF1BAE6 /* Pods_PIALibrary_PIALibraryHost_iOS.framework */; };
DD58F4BB21AEB99C00D043F7 /* GlossToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD58F4BA21AEB99C00D043F7 /* GlossToken.swift */; };
DDC812482176166600CB290C /* SwiftGen+ScenesStoryboards.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC812472176166500CB290C /* SwiftGen+ScenesStoryboards.swift */; };
DDC8124A217617F900CB290C /* SwiftGen+SeguesStoryboards.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC81249217617F900CB290C /* SwiftGen+SeguesStoryboards.swift */; };
/* End PBXBuildFile section */
......@@ -491,6 +492,7 @@
8BF83242A6BD73CE080CEE2A /* Pods-PIALibrary-PIALibraryHost-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PIALibrary-PIALibraryHost-iOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-PIALibrary-PIALibraryHost-iOS/Pods-PIALibrary-PIALibraryHost-iOS.release.xcconfig"; sourceTree = "<group>"; };
BB47885FCCA9DDFF53237D2C /* Pods-PIALibrary-PIALibraryTests-iOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PIALibrary-PIALibraryTests-iOS.release.xcconfig"; path = "Pods/Target Support Files/Pods-PIALibrary-PIALibraryTests-iOS/Pods-PIALibrary-PIALibraryTests-iOS.release.xcconfig"; sourceTree = "<group>"; };
D9FDC8980713EDCEDD51B936 /* Pods-PIALibrary-PIALibrary-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PIALibrary-PIALibrary-iOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PIALibrary-PIALibrary-iOS/Pods-PIALibrary-PIALibrary-iOS.debug.xcconfig"; sourceTree = "<group>"; };
DD58F4BA21AEB99C00D043F7 /* GlossToken.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GlossToken.swift; sourceTree = "<group>"; };
DDC812472176166500CB290C /* SwiftGen+ScenesStoryboards.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SwiftGen+ScenesStoryboards.swift"; sourceTree = "<group>"; };
DDC81249217617F900CB290C /* SwiftGen+SeguesStoryboards.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SwiftGen+SeguesStoryboards.swift"; sourceTree = "<group>"; };
E526D8161FFFEE65AC2DF844 /* Pods-PIALibrary-PIALibraryTests-iOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-PIALibrary-PIALibraryTests-iOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-PIALibrary-PIALibraryTests-iOS/Pods-PIALibrary-PIALibraryTests-iOS.debug.xcconfig"; sourceTree = "<group>"; };
......@@ -638,6 +640,7 @@
0E9D626F1FDE83BD009A90CF /* GlossServer.swift */,
0E9D62701FDE83BD009A90CF /* GlossServersBundle.swift */,
0E3D13D81F9E273300434A48 /* GlossSignup.swift */,
DD58F4BA21AEB99C00D043F7 /* GlossToken.swift */,
0EFB512D1F82D7C50033B81F /* PIAWebServices.swift */,
0E392D9F1FE323ED0002160D /* PIAWebServices+Ephemeral.swift */,
0E392DA81FE329AD0002160D /* PlatformVPNLog.swift */,
......@@ -1499,6 +1502,7 @@
0EAA388B1F9CC4C4000149CF /* InAppProduct.swift in Sources */,
0EAA388D1F9CC4C4000149CF /* InAppTransaction.swift in Sources */,
0E4D4E9E1FA4CA7A007DA6DA /* PurchasePlan.swift in Sources */,
DD58F4BB21AEB99C00D043F7 /* GlossToken.swift in Sources */,
0E2215CF2008DFD900F5FB4D /* SwiftGen+Assets.swift in Sources */,
0EE78AF21F8187F8002E4CDD /* LoginRequest.swift in Sources */,
0EE78AF01F818767002E4CDD /* ClientError.swift in Sources */,
......
......@@ -22,4 +22,13 @@ public struct Credentials {
self.username = username
self.password = password
}
}
public extension Credentials {
public func toJSONDictionary() -> [String: Any] {
return ["username":username, "password": password]
}
}
......@@ -15,8 +15,10 @@ protocol WebServicesConsumer {
protocol WebServices: class {
// MARK: Account
func info(credentials: Credentials, _ callback: LibraryCallback<AccountInfo>?)
func token(credentials: Credentials, _ callback: LibraryCallback<String>?)
func info(token: String, _ callback: LibraryCallback<AccountInfo>?)
func update(credentials: Credentials, email: String, _ callback: SuccessLibraryCallback?)
......
......@@ -95,28 +95,44 @@ class DefaultAccountProvider: AccountProvider, ConfigurationAccess, DatabaseAcce
guard !isLoggedIn else {
preconditionFailure()
}
webServices.info(credentials: request.credentials) { (accountInfo, error) in
guard let accountInfo = accountInfo else {
webServices.token(credentials: request.credentials) { (token, error) in
guard let token = token else {
callback?(nil, error)
return
}
self.accessedDatabase.plain.username = request.credentials.username
self.accessedDatabase.secure.setPassword(request.credentials.password, for: request.credentials.username)
self.accessedDatabase.plain.accountInfo = accountInfo
let user = UserAccount(credentials: request.credentials, info: accountInfo)
Macros.postNotification(.PIAAccountDidLogin, [
.user: user
])
callback?(user, nil)
self.webServices.info(token: token) { (accountInfo, error) in
guard let accountInfo = accountInfo else {
callback?(nil, error)
return
}
//Save after confirm the login was successful.
self.accessedDatabase.plain.username = request.credentials.username
self.accessedDatabase.secure.setPassword(request.credentials.password, for: request.credentials.username)
self.accessedDatabase.plain.accountInfo = accountInfo
//TODO: PLEASE SAVE THE TOKEN HERE
let user = UserAccount(credentials: request.credentials, info: accountInfo)
Macros.postNotification(.PIAAccountDidLogin, [
.user: user
])
callback?(user, nil)
}
}
}
func refreshAccountInfo(_ callback: ((AccountInfo?, Error?) -> Void)?) {
guard let user = currentUser else {
preconditionFailure()
}
webServices.info(credentials: user.credentials) { (accountInfo, error) in
//TODO: PLEASE GET THE TOKEN HERE
webServices.info(token: "TOKEN HERE") { (accountInfo, error) in
guard let accountInfo = accountInfo else {
callback?(nil, error)
return
......@@ -335,7 +351,8 @@ class DefaultAccountProvider: AccountProvider, ConfigurationAccess, DatabaseAcce
}
Macros.postNotification(.PIAAccountDidRenew)
self.webServices.info(credentials: user.credentials) { (accountInfo, error) in
//TODO: PLEASE GET THE TOKEN HERE
self.webServices.info(token: "TOKEN HERE") { (accountInfo, error) in
guard let newAccountInfo = accountInfo else {
callback?(nil, nil)
return
......
......@@ -17,7 +17,9 @@ enum ClientEndpoint: String, Endpoint {
case redeem = "giftcard_redeem"
case account
case token = "v2/token"
case account = "v2/account"
case payment
......
//
// GlossToken.swift
// PIALibrary-iOS
//
// Created by Jose Antonio Blaya Garcia on 28/11/2018.
// Copyright © 2018 London Trust Media. All rights reserved.
//
import Foundation
import Gloss
class GlossToken: GlossParser {
let parsed: String
required init?(json: JSON) {
let token: String? = "token" <~~ json
parsed = token ?? ""
}
}
......@@ -16,7 +16,36 @@ private let log = SwiftyBeaver.self
class PIAWebServices: WebServices, ConfigurationAccess {
private static let serversVersion = 60
func info(credentials: Credentials, _ callback: ((AccountInfo?, Error?) -> Void)?) {
/***
Generates a new auth token for the specific user
*/
func token(credentials: Credentials, _ callback: ((String?, Error?) -> Void)?) {
let endpoint = ClientEndpoint.token
let status = [200, 401, 429]
let errors: [Int: ClientError] = [
401: .unauthorized,
429: .throttled
]
let parameters = credentials.toJSONDictionary()
req(nil, .post, endpoint, parameters, status, JSONRequestExecutor() { (json, status, error) in
if let knownError = self.knownError(endpoint, status, errors) {
callback?(nil, knownError)
return
}
guard let json = json else {
callback?(nil, error)
return
}
guard let token = GlossToken(json: json)?.parsed else {
callback?(nil, ClientError.malformedResponseData)
return
}
callback?(token, nil)
})
}
func info(token: String, _ callback: ((AccountInfo?, Error?) -> Void)?) {
let endpoint = ClientEndpoint.account
let status = [200, 401, 429]
let errors: [Int: ClientError] = [
......@@ -24,7 +53,7 @@ class PIAWebServices: WebServices, ConfigurationAccess {
429: .throttled
]
req(credentials, .get, endpoint, nil, status, JSONRequestExecutor() { (json, status, error) in
req(nil, .get, endpoint, nil, status, JSONRequestExecutor() { (json, status, error) in
if let knownError = self.knownError(endpoint, status, errors) {
callback?(nil, knownError)
return
......@@ -186,27 +215,35 @@ class PIAWebServices: WebServices, ConfigurationAccess {
_ credentials: Credentials?,
_ method: HTTPMethod,
_ endpoint: Endpoint,
useAuthToken useToken: Bool = false,
_ parameters: [String: Any]?,
_ statuses: [Int],
_ executor: RequestExecutor) {
req(credentials, method, endpoint.url, parameters, statuses, executor)
req(credentials, method, endpoint.url, useToken, parameters, statuses, executor)
}
private func req(
_ credentials: Credentials?,
_ method: HTTPMethod,
_ url: URL,
_ useToken: Bool,
_ parameters: [String: Any]?,
_ statuses: [Int],
_ executor: RequestExecutor) {
var headers = SessionManager.defaultHTTPHeaders
//TODO: HERE ADD THE TOKEN
// headers["X-Device"] = "ios-\(Constants.iosVersion)/\(Constants.appVersion)/\(Constants.language)/\(Constants.region)"
if let credentials = credentials, let authHeader = Request.authorizationHeader(user: credentials.username, password: credentials.password) {
headers[authHeader.key] = authHeader.value
}
if useToken {
//TODO: PLEASE GET TOKEN HERE
headers["Authorization"] = "Token PLEASE THE TOKEN HERE"
}
if let parameters = parameters {
log.debug("Request: \(method) \"\(url)\", parameters: \(parameters), headers: \(headers)")
} else {
......
......@@ -15,7 +15,13 @@ class MockWebServices: WebServices {
var serversBundle: (() -> ServersBundle)?
func info(credentials: Credentials, _ callback: ((AccountInfo?, Error?) -> Void)?) {
func token(credentials: Credentials, _ callback: ((String?, Error?) -> Void)?) {
let result = "AUTH_TOKEN"
let error: ClientError? = (result == nil) ? .unsupported : nil
callback?(result, error)
}
func info(token: String, _ callback: ((AccountInfo?, Error?) -> Void)?) {
let result = accountInfo?()
let error: ClientError? = (result == nil) ? .unsupported : nil
callback?(result, error)
......
......@@ -337,15 +337,24 @@ class EphemeralAccountProvider: AccountProvider, ProvidersAccess, InAppAccess {
}
func login(with request: LoginRequest, _ callback: ((UserAccount?, Error?) -> Void)?) {
webServices?.info(credentials: request.credentials) { (info, error) in
guard let info = info else {
webServices?.token(credentials: request.credentials) { (token, error) in
guard let token = token else {
callback?(nil, error)
return
}
let user = UserAccount(credentials: request.credentials, info: info)
self.currentUser = user
self.isLoggedIn = true
callback?(user, nil)
self.webServices?.info(token: token) { (info, error) in
guard let info = info else {
callback?(nil, error)
return
}
let user = UserAccount(credentials: request.credentials, info: info)
self.currentUser = user
self.isLoggedIn = true
callback?(user, nil)
}
}
}
......
......@@ -2,13 +2,13 @@ PODS:
- Alamofire (4.7.3)
- Gloss (2.0.1)
- OpenSSL-Apple (1.1.0h)
- PIATunnel (1.1.7):
- PIATunnel/AppExtension (= 1.1.7)
- PIATunnel/Core (= 1.1.7)
- PIATunnel/AppExtension (1.1.7):
- PIATunnel (1.1.8):
- PIATunnel/AppExtension (= 1.1.8)
- PIATunnel/Core (= 1.1.8)
- PIATunnel/AppExtension (1.1.8):
- PIATunnel/Core
- SwiftyBeaver
- PIATunnel/Core (1.1.7):
- PIATunnel/Core (1.1.8):
- OpenSSL-Apple (~> 1.1.0h)
- SwiftyBeaver
- ReachabilitySwift (4.3.0)
......@@ -37,7 +37,7 @@ SPEC CHECKSUMS:
Alamofire: c7287b6e5d7da964a70935e5db17046b7fde6568
Gloss: 1e8743f8de1fbe14a97f220ff901cba91ae5f8f8
OpenSSL-Apple: cd153d705ef350eb834ae7ff5f21f792b51ed208
PIATunnel: 3b1b68398ac384b04070994eabb53d7ce07e6368
PIATunnel: fc7e7d0a812c6c98138ac315e7a43008aadd15b2
ReachabilitySwift: 408477d1b6ed9779dba301953171e017c31241f3
SwiftyBeaver: ccfcdf85a04d429f1633f668650b0ce8020bda3a
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment