I have implemented a web-scraping iOS application for a service provider to get data usage information. This used to work fine using NSURLConnection to post the username and password to the site, and then scrape the response.
However, said service provider has recently upgraded their account website and the login step now also includes an account selection step. So you first provide a username and password, the response then includes a list of all your accounts. This is presented in a selectable list. Clicking an account causes another postback, the response is the data I want to scrape.
I am unsure how to programatically perform this second step, since no data is sent with the request, and no extra cookies are set. Each clickable account link causes a __dopostback javascript action, so it is all handled serverside. There seems no way for me to perform this postback using nsurlconnection as no data about which account was clicked is sent with the post.
Any ideas how I could get around this?
Related
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?
I am currently using implicit flow to link user's account for Google assistant use. The linking works perfectly, the user is redirected to my website to login, user logs in and is redirected to the following url with access_token generated by the website.
https://oauth-redirect.googleusercontent.com/r/YOUR_PROJECT_ID#access_token=ACCESS_TOKEN&token_type=bearer&state=STATE_STRING
Google.com page is now displayed, which I assume means account linking has been successful. The problem however is on subsequent calls the access_token sent to API.ai is different then the one I sent back as a URL parameter.
I am failing to understand why this is?
NOTE: I am testing on Google Home Web simulator
For starters, check to make sure the other parameters in the URL for the google.com page actually do indicate a success. They may show an error.
If you are repeatedly testing with the same user, you may need to remove permissions to your application in between each test. You can do this at https://myaccount.google.com/permissions.
Since tokens never expire with the Implicit Flow, it is possible that Google is using an old token and never accepting one of the new tokens you're issuing, but always using the original token you issued.
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
I'm using the LinkedIn API to authenticate users. After authentication LinkedIn posts data back to my app at /auth/linkedin/callback (as is the OAuth standard).
I also offer other auth methods (e.g. Google+, Twitter, etc..). If the user signs in with one of those, I want them to also be able to (on top of their existing auth) connect with LinkedIn to pull in additional data.
In those cases, I want the callback URL to be something different so I don't have to do some very custom if...then logic.
Is there a way to specify in an OAuth request where you want to call back to?
If #1 isn't possible, can I send some custom arbitrary data or flags with my initial request that are returned during the callback? That way when parsing the response I'll check those flags for the appropriate state of the User and redirect them as necessary.
Thanks!
The state parameter is guaranteed to be preserved across all interactions. You can store (encoded?) information in it, and when the final callback is called, you will get back the original value you sent.
A common use case is capturing the "end URL" for the user (like a deep link into your app that requires auth).
You are supposed to check that what you receive is exactly what you sent.
*Apologies in advance for the long background but I think it is necessary and helpful to other devs once this is answered.
Background
I am building a very social web-application in which there are several events that trigger social actions such as updating the user's Twitter status.
Currently, I use a library called "TweetMoaSharp" (.NET) to handle the Oauth workflows and events that trigger a status update or follow action work brilliantly as long as the user is briefly redirected to the Twitter authentication page.
To clarify, the user is not asked to re-authorize my app each time, but there is an unsightly flicker that lasts for 1-2 seconds while the user is directed to Twitter and then back to my app. This will annoy the end user as there are frequent Twitter interactions.
So--to relieve the situation, I use TweetMoaSharp to obtain an OAuth Access Token via the server and then store that token along with the user id returned from Twitter in my database. I then set a cookie on the client that contains the user's Twitter Id so that for future requests I can simply pass that ID to the server, grab the OAuth token form the database and do my business. No redirect required!
Problem Solved, Right?
Well, no. Stupidly, I overlooked the fact that this can cause a collision with multiple Twitter Accounts being used on the same page and ended up tweeting test-tweets to a second twitter account I own because I had changed Twitter sessions. This could happen to any user(s) who access multiple Twitter accounts from the same browser; a husband and wife for example.
Back to the Drawing Board
I thought to myself, "The Facebook JavaScript API" makes it super easy to get the id of the currently logged in user without going through a bunch of server-side token steps so I am sure Twitter offers the same approach." Ha! I haven't found one yet.
Bottom Line / Question
How do I get the ID of the currently authenticated Twitter user without redirecting them to Twitter (even for just a second)? If I can do this, then I can compare the returned ID to the one in my cookie and know if it is valid for my application's current session or if I need to have that (new) user authenticate as well so that I avoid "Tweeting" under the wrong account.
Thanks in advance.
Use your app tokens to do a verify credentials call
https://api.twitter.com/1.1/account/verify_credentials.json
The returned info is the logged in user.
Unfortunately limited to 15 calls per 15 minute window!