Content posted here with the permission of the author Amit Dhadse, who is currently employed at Josh Software. Original post available here.
iOS devices became widely used in an enterprise level daily-work now a days, due to this we need to have guaranteed secure communications between device and associated enterprise services.
So question raise about enterprise environment security which can be covered with the help of VPN or any other third party tool. Actually what VPN does is creating secure tunnel between identity device and service which is hosted on cloud or on partner networks.
Thats one part of accessing enterprise service but what if we don’t want to use any VPN client and still wants to access enterprise service from any device in our case we are taking iOS device.One way of doing that is using digital certificates to encrypt/decrypt, sign and authenticate communications and data.So how we can use certificate on iOS device at system level so that iOS can use that certificate while consuming services. Advantage of this over VPN is, User has login every time on VPN Client to consume services where as deploying certificate on iOS device is one time activity and it will work all along till User removed certificate.
I have been asked to create an iOS app to request and deploy digital certificates in device system keychain so that, it will be recognised by all system apps of iOS while accessing enterprise services. After doing my research I concluded that in iOS devices there are two types of certificate keychain stores:
- App certificates keychain store:
- This keychain store embedded in app space and can be used by that app only.(Not exposed at system level)
- Apple offer APIs to Insert/Delete/Update certificate
- System certificate keychain store:
- This keychain is exposed at system level. This store located in Setting -> General -> Profiles used for VPN and wifi networks
- Apple does not offer any API to deploy/retrieve certificates from the system certificate keychain store (Profiles).
So there are four ways to deploy certificates to system certificate keychain store (not programmatically):
- Configuration Profiles: Pre-configured profiles that used to distribute settings.(These can be created on MAC and deploy in iOS device)
- Using Simple Certificate Enrolment Protocol (SCEP): this protocol enables Over-the-Air Enrolment of digital certificates, mainly used for routers and switches.
- Email Attachment: send the certificate from a desktop or mac to iOS device as an email attachment. Open this attachment(certificate) in iOS mail client ( having system privileges ). It will automatically ask you for installation.
- Using Safari: browse the certificate using Safari. Safari has system privileges over normal UIWebView.
After I did my research I found a workaround that worked for me to deploy a certificate to the System Certificate Store from Xcode directly.
Here’s what you will need to do, first, to create a web-server inside your App, then save the certificate in this web-server and open it’s URL.
When the page launches, Safari will recognize that it’s a certificate, then the System Profiles will pop up and ask the user to install the certificate. After the user install the certificate it will be saved to the Profiles and the certificate can be used in the System level.
To create web server inside iOS app, there are 2-3 libraries are available on Git. I recommend “GCDWebserver” library to create web server due to its easy implementation, background support and most important it is stable.
How to use GCDWebserver :-
let localServer = GCDWebDAVServer(uploadDirectory: path) localServer?.start(withPort: 8080, bonjourName: nil) let url = localServer?.serverURL UIApplication.shared.open(url)
- Here “path” is your certificate path(in my case it was document directory path as my certificate was store in document directory(NSDocumentDirectory) folder).
- “serverURL” will return URL of certificate which is hosted on local server.
- Open this URL on safari, Safari recognise that it is certificate and pops an installation alert automatically.
Note :- Now in this scenario here is one problem, as soon as user open URL in safari, user were no longer in app all control is shift to safari and to comeback in app, user has to do manually.
Solution :- import “SafariServices” framework which already have a safari view in it which opens safari inside your app.
I spent a lot of time and research efforts to reach upto this solution, I hope someone surly will get benefit from my results. Please contact me for any question.