My app has an embedded WKWebView that we use to show custom user content served from the users organization. A few organizations are using HTTP authentication (NTLM) so I am working on supporting this. I've implemented the necessary delegate function (webView didReceive: completionHandler:) and create a UIAlertController with two text fields to allow the user to input their username and password. Functionally, this works and allows the users to log in to their organizations site.
However, because I'm creating the alert controller in my app, usernames and passwords are saved and suggested using the apps associated domain. While technically this makes sense, it is confusing for our users to be logging in to their website but seeing a password suggestion coming from our domain.
I haven't found any way to get the WKWebView to display its own username and password prompt. I've considered trying to inject some javascript to show the prompt, but I'm far from a javascript expert and I'm concerned about causing issues with existing javascript on our customers sites (and I don't know if it will still use the app domain anyway). Edit - tested this, the app domain is still used.
https://developer.apple.com/documentation/security/password_autofill/ seems to say that there's no way to use a different url.
Is there anyway for the username and password to be saved using the url that is being loaded in the web view instead of the apps associated domain?
Related
I want to open, from an iOS app, a web page that requires authentication in order to get to that page.
I googled a little bit and I believe I need to use WebKit and Javascript injection, but I am not sure and I have never done something like this, so every bit of information is welcomed or pointing me in the right direction.
I will give an example that I hope will make things more clear(I don't actually want to open facebook, it's just part of the example):
Is it possible to do the following scenario? And if yes, how?
Open a web page from an iOS app, for example: "https://www.facebook.com/profile" without having to go through the login page? I do have the user credentials(username and password), as the user is already logged in with those credentials in the iOS app, but the requirement is to not go through the login page, but to go straight to the profile page.
In general the answer is: no. Even if the user is already logged in and has a valid authentication token that token may only be valid from within your app and not from within the browser. And the login form may be protected by something like a captche preventing you from automatically logging someone in.
There certainly are situation where it is possible: For example if the tokens are not scoped to your app you can try passing them along. Or there is an actual API that you can call with the token that logs the user into the website on the website, etc. But those depend on the specific target website or wether you can control that target website and can add this functionality.
I am writing a Reddit client that uses OAuth to authenticate the user. One of the features I would like to implement is the ability to use multiple accounts simultaneously. This requires the user to authorize my client on each account they want to use. The problem I'm running into is that if the user is already logged into Reddit in their browser, when I pop a browser to perform the auth, it will have them authenticate my client against their currently logged in user.
Is there a way to force the user to re-enter their credentials? I would rather not have to put some kind of disclaimer on my Add Account screen that says "Please log out of Reddit in any open browser windows".
I tried opening the Reddit login page in a WebView so the request is sandboxed, and while that worked, it gives the user access to the entire login page (including all the links that navigate to elsewhere on the site). I don't mind that experience when I'm popping an external browser, but in an embedded WebView I really just want to present a username and password box along with the OAuth validation prompt.
Note: I do kind of prefer the embedded experience because it doesn't interfere with the users existing browser cookies, I just don't like how cluttered the login page is this way and I'm not sure how to prevent the user from navigating away from login. Also, for completeness, this is a UWP app, though this problem is largely technology independent.
The problem I'm running into is that if the user is already logged into Reddit in their browser, when I pop a browser to perform the auth, it will have them authenticate my client against their currently logged in user.
It may be caused by the authorization server. If so, we can not do anything in our client app.
But if it is not the server issue, in UWP, there is a WebAuthenticationBroker class witch can help you to authorize your app to access the user info from Resource server by getting a token. You can try to use the class to implement OAuth authorization. You don't need to use the in a WebView so that you can authorize your app with multiple users if you can manage all the user with the token properly in your code logic.
See the Web authentication broker topic and the sample to learn more details.
I have an upload application that will be accessible by multiple other applications. I want user security from those applications to be federated to this upload hub. I'm doing it with HTTP tokens that are shared between the applications.
I have read 5 different articles on how to secure an API in Rails. I have everything set up properly in the upload hub app. I have keys set up in my User table, and I have shared this key with the user table in the other apps. I have the code in place to check for this key, and to locate the appropriate subscription. Upon failure, the user is redirected to the login page of the source application.
There's just one thing. I can't find anywhere how to create the actual request! I want the users in the other applications to click an "upload" link that will take them to this application. No problem creating the link, of course. The problem is, how do I add the token to the request?
See, I'm not making programmatic requests to an API... The user is actually going from one app to another. I want the upload hub app to check the request and say "Oh, there's this big long key. Let me see if I can find a user associated with that. I'm obviously not going to put it in a query string.
The only thing I've come up with on my own is to have a bit of jQuery code that constructs a form with a hidden item containing the key in it, which it would get from a hidden field on the current page, then do a POST against the upload hub app. That's not really a token, but it's doable. Surely there's a better way?
UPDATE
I went the jQuery "postGo" route where I construct a form with a hidden field and send it as a parameter to the other app. I had forgotten about protect_from_forgery though. However, even after turning protect_from_forgery off, Rails somehow still strips all parameters except for controller and action from outside requests. Undocumented feature? Or maybe I missed the documentation.
Really, I just want SSO on a couple of apps. It looks like I'm going to have to create an Oath provider. Sure are a lot of hoops to jump through to federate a simple session on some apps that I own.
Here's a possible way of doing this.
In the upload controller method of the app, instead of redirecting the user directly, make a request to the upload hub app.
In the upload hub app, add a controller method and generate a token, store it and a user's credential in redis, or other storage of your choice, then response the app with the token.
Your app's upload controller method receive the response from upload hub, then give 302 response back to the client, with the token included in the redirect url.
The client redirects to the upload hub
The upload hub router accepts this format, the token can be in a query string.
Check in redis and find it by the token and match the user's credential
The Scenario:
A web application that once a new user completes the registration, an email will be sent, containing a URL that once tapped from within an iOS device, the iOS app will be launched. This scenario is a classic scenario to make users use the mobile app.
While implementing it (using URL scheme), we start wondering how secured is this method? Theoretically - a malicious app could sign up to the same URL scheme, and according to Apple:
Note: If more than one third-party app registers to handle the same URL scheme, there is currently no process for determining which app will be given that scheme.
Implementing Custom URL Schemes by Apple
In such scenario, if a user is tapping the url inside the email, it is unknown which of the two (or more apps) will be launched - ours or the malicious one. Lets say a different app is being launched - if its really malicious, theoretically it could mimic the login page of our app and grab the user's credentials.
Are there any best practices that handles such scenario? I've read many articles regarding the issue, all of them claims that the only solution is to wait for Apple to make these url schemes unique.
example1,
example2
I would love hearing about any solution to the issue if exist,
Thanks in advance!
We have to assume the malicious app can intercept any data included in this url and that it's author has been free to reverse engineer any behavior included in your app so it can imitate your UI and any validation your app attempts to perform. However we can also assume that the malicious app is contained in its own sandbox so your app can communicate with your backend privately. The malicious app can imitate any such communication but this does allow us to construct a secret unknown to the malicious app. That gives us at least an opportunity to design some countermeasures.
One option might be:
As part of registration construct a public/private key pair and store it in your app.
Send the public key to your web backend as part of the registration process.
Encode they payload of your URL using that public key.
Now we've sent data to your app which might be redirected to a malicious app but which the malicious app cannot read. That's a partial solution. We still need to be careful to design a UI which does not encourage a user to fall for a phishing attack since the URL might still launch the imposter.
The encoded data might be a token we can use to authenticate the user and therefore never require them to re-authenticate within the app. Then there is no login screen to imitate (though a clever forgery might still be enough to trick users into divulging their credentials).
An alternative might be to use a similar per-user secret stored on the client as a salt to combine with the user's password. Their password alone might then be insufficient to authenticate so a malicious app capturing their credentials is not immediately able to access their account.
Another design could be to allow the user to customize their experience in a recognizable way. You might show their selected profile image on the sign in screen. If that selection is known only to your app then an imitator shouldn't be able to duplicate it reliably (again, no guarantee that means users will catch the deception).
All of this introduces tradeoffs; users might still be tricked into revealing information to malicious apps no matter how different they appear from your legitimate client, client side secrets can be extracted by other attacks, and you need a plan to support users who switch, lose, or upgrade devices. You have to decide if any of this actually improves the security of your users and if it is worth the cost to implement.
Try something like this:
In your email, state that clicking on the URL will launch the app and log you in for the first time then prompt user to enter their new password. Include a token in the URL which, when handled by your app, does a one-off login and put the user on a "New Password" page.
If a malicious app has also registered your custom URL and steals the link, they should (hopefully) not be able to do much with it. Even if they replicate your interface and prompt the user for a new password, it's not going to achieve anything.
edit: After thinking on this further, as long as you have an active attacker, you're pretty much screwed. The attacker could continue to emulate your app, effectively MITMing you, regardless of what you do, as long as they're able to hijack that initial URL. My solution would only work in the most basic of cases, not really reliable.
I am working on an iOS app in Monotouch. Part of it is to connect to an exchange server and download a list of emails. I would like to include the ability to open the email in the OWA client as well (so I don't have to recreate a email client to provide features OWA gives me for free).
I don't want the user to have to input credentials again however. Opening OWA in safari would usually present the user with either a form or a pop up asking for username and password.
Say I have a user admin with password password1. Currently what I do is request safari to open a link in the following form:
https://admin:password1#mailserver/exchange
This passes the credentials to safari and bypasses the HTTP basic authentication that OWA would usually pop up, however it is not very safe and safari complains of a possible phishing attack.
What other options are there for performing this kind of bypass of HTTP basic authentication?
I would recommend using HttpWebRequest to download each page and set the UIWebView's text manually. Using HttpWebRequest gives you the flexibility to use whatever cookies, credentials, http headers, etc. you want.
This will be tricky, but probably the only way to safely get the credentials in there. Not sure if your OWA app will be able to handle it either.