APNS - Multiple Certificates in one file (dev and production) - ios

We are developing an iPhone application as well as an iPad application.
Both of them do have different Bundle Identifieres but should receive Push Notifications.
The certificates are generated like documented in apples programming guide.
So, due to the fact that we do have four ceriticates (APNS-Dev-iPhone, APNS-Prod-iPhone, APNS-Dev-iPad, APNS-Prod-iPad) I am wondering how to combine those certificates into one file?
The problem is, that on the backend side we are only storing the device token of a user. It is easy to decide whether we are working in development mode or not,but how should I decide which certificate to use - the ipad one or the iphone one?
Due to the fact, that we only have the device token, we do not know if the user is using the iPad application or the iPhone one, so we cannot assume which certificate to use when connecting to the apns apple server.
Any suggestions on how to handle this issue? Should we store more information - for example the device the user was sending the device token from? Or is there any easier way to combine all the certificates into one file and send it over to the apns apple server?
Thanks in advance, I would appreciate any help!

I have a similar issue and have not found a solution that I find satisfactory.
The way that we handle it is similar to what tGilani described. We have to store some kind of identifier that distinguishes which certificate to send a notification through for a particular device token.
Our issue goes further in that we might possibly have to send notifications to different applications altogether. These applications will probably be on a per tenant basis. Thus creating a universal application and one certificate will not work for us.
It would be terribly convenient if I could find a way to combine multiple p12 files into one jks and continue to use one of the Java PNS or Java APNS projects to send notifications.

Related

Storing API and App secrets within enterprise iOS app

I have a requirement to remove all API keys and app secrets from the source code of the app we are building. Ideally the keys and app secrets should be sent to the app out of band as a configuration file, through an MDM solution.
Is this possible, and if so how? If not, what is the recommended approach to store this kind of information, such that it cannot be viewed in the source or extracted from the binary?
EDIT: Update
It is possible to send NSUserDefaults to the app via the MDM solution using Managed App Configuration. However, NSUserDefaults is not secure, easily viewed and modified by a casual user.
My plan is to encrypt the NSUserDefaults to prevent this using the common crypto library included in iOS. Is this the best approach to this problem? Should I also be sending a certificate as part of the MDM config?
Any thoughts, comments, and recommendations appreciated before I go too far down this route.
I know it's been a while, but I recently looked into this (not for an MDM application). I don't have any experience with MDM and that may have another solution. The route I chose to go was using CloudKit. It's a 1st party solution, always available whether the user is logged in to iCloud or not and you communicate securely with Apple's servers and only your App can access these keys.
Also depending how you set it up you can easily rotate out keys.
See more info here

Dynamic certificate pinning

I have an iOS application that will be distributed to multiple customers, each using their own network infrastructure. I would like to add some certificate pinning capabilities, but I need to do it in a dynamic fashion since I cannot ship the app with the cert/pubkey bundled, as doing so would require a different build for each customer.
My idea is to query the per-client configured HTTPS server on app startup, get the certificate, potentially extract the public key and then pin it.
Is it possible to do this in Swift or Objective-C? I have not been able to find relevant code samples or documentation.
Operationally, it will be a lot easier to manage and recover from misconfigurations if you embed the certificates or keys in the App. If you just pin whatever certificate the server sent to the App the first time, you have no mechanism to support a new certificate once the current one expires or gets rotated. If that's still what you would like to do, I would recommend looking at the HPKP specification, which implements the same mechanism but for browsers: https://www.rfc-editor.org/rfc/rfc7469
Also, if the App servers are not directly under your control, there is a high change that pinning will end up bricking the App, if the server's certificate unexpectedly changes. Will the team building the App be informed about infrastructure/certificate changes on the App/customer servers, so they can release an update just in time? If not, you should not do it.
Its possible. I haven't tried myself, but I think you are looking for something like this.
https://github.com/wultra/ssl-pinning-ios

How to implement SSL mutual authentication in iOS where the client certificate is loaded remotely?

I am trying to implement SSL mutual authentication in an iOS app.
In most of the examples that I have seen, the client certificate is bundled with the application package. But in my case, I need to load the client certificate remotely (i.e, from a link or via email).
If I try to load a certificate from an external source (i.e, mail app), it navigates to settings app and install it to the apple's keychain. So this certificate is not accessible with my app.
So anyone please suggest an idea for this ?
I built a system like this in our internal iPad app.
Forget the System preferences, profiles, etc. All certificates installed in this way are inaccessible to third party apps but only to the system apps, probably because are installed into the Apple keychain.
I have explored these three methods to load the certificate and used the last one:
Bundle into the app, as you have already seen is impractical
Send a file from another app (e.g. email)
Use a link to download (what I did)
FOREWORD
I think you have built your simil-PKI, with a CA, an automatic/manual way to issue/revoke certificates, etc.
So the problem is the delivery to devices.
For all the solutions I suggest to save the private key and cert in PKCS #12 format with a strong password.
Use an MDM to manage the devices and if your app is internal and will be used with company's devices supervise them for added options
(e.g. Meraki, is free but do not handle the ManagedAppConfiguration)
SOLUTIONS
Solution 1)
Impractical because is very hard (to impossible) to generate different versions of the app with specific certificates. Not to mention that will be nearly impossible to handle the distribution of a specific version on every single device of the users.
Solution 2)
Save the .p12 file
change the file extension to a custom one
register that extension to open with your app, so in the "Open in..." will be listed your app
"Open in" for specific document type
The safest way should be that the user can select the password to encrypt the .p12 file so when the p12 will be opened the user must enter his password but this lead to other work to make it work.
A less safe but working method is to use a single strong password embedded in the app and use that for all .p12 files
Solution 3)
Similar to 2) but you download the file directly from a specific URI of your web application, this allow some automatic configuration because the app can identify himself.
Basically these are the steps:
the app connects to a specific URL of our application via HTTPS.
checks that the server certificate is correct (trusted origin).
send something to authenticate.
In our case I use the device name that I set up during device preparation and I can change it remotely using MDM.
download the configuration bundle with the certificate in it
I use a JSON payload to send the PKCS #12 file base64 encoded and other data to config the app.
If your MDM supports ManagedAppConfiguration you can change a bit these operations to build a more flexible behavior:
With ManagedAppConfiguration you can send a specific string inside every app NSUserDefaults remotely, so you can use a different or temporary URLs/tokens to download the config bundle and ditch completely the use of devices name for authentication.
WWDC 2014 #704 - Building Apps for Enterprise and Education ~13:00
Apple Developer - ManagedConfig Sample App
ADDED PARANOIA
log everything! Everything that this part of the app does (failed/wrong requests, not existent device names requests, etc)
the configuration URL is activated/deactivated only when we need to configure new devices.
You can done this a lot of ways, my webapp checks for the presence of a specific file so I can do something like touch APP_CERTIFICATES_CONFIG_ENABLED to activate the auto-configuration service and disable everything deleting the file.
Just to be sure that no certificate will go around without my supervision.

Push notifications issues: key,failed/message not reach

I'm still new to iOS dev.
And I'm very, very new to whole APNS idea. I followed many tutorials, and didn't go so well.
I'd like to ask some questions.
Can I use same .certSigningRequest file for dev/dist/apns certificates? Does it matter if some of this certificates from this .certSigningRequest have been revoked?
When I export my key in keychain to .p12 file, can I use this one for both dev/distribute version?
If my server open port 2195, by giving .pem generated from above cer, my server should be able to send push message, right?
How can I unsubscribe/unregister from my device and/or from server/apns service? I mean when I need to remove, and try to build&run the code again.
4.1 How does
[[UIApplication sharedApplication] unregisterForRemoteNotifications];
really work? Does it tell apns not to send message/just turn it off? How can my server/provider know if device need to unsubscribe?
I find this tutorial really useful: http://www.raywenderlich.com/32960/apple-push-notification-services-in-ios-6-tutorial-part-1
And here some questions I have about what I encountered.
1. The sample app from the tutorial worked fine, using both my laptop & my server to send a message. But after a few days, it doesn't. (the response is still 'Connected to APNS Message successfully delivered', but the message never reach my device)
What could be the cause? My friend have revoked a dev cert? (I shared acc. w/ my friends) Or I reinstall the app? I also tried method unregisterForRemoteNotifications & register again, but nothing happens.
2. I also tried https://apphq.shephertz.com for a provider. This one requires .p12 key file in their format. (link) I have another project (this one is unity) register apns thru the app. It seems fine since I can see device token & user store in the web. But when I tried to send message, I got an error, like
iOS KeystoreException Device ID : <my-device-token> : Invalid keystore password! Verify settings for connecting to Apple... Does anyone know what this mean?
Sorry for my poor English.

Can my iPhone app register to receive push notifications meant for another app?

This may be a pretty basic question, but here goes. I develop an iPhone app that is a third-party client for a popular webapp. This webapp has it's own iPhone app to which it publishes push notifications. Is it possible for my app to register to receive push notificatons Sent by the webapp and intended for the webapp's native iPhone app? Or is this prevented by certificate magic as I suspect?
Apple allow you to have apps with either a generic app ID in the format:
12345678.*
Or an explicit app ID in the format:
12345678.com.myCompanyName.myAppName
However, they only allow applications with explicit app IDs to register for APN (Apple Push Notification) Service. Therefore it is not possible for more than one specific iPhone app to receive the same notification.
As Farcaller says, this is not a technical limitation but an imposed one.
Hope that helps
From the technical point of view, you can register at another server with device token. You just need to know, where to register and what protocol does it use. Still you wouldn't be able to receive notifications, as they are routed depending on the application id, and you can't mimic that.

Resources