I have an app that gets opened from another app via a URL scheme. The URL contains signup tokens. As any app can register the same URL scheme as my app, I am concerned a "fake" app can do a man-in-the-middle attack and capture the signup tokens.
My idea is to check that the URL scheme does not open another app when my app is first opened.
From a security perspective, if the URL scheme opens my app the first time, will it always open my app in the future?
How about using iOS 9 universal links?
Unlike custom URL schemes, universal links can’t be claimed by other apps, because they use standard HTTP or HTTPS links to your website.
https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/AppSearch/UniversalLinks.html
This way the "dispatch table" is on your server, so no other app can hijack the signup URL. (URL dispatch is based on AppIDs)
It's a valid (and usually ignored) attack vector. It isn't strictly a man-in-the-middle attack as it won't forward the URL on to your app (it can't). It's almost worse as the attacking app would only really be able to crash and it would look like your app had...
Another app could be installed any time your app is in the background. Technically it's possible that an update is released and installed for an existing app while your app is running (it's hard to know if that happens). So, it isn't safe to only test when your app is first opened.
Related
I am working on project where I have been implementing deep linking from app/browser to my app. I have everything setup and it has been working as expected.
But recently, there is changed to the other app where there is new url introduced, which is launching in the browser and that url has changed to exiting url. But it is not launching my app. How to implement and launch my app with that change?
Example
--> deep link url, https://www.externalApp.com/requestPage=homePage&id=4444
--> When user tap on button on the external app, the above URL is invoke and launch the my app.
After change
--> Now new url, http://www.externalApp.com/request=sometoken
--> when user tap on button, http://www.externalApp.com/request=sometoken invoke and open browser and then become https://www.externalApp.com/requestPage=homePage&id=4444 in the browser. But it is staying in the browser and not opening my app.
Expectation is to launch app after url become https://www.externalApp.com/requestPage=homePage&id=4444.
Please help and advise.
A URL redirect will not trigger your app deeplink under any circumstance.
The ideal way to do this would be for your app to handle the URL http://www.externalApp.com/request=sometoken and convert it into https://www.externalApp.com/requestPage=homePage&id=4444 using whatever logic you are currently executing server-side (or on the webpage).
If this is not possible in any way, then the discussion goes into the direction of ugly hacks where you try to trigger the deeplink using Javscript, which can fail (since you cannot guarantee that the deeplinked app is present on the device). I would not delve into those pathways here and recommend you re-think your solution.
Please note that I do not mean to disparage or deride your implementation in any way. You may have a valid use-case where such a flow is required. But with how universal links work on iOS, the above is my recommendation based on my experience as a developer.
There are 2 Apps in my case say App A and App B.
I want to use universal link to open App B from App A and do some authentication work. I will be sending some result from App B to App A after it completes authentication via App A universal link.
But the use case I am troubled about is I do not want any other app to open App B.
If my HTTPS universal linking URL gets exposed, I know that universal links can not work directly from browser but someone can create malicious app and can try to open the universal link from malicious app.
Is there any solution to that? Like restricting what apps can open App B via universal linking?
Please correct me if my understanding is wrong.
The developer of a malicious app cannot intercept ANY link they want, that's what your apple-app-site-assotiation is for. The connection between the app and the site works both way:
In your app you need to put a domain to your website.
Under <your_domain>/.well-known/apple-app-site-assotiation you've got to put appID and only the app with that specific appID will be eligible to handle URLs to of this domain.
Hope it answers your question.
I have Universal Linking setup in my app.
Now when browsing my website in Safari and visiting a UL registered link, it opens in safari and asks me if I want to open in my App.
Is there a way that it always opens in the app? No prompt to open in app, just open when it is installed, else continue in safari.
There are two different issues here:
1. In Safari, the URL of a Universal Link needs to be on a different domain/subdomain than the page on which it appears
Apple is very conservative with where Universal Links are allowed to work. One of the limitations in Safari is not allowing the app to open if the user is already browsing the same site (this sort of pages sense — if the user made the effort to open a site in Safari instead of the app, it could be annoying if every single link on that site tried to open the app, especially if the app isn't properly configured for deep link routing).
The workaround is to use a separate domain/subdomain for links you want to open the app. For example, if your site is on example.com, point any link you want to open the app to link.example.com and then redirect users without the app back to the main website or onward to the App Store. This is actually the system we built at Branch.io (which you could consider using instead of re-building it yourself!)
2. What you have described is not Universal Links behavior
Universal Links do not ask the user for confirmation before opening the app, even the first time. They always open the app immediately without even requesting the web page, until/unless the user explicitly disables them (which is actually rather easy to do). What you're describing is the behavior of custom URI schemes, so I suspect you may have a some sort of automatic redirect to the app's URI scheme on the page the Universal Link points to. This is actually not the best idea in most cases, since users without the app will see a nasty error message.
I will to check if another iOS application installed on a device handles a URL scheme. I can easily do that with the canOpenURL(_:).
The catch is my app also implements the same URL scheme but I only want my application to handle calls to the URL if no other application on the device handles it.
As you might've noticed, Apple values its users' privacy with utmost priority. Similarly, it also values its developers. Your task at hand at hand requires accessing the code of another application — which (un)fortunately is not possible.
Let's say I have a web app that calls out to a native app via a custom URL scheme, and after the native app has done its thing it returns to my web app by opening a callback URL.
This all works fine when my web app is running in Safari. But what happens if a user saves the web app to the home screen (creating a "Web Clip")? In that case it runs in a separate process from regular safari, and has separate cookies and cache.
So when the native app tries to return to the web app, the URL will presumably get opened by Safari, not by the Web Clip, and the session will be lost. (And not just the session -- all the page state, which in a rich Javascript-based web app can be a lot of stuff with non-trivial startup time.)
Is this assumption correct? And if so, is there any way around it? Is there some way to get iOS to try to open the URL with a web clip if installed?
In order to have something launch via a custom url scheme on iOS, you must have an application register this information via the Info.plist built into the app.
It is not possible to have a webapp/webclip register this information system-level.
So, to answer your main question, you cannot do this.
Here is the information on implementing custom URL schemes in native applications.