Commit d28c54a4 authored by Thomas Markiewicz's avatar Thomas Markiewicz
Browse files


parent 0bb36ae1
# Changelog
The format is based on [Keep a Changelog](
## [Unreleased]
- Merged upstream master v2.8.2
# Contribution Guidelines
Private Internet Access welcomes community contributions, and are always looking for ways in which to improve. Please take a look at our contribution guidelines, and get involved with the PIA community.
## Bugs and Issues
Have you found a bug? Is our software behaving in an unexpected way? Please check the open issues for duplicates -- perhaps a fix is already in development, or maybe a solution has already been published.
If not then please submit a bug report using our [template](/.github/
## Feature Requests
Feature requests can also be submitted as issues. We’d be grateful if you checked for duplicates also before submitting a feature request.
## Working with our Code
* Fork the repository. Make sure to keep your repository synced with the source repo.
* When you are ready to start working on a new feature, cut a new branch from `develop` with the prefix `feature/` (e.g. `feature/name-of-feature`).
* Refer to the [README](/ for instructions on how to install and build.
## Making Pull Requests
* Sync the `develop` branch in your fork with the `develop` branch in the source repo.
* Merge your feature branch into `develop`.
* Make your pull request from `develop` in your fork to `develop` in the source.
* Use short and concise commit messages.
* Lint your code before committing and making a pull request.
* Write unit tests for new features and make sure all tests are passing.
* If your pull request contains multiple commits or commits that are not meaningful, consider squashing them.
[![PIA logo][pia-image]][pia-url]
# client-library-apple
# Private Internet Access
Private Internet Access is the world's leading consumer VPN service. At Private Internet Access we believe in unfettered access for all, and as a firm supporter of the open source ecosystem we have made the decision to open source our VPN clients. For more information about the PIA service, please visit our website [][pia-url] or check out the [Wiki][pia-wiki].
# Client library for Apple platforms
With this library, consumers can easily enable and communicate with the Private Internet Access services. It provides abstract interfaces for authenticating, purchasing plans, updating servers, getting connectivity updates, handling VPN profiles etc. You will also find mock objects for testing the library offline.
## Getting started
The library has been tested on both iOS and macOS and includes the following features:
- [x] Authentication
- [x] Convenient login/signup view controllers (iOS only)
- [x] In-app plan purchasing
- [x] Server list handling
- [x] Network connectivity
- [x] Extensible VPN profiles
- [x] Persistent preferences
- [x] Mock objects for offline testing
- [x] Theming
- [x] Convenient macros
## Installation
### Requirements
- iOS 11.0+ / macOS 10.11+
- Xcode 9+ (Swift 4)
- Git (preinstalled with Xcode Command Line Tools)
- Ruby (preinstalled with macOS)
- [CocoaPods 1.5.0][dep-cocoapods]
- [SwiftGen][dep-swiftgen]
- [jazzy][dep-jazzy] (optional, for documentation)
It's highly recommended to use the Git and Ruby packages provided by [Homebrew][dep-brew].
### CocoaPods
To use with CocoaPods just add this to your Podfile:
pod 'PIALibrary'
To include other non-default subspecs:
pod 'PIALibrary'
pod 'PIALibrary/VPN' # adds support for TunnelKit
pod 'PIALibrary/Mock'
### Testing
Download the library codebase locally:
$ git clone
Assuming you have a [working CocoaPods environment][dep-cocoapods], setting up the library workspace only requires installing the pod dependencies:
$ pod install
After that, open `PIALibrary.xcworkspace` in Xcode and run the unit tests found in the `PIALibraryTests` target. A simple CMD+U while on `PIALibrary-iOS` should do that as well.
#### Demo
There is a `Demo` directory containing a simple project for testing the library. As usual, prepare for CocoaPods:
$ pod install
then open `Demo.xcworkspace`. You can test the account-related business with the `WelcomeDemo-iOS` target which is, unsurprisingly, for iOS only.
We'd definitely like to offer a more extensive showcase later on.
## Documentation
Due to its complexity, the library is split into several modules named after their context. The *Core* and *Library* modules make up the foundation of the library and are the bare requirements.
Full documentation of the public interface is available and can be generated with [jazzy][dep-jazzy]. After installing the jazzy Ruby gem with:
$ gem install jazzy
enter the root directory of the repository and run:
$ jazzy
The generated output is stored into the `docs` directory in HTML format.
### Core
Here you will find the core components on top of which the library is built. These consist of:
- Business interfaces (e.g. `AccountProvider`)
- Web model (e.g. `AccountInfo`)
- Persistence model
- Callbacks (e.g. `LibraryCallback`)
- Public notifications
- Utilities (`Macros` and extensions)
### Library
The module is the default implementation of *Core*. It has an entry point called `Client`, which is the gateway to mostly every available method and variable.
The `Client` container gives access to:
- `Client.environment` - the environment in which the library operates
- `Client.configuration` - defines default and transient values/behavior
- `Client.database` - the persistency layer
- `Client.daemons` - holds information coming from passive updates
- `Client.preferences` - the model for persistent preferences
- `Client.providers` - the current implementations of Core's `*Provider` interfaces
#### Bootstrap
Before using the library, a bootstrap phase is needed through the invocation of `Client.bootstrap()`. Before the bootstrap itself, you want to take care of fine-tuning the library parameters.
Below is a typical bootstrap code:
import PIALibrary
// ...
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
Client.environment = .production
Client.providers.vpnProvider = MockVPNProvider()
Client.configuration.enablesServerUpdates = false
Client.configuration.verifiesServersSignature = true
Client.configuration.enablesConnectivityUpdates = false
// ...
return true
1. Sets the current environment to production endpoints
2. Mocks the VPN connection (especially useful on the iPhone simulator)
3. Receives notifications about server updates
4. Verifies the server list signature against the PIA public key
5. Receives notifications about connectivity (e.g. public IP address)
Remember to dispose the library at the end of the consumer lifecycle:
func applicationWillTerminate(_ application: UIApplication) {
#### Examples
Log into PIA:
// pack auth request
let credentials = Credentials(username: "user", password: "pass")
let request = LoginRequest(credentials: credentials)
// verify credentials against PIA services
Client.providers.accountProvider.login(with: request) { (user, error) in
guard let user = user else {
print("Login failed: \(error)")
// success, print user info
print("Account info: \(")
Connect to the VPN:
// do this on simulator
// ...
// raw set VPN credentials (skip verify for this sample)
let credentials = Credentials(username: "user", password: "pass")
let user = UserAccount(credentials: credentials, info: nil)
Client.providers.accountProvider.currentUser = user
// establish VPN type (protocol)
let prefs = Client.preferences.editable()
prefs.vpnType = IKEv2Profile.vpnType
// observe VPN updates
NotificationCenter.default.addObserver(forName: .PIADaemonsDidUpdateVPNStatus, object: nil, queue: nil) { (notification) in
print("VPN status: \(Client.daemons.vpnStatus)")
// connect
Get public IP notifications:
// enable passive connectivity updates
// ...
Client.configuration.enablesConnectivityUpdates = true
// observe connectivity updates
NotificationCenter.default.addObserver(forName: .PIADaemonsDidUpdateConnectivity, object: nil, queue: nil) { (notification) in
guard let ip = Client.daemons.publicIP else {
print("Unable to get public IP")
print("Public IP: \(ip)")
### VPN
The *VPN* module complements part of the Library module dedicated to VPN profiles, normally based on the NetworkExtension framework for iOS and macOS.
Today, it offers the `PIATunnelProfile` bridge to integrate [TunnelKit]( into the library. In the pre-bootstrap code, do something like:
let packetTunnelBundle = "com.example.MyApp.MyTunnel"
let group = ""
let ca = OpenVPN.CryptoContainer(pem: """
var sessionBuilder = OpenVPN.ConfigurationBuilder()
sessionBuilder.cipher = .aes128gcm
sessionBuilder.digest = .sha1
var builder = OpenVPNTunnelProvider.ConfigurationBuilder(sessionConfiguration:
builder.mtu = 1350
PIATunnelProfile(bundleIdentifier: packetTunnelBundle)
Client.preferences.defaults.vpnCustomConfigurations = [
to enable it as a VPN type in `Client.preferences.vpnType`.
### Mock
With mock providers, you can simulate library behavior without actually touching real business. For example, you might want to test login code in your app without submitting credentials to the PIA web services.
Each area of the library has its mock counterpart:
- `MockAccountProvider`
- `MockServerProvider`
- `MockVPNProvider`
- `MockInAppProvider` (internal)
After configuration, put your mock provider into the proper field of `Client.providers` before bootstrap. For example:
let mock = MockAccountProvider()
mock.mockPlan = .trial
mock.mockIsExpiring = true
mock.mockIsRenewable = true
Client.providers.accountProvider = mock
All providers have [shortcuts](/PIALibrary/Sources/Mock/Client+Mock.swift) in `Client`, so you can do more concisely:
which for in-app mocking is actually the only way, being it non-customizable:
### UI
Most of this module makes more sense for use in our own apps. The module is almost iOS only and includes:
- Useful macros
- Some custom views and view controllers
- Form validation
- Theming support
- Welcome view controllers
The `Theme` class helps the consumer app comply with a set of styles. Rather than explicitly setting colors and fonts, we centralize the typography definition in a `Theme.Palette` (colors) and a `Theme.Typeface` (fonts), to later use `Theme` methods to apply symbolic styles.
In such a setup, the use of `AutolayoutViewController` allows dynamic theme changes across the whole app.
`PIAWelcomeViewController` is a quick user interface to support login and signup to the PIA services in an app.
### Util
Generic utility classes and extensions.
## Known issues
### macOS support
There is some overlooked difference between the iOS and macOS keychain that breaks the loading of the PIA public key, needed for servers verification.
## Contributing
By contributing to this project you are agreeing to the terms stated in the Contributor License Agreement (CLA) [here](/CLA.rst).
For more details please see [CONTRIBUTING](/
Issues and Pull Requests should use these templates: [ISSUE](/.github/ and [PULL REQUEST](/.github/
## Authors
- Jose Blaya - [ueshiba](
- Davide De Rosa
## License
This project is licensed under the [MIT (Expat) license](, which can be found [here](/LICENSE).
## Acknowledgements
- SwiftyBeaver - © 2015 Sebastian Kreutzberger
- Gloss - © 2017 Harlan Kellaway
- Alamofire - © 2014-2018 Alamofire Software Foundation (
- ReachabilitySwift - © 2016 Ashley Mills
- TunnelKit - © 2018 - Present Davide de Rosa ( - TunnelKit is not MIT software and remains under the terms of the GPL license (
This is a fork of PIA [client-library-apple]( customized for [Librem Tunnel]( iOS app and [Librem One]( services.
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