Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
liberty
tunnel
liberty-tunnel-client-library-apple
Commits
1a037220
Commit
1a037220
authored
Nov 28, 2018
by
Jose Blaya
Browse files
Store the token in the Keychain (WIP)
parent
650573e8
Changes
8
Hide whitespace changes
Inline
Side-by-side
PIALibrary/Sources/Core/Account/AccountProvider.swift
View file @
1a037220
...
...
@@ -22,6 +22,9 @@ public protocol AccountProvider: class {
/// The user account currently logged in, or `nil` if logged out.
var
currentUser
:
UserAccount
?
{
get
set
}
/// The current auth token, or 'nil' if logged out.
var
token
:
String
?
{
get
}
/// The password reference object associated with the currentUser, or `nil` if logged out.
var
currentPasswordReference
:
Data
?
{
get
}
...
...
PIALibrary/Sources/Core/Persistence/SecureStore.swift
View file @
1a037220
...
...
@@ -19,5 +19,13 @@ protocol SecureStore: class {
func
passwordReference
(
for
username
:
String
)
->
Data
?
func
token
(
for
username
:
String
)
->
String
?
func
setToken
(
_
token
:
String
?,
for
username
:
String
)
func
tokenReference
(
for
username
:
String
)
->
Data
?
func
tokenKey
(
for
username
:
String
)
->
String
func
clear
(
for
username
:
String
)
}
PIALibrary/Sources/Library/Account/DefaultAccountProvider.swift
View file @
1a037220
...
...
@@ -75,6 +75,14 @@ class DefaultAccountProvider: AccountProvider, ConfigurationAccess, DatabaseAcce
}
}
var
token
:
String
?
{
guard
let
username
=
accessedDatabase
.
plain
.
username
else
{
return
nil
}
return
accessedDatabase
.
secure
.
token
(
for
:
accessedDatabase
.
secure
.
tokenKey
(
for
:
username
))
}
var
currentPasswordReference
:
Data
?
{
guard
let
username
=
accessedDatabase
.
plain
.
username
else
{
return
nil
...
...
@@ -103,6 +111,10 @@ class DefaultAccountProvider: AccountProvider, ConfigurationAccess, DatabaseAcce
return
}
self
.
accessedDatabase
.
plain
.
username
=
request
.
credentials
.
username
self
.
accessedDatabase
.
secure
.
setToken
(
request
.
credentials
.
password
,
for
:
self
.
accessedDatabase
.
secure
.
tokenKey
(
for
:
request
.
credentials
.
username
))
self
.
webServices
.
info
(
token
:
token
)
{
(
accountInfo
,
error
)
in
guard
let
accountInfo
=
accountInfo
else
{
callback
?(
nil
,
error
)
...
...
@@ -110,10 +122,9 @@ class DefaultAccountProvider: AccountProvider, ConfigurationAccess, DatabaseAcce
}
//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
.
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
,
[
...
...
PIALibrary/Sources/Library/Persistence/KeychainStore.swift
View file @
1a037220
...
...
@@ -58,6 +58,31 @@ class KeychainStore: SecureStore {
func
clear
(
for
username
:
String
)
{
backend
.
removePassword
(
for
:
username
)
backend
.
removeToken
(
for
:
tokenKey
(
for
:
username
))
backend
.
remove
(
publicKeyWithIdentifier
:
Entries
.
publicKey
)
}
}
extension
KeychainStore
{
func
token
(
for
username
:
String
)
->
String
?
{
return
try
?
backend
.
token
(
for
:
username
)
}
func
setToken
(
_
token
:
String
?,
for
username
:
String
)
{
if
let
token
=
token
{
try
?
backend
.
set
(
token
:
token
,
for
:
username
)
}
else
{
backend
.
removeToken
(
for
:
username
)
}
}
func
tokenReference
(
for
username
:
String
)
->
Data
?
{
return
try
?
backend
.
tokenReference
(
for
:
username
)
}
func
tokenKey
(
for
username
:
String
)
->
String
{
return
"auth-token:
\(
username
)
"
}
}
PIALibrary/Sources/Library/WebServices/PIAWebServices.swift
View file @
1a037220
...
...
@@ -53,7 +53,7 @@ class PIAWebServices: WebServices, ConfigurationAccess {
429
:
.
throttled
]
req
(
nil
,
.
get
,
endpoint
,
nil
,
status
,
JSONRequestExecutor
()
{
(
json
,
status
,
error
)
in
req
(
nil
,
.
get
,
endpoint
,
useAuthToken
:
true
,
nil
,
status
,
JSONRequestExecutor
()
{
(
json
,
status
,
error
)
in
if
let
knownError
=
self
.
knownError
(
endpoint
,
status
,
errors
)
{
callback
?(
nil
,
knownError
)
return
...
...
@@ -239,11 +239,11 @@ class PIAWebServices: WebServices, ConfigurationAccess {
headers
[
authHeader
.
key
]
=
authHeader
.
value
}
if
useToken
{
//TODO: PLEASE GET TOKEN HERE
headers
[
"Authorization"
]
=
"Token
PLEASE THE TOKEN HERE
"
if
useToken
,
let
token
=
Client
.
providers
.
accountProvider
.
token
{
headers
[
"Authorization"
]
=
"Token
\(
token
)
"
}
if
let
parameters
=
parameters
{
log
.
debug
(
"Request:
\(
method
)
\"\(
url
)\"
, parameters:
\(
parameters
)
, headers:
\(
headers
)
"
)
}
else
{
...
...
PIALibrary/Sources/Mock/MockAccountProvider.swift
View file @
1a037220
...
...
@@ -10,6 +10,7 @@ import Foundation
/// Simulates account-related operations
public
class
MockAccountProvider
:
AccountProvider
,
WebServicesConsumer
{
/// Mocks the outcome of a sign-up operation.
///
...
...
@@ -111,6 +112,10 @@ public class MockAccountProvider: AccountProvider, WebServicesConsumer {
return
delegate
.
isLoggedIn
}
public
var
token
:
String
?
{
return
"TOKEN"
}
/// :nodoc:
public
var
currentUser
:
UserAccount
?
{
get
{
...
...
PIALibrary/Sources/UI/iOS/PIAWelcomeViewController.swift
View file @
1a037220
...
...
@@ -326,6 +326,8 @@ class EphemeralAccountProvider: AccountProvider, ProvidersAccess, InAppAccess {
var
isLoggedIn
=
false
var
token
:
String
?
var
currentUser
:
UserAccount
?
var
currentPasswordReference
:
Data
?
{
...
...
PIALibrary/Sources/Util/Keychain.swift
View file @
1a037220
...
...
@@ -226,3 +226,103 @@ public class Keychain {
}
}
}
extension
Keychain
{
// MARK: Token
/// :nodoc:
public
func
set
(
token
:
String
,
for
username
:
String
)
throws
{
removeToken
(
for
:
username
)
var
query
=
[
String
:
Any
]()
setScope
(
query
:
&
query
)
query
[
kSecClass
as
String
]
=
kSecClassGenericPassword
query
[
kSecAttrAccount
as
String
]
=
username
query
[
kSecAttrAccessible
as
String
]
=
kSecAttrAccessibleAfterFirstUnlock
query
[
kSecValueData
as
String
]
=
token
.
data
(
using
:
.
utf8
)
let
status
=
SecItemAdd
(
query
as
CFDictionary
,
nil
)
guard
(
status
==
errSecSuccess
)
else
{
throw
KeychainError
.
add
}
}
/// :nodoc:
@discardableResult
public
func
removeToken
(
for
username
:
String
)
->
Bool
{
var
query
=
[
String
:
Any
]()
setScope
(
query
:
&
query
)
query
[
kSecClass
as
String
]
=
kSecClassGenericPassword
query
[
kSecAttrAccount
as
String
]
=
username
let
status
=
SecItemDelete
(
query
as
CFDictionary
)
return
(
status
==
errSecSuccess
)
}
/// :nodoc:
public
func
token
(
for
username
:
String
)
throws
->
String
{
var
query
=
[
String
:
Any
]()
setScope
(
query
:
&
query
)
query
[
kSecClass
as
String
]
=
kSecClassGenericPassword
query
[
kSecAttrAccount
as
String
]
=
username
//query[kSecAttrAccessible as String] = kSecAttrAccessibleAfterFirstUnlock
query
[
kSecMatchLimit
as
String
]
=
kSecMatchLimitOne
query
[
kSecReturnData
as
String
]
=
true
var
result
:
AnyObject
?
let
status
=
SecItemCopyMatching
(
query
as
CFDictionary
,
&
result
)
guard
(
status
==
errSecSuccess
)
else
{
throw
KeychainError
.
notFound
}
guard
let
data
=
result
as?
Data
else
{
throw
KeychainError
.
notFound
}
guard
let
token
=
String
(
data
:
data
,
encoding
:
.
utf8
)
else
{
throw
KeychainError
.
notFound
}
return
token
}
/// :nodoc:
public
func
tokenReference
(
for
username
:
String
)
throws
->
Data
{
var
query
=
[
String
:
Any
]()
query
[
kSecClass
as
String
]
=
kSecClassGenericPassword
setScope
(
query
:
&
query
)
query
[
kSecAttrAccount
as
String
]
=
username
query
[
kSecMatchLimit
as
String
]
=
kSecMatchLimitOne
query
[
kSecReturnPersistentRef
as
String
]
=
true
var
result
:
AnyObject
?
let
status
=
SecItemCopyMatching
(
query
as
CFDictionary
,
&
result
)
guard
(
status
==
errSecSuccess
)
else
{
throw
KeychainError
.
notFound
}
guard
let
data
=
result
as?
Data
else
{
throw
KeychainError
.
notFound
}
return
data
}
/// :nodoc:
public
static
func
token
(
for
username
:
String
,
reference
:
Data
)
throws
->
String
{
var
query
=
[
String
:
Any
]()
query
[
kSecClass
as
String
]
=
kSecClassGenericPassword
query
[
kSecAttrAccount
as
String
]
=
username
query
[
kSecMatchItemList
as
String
]
=
[
reference
]
query
[
kSecReturnData
as
String
]
=
true
var
result
:
AnyObject
?
let
status
=
SecItemCopyMatching
(
query
as
CFDictionary
,
&
result
)
guard
(
status
==
errSecSuccess
)
else
{
throw
KeychainError
.
notFound
}
guard
let
data
=
result
as?
Data
else
{
throw
KeychainError
.
notFound
}
guard
let
password
=
String
(
data
:
data
,
encoding
:
.
utf8
)
else
{
throw
KeychainError
.
notFound
}
return
password
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment