Programmatically logging in to website with saved username and password - objective-c

One of the functions of an app I am making involves logging the user into our Campus Portal website. For ease of use, the user may enter a username and password into the app once, and it will be saved for all future log-ins. When the user clicks a button, the information will automatically be sent to log in, and the website will be displayed in a UIWebView.
Let us say that the username and password are each stored in an NSString. How can I use this data to log in to this website programmatically and display the page it in a UIWebView?
I know little about posting and forms, so any help is appreciated.
Would something like this Stackoverflow answer help?
Here's the shell of my code for this
- (IBAction)btnGo:(id)sender {
username = usernameField.text;
password = passwordField.text;
if (saveSwitch.isOn) {
//Save data if the user wants
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
usernameSaved = username;
passwordSaved = password;
[appDelegate.listOfPortalCredentials replaceObjectAtIndex:0 withObject:usernameSaved];
[appDelegate.listOfPortalCredentials replaceObjectAtIndex:1 withObject:passwordSaved];
}
//Insert username and password to web form, log in to portal
//This is where I need help
}
Edit:
Thanks to Karthik I was able to find the HTTP Post using Firebug. It gave me:
appName=ridgefield&portalUrl=portal%2Fridgefield.jsp%3F%26rID%3D0.18423783694092&username=<username>&password=<password>&B1=Log+In&url=portal%2Fmain.xsl%3FrID%3D0.6845596700302482&lang=en
where and represent the real username and password. I believe this is what I need. Using this, how can I display the logged-in page in a UIWebView? Do I just need to load the above URL in the UIWebView?

Use UIWebView, and do a http POST to https://ic.ridgefield.org/campus/verify.jsp with username and password.
To understand how it works, install Firebug on Firefox browser and go to 'Net' tab on firebug, and then open your website and enter some username/password.
You should mimic that action using code. (I always get invalid username or password response from server, coz i dont have an account and i try some random ones, and since there is no signup on the site, there is no way for me to verify this)
UIWebView* webView = [[UIWebView alloc] initWithFrame:self.view.frame];
[self.view addSubview:webView];
NSString* username = #"";
NSString* password = #"";
NSURL* url = [NSURL URLWithString:#"https://ic.ridgefield.org/campus/verify.jsp"];
NSString* body = [NSString stringWithFormat:#"appName=ridgefield&username=%#&password=%#", username, password];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:30];
request.HTTPMethod = #"POST";
request.HTTPBody = [body dataUsingEncoding:NSStringEncodingConversionAllowLossy];
[webView loadRequest:request];

Related

Open OneNote from my Ipad Application - Need OneNote URL SCHEME?

When I use onenote:// for opening OneNote from my ipad Application, it opens OneNote but gives an error message that says
Cannot Open Link" There’s a problem with this link in One Note.
This is my Code
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"onenote://"]];
PS: OneNote for Ipad already has to be installed in the Ipad Device before trying this.
Is this the right URL SCHEME for OneNote - onenote://
Or am I doing it wrong.
The Error Message does note create a problem when closed, but I just want to get rid of the Error Message.
Also can parameters be passed to OneNote from my Application.
Help Appreciated!!
Using "onenote-cmd://" should open up OneNote without any errors.
The reason you're getting an error is that the iOS OneNote client doesn't support being launched by a protocol handler without having parameters completed for notebook, section, and page (it doesn't know where to navigate to).If you're just using onenote:// without specifying a destination, it's "by design" that you will receive an error.
We recommend you link to a specific page when opening OneNote from your application to avoid the error. The OneNote REST API returns a link to the page you've created when Creating a Page, and you can also retrieve a link using the "Copy Link to Page" function from within the iOS app.
As Nick pointed out, the OneNote app needs additional parameters to open successfully, without showing the "Cannot Open Link" alert. Here is what I did to solve the problem:
Note: In my app, the user is already logged in using the LiveSDK (Microsoft Account Login) so I have their Access Token saved.
I created an "Authorize OneNote" method that sends a request to the OneNote API to create a "Page" in the User's default notebook:
(void)AuthorizeOneNote
{
NSString *date = [NSString stringWithFormat:#"%#", [NSDate date]];
NSString *simpleHtml = [NSString stringWithFormat:
#"<html>"
"<head>"
"<title>\"%#\"</title>"
"<meta name=\"created\" content=\"%#\" />"
"</head>"
"<body>"
"<p></p>"
"</body>"
"</html>", #"Page Title", date];
NSData *presentation = [simpleHtml dataUsingEncoding:NSUTF8StringEncoding];
NSString *endpointToRequest = #"https://www.onenote.com/api/v1.0/pages";
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:endpointToRequest]];
request.HTTPMethod = #"POST";
request.HTTPBody = presentation;
[request addValue:#"text/html" forHTTPHeaderField:#"Content-Type"];
[request setValue:[#"Bearer " stringByAppendingString:#"LIVE-ID-ACCESS-TOKEN"] forHTTPHeaderField:#"Authorization"];
objConnectionOneNote = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}
This is how I handle the response:
(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if (connection == objConnectionOneNote)
{
NSString *strData = [[NSString alloc]initWithData:objData encoding:NSUTF8StringEncoding];
NSMutableDictionary *dictData1 = [[NSMutableDictionary alloc] init];
dictData1 = [NSJSONSerialization JSONObjectWithData:objData options:kNilOptions error:nil];
oneNoteClientUrl = [dictData1 valueForKeyPath:#"links.oneNoteClientUrl.href"];
NSLog(#"Response: %#",oneNoteClientUrl);
NSLog(#"Response: %#",strData);
// Launch OneNote Client
if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:#"onenote://"]])
{
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:oneNoteClientUrl]];
}
else
{
[[UIApplication sharedApplication] openURL: [NSURL URLWithString:#"https://itunes.apple.com/us/app/microsoft-onenote-for-iphone/id410395246?mt=8&uo=4"]];
}
}
There are couple things to note here:
This will create a new page every single time OneNote is launched from the app. In order to open the same page, you can persist the returned URL and use that to Open the client.
The Access Token from the MS Live Authentication expires in about an hour. When this happens, the OneNote API request returns a 401 Unauthorized response. To mitigate this, you can refresh the Access Token using the refresh token, which is also returned during Live Authentication.
Hope it helps!
With the addition of new automation app Workflow for iOS I'm extremely interested in figuring out how to incorporate OneNote into my actions.
I'm not looking to make an app and thus far I cannot find any examples for advanced url schemes for OneNote so the ability to grab a link that would open the OneNote app on either iPhone or iPad and have it go to the correct notebook and page would be great.
Ideally we could use a url scheme which OneNote:// works but need additional parameters for which notebook and page and how to create either a new notebook or page with that.
Workflow goes above and beyond what IFTTT can do (situation depending) and really looking forward to starting to use OneNote more due to automation possibilities.

Sending data to a webpage that is not mine

Is it possible to have a viewController in an iOS app with some textboxes where the user inputs some strings and then with a button sends it to a webpage which is NOT mine? Here is an example of a webpage (http://www.nattklubbvictoria.se/#/list) with some choices, text boxes and a Send button. The websites is using some sort of widget. If it is possible, how?
Currently I have a uiweview but it's not so good looking and it's slow to load it. So it would be awesome if I could do this!
You could do something as simple as construct a GET URL & forward the user to that URL when the user clicks the button.
For example (not tested):
NSString *stringToSendUserTo = #"http://www.site.com/form.php?foreignParameterA=";
stringToSendUserTo = [stringToSendUserTo stringByAppendingString:firstTextField.text];
stringToSendUserTo = [stringToSendUserTo stringByAppendingString:#"&foreignParameterB="];
stringToSendUserTo = [stringToSendUserTo stringByAppendingString:secondTextField.text];
stringToSendUserTo = [stringToSendUserTo stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *URLToSendUserTo = [NSURL URLWithString:stringToSendUserTo];
if ([[UIApplication sharedApplication] canOpenURL:URLToSendUserTo]) {
[[UIApplication sharedApplication] openURL:URLToSendUserTo];
} else {
// do something
}

How to clear username and password on CocoaLibSpotify logout?

I'm using the CocoaLibSpotify library to develop an iOS application that will utilize the Spotify API. I've got it just about where I want it, but I've run into a bit of a problem.
When the user touches my "Logout of Spotify" button, I execute the following code:
-(IBAction)logoutButtonTouched:(id)sender
{
// Clear out the user's settings that I am saving.
NSString *appDomain = [[NSBundle mainBundle] bundleIdentifier];
[[NSUserDefaults standardUserDefaults] removePersistentDomainForName:appDomain];
[[SPSession sharedSession] logout:^(void) {
SPLoginViewController *controller = [SPLoginViewController loginControllerForSession:[SPSession sharedSession]];
controller.allowsCancel = NO;
}];
}
This does indeed logout the user and display the SPLoginViewController, but my problem is, the username and password field still contain the values that they'd logged-in with. Does anyone know of a way to clear these fields when I display the SPLoginViewController?
This functionality isn't in the login controller, which is indeed a bug.
You can do it like this. Please note that this is really fragile code and will fail if any internal detail of the login controller changes, and it will in the future:
SPLoginViewController *controller = [SPLoginViewController loginControllerForSession:[SPSession sharedSession]];
id internalLoginViewController = [controller.viewControllers objectAtIndex:0];
UITextField *loginField = [internalLoginViewController valueForKey:#"usernameField"];
UITextField *passwordField = [internalLoginViewController valueForKey:#"passwordField"];
loginField.text = #"";
passwordField.text = #"";

UIWebView, enter a password

I want to enter a password in a webpage I load in an UIWebView. The password is a string, and I want to enter the password and hit a button in the page, automatically when the View loads.
Any help?
If you're using a UIWebView, I assume you're loading some web service into that WebView. Why not build your login system into the web service? You could even just use HTTP Basic Auth.
If you're managing the passwords within your cocoa app, then I would probably implement a UIAlertView with a UITextField asking for the password. When the user presses Login you can validate the password and then load your web service in your UIWebView.
If you're managing the passwords in a database on the website then you'd build an html/js/php/mysql login form and load it in the UIWebView first.
Update
I'd go with the first option and display your own login form using cocoa controls like the UIAlertView with 2 UITextFields. You can then save the username and password using the keychain services and submit them every time the users launches the app or the web session expires.
If you want to try this method I'd suggest having a look at the ASIHTTPRequest framework. In particular ASIFormDataRequest which let's you easily send a form with the correct fields.
- (void)login
{
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
// Change these values to the ones in NSUserDefaults and the KeyChain
[request setPostValue:#"Joe" forKey:#"username"];
[request setPostValue:#"Secret" forKey:#"password"];
[request setDelegate:self];
[request startAsynchronous];
}
- (void)requestFinished:(ASIHTTPRequest *)request
{
// Use when fetching text data
NSString *responseString = [request responseString];
// Use when fetching binary data.
NSData *responseData = [request responseData];
}
- (void)requestFailed:(ASIHTTPRequest *)request
{
NSError *error = [request error];
}
Just an idea : you could try to add some javascript to the page before displaying it in the webview and use the ONLOAD event to fill the password field and post the form.
To do so you have 2 solutions :
Use the stringByEvaluatingJavaScriptFromString instance method of UIWebView , you could evaluate your javascript in the webViewDidFinishLoad delegate method for example. You will find an example here : http://iphoneincubator.com/blog/windows-views/how-to-inject-javascript-functions-into-a-uiwebview
Or if for some reason you can't use this solution in your context you can always download the HTML using NSURLConnection, and then edit the string to insert your javascript. Then load the WebView using loadHTMLString:baseURL:

Objective C - Webkit external files causing 401

I'm currently using Webkit to display a mobile web on my iPhone app.
The domain is password protected, so I pass the username & password to the request.
It loads the main HTML page fine, however, even after passing the username & password, any other pages that the main HTML page loads (i.e css and js) are all returning 401.
Is there a way around that?
Thanks,
Tee
This is one of the use cases for ASIWebPageRequest.
If you want something lower level, you'll have to create an NSURLCredential instance and an NSURLProtectionSpace and save them to the credential store. At this point, the UIWebView should use the credential for all requests that match the protection space (which basically represents your site).
Here's some sample code, taken from here, which is not really where I'd expect to find it.
NSURLCredential *credential = [[NSURLCredential alloc]
initWithUser: #"userName"
password: #"password"
persistence: NSURLCredentialPersistenceForSession];
NSURLProtectionSpace *protectionSpace = [[NSURLProtectionSpace alloc]
initWithHost: #"www.mydomain.com"
port: 80
protocol: #"http"
realm: #"mydomain.com"
authenticationMethod: NSURLAuthenticationMethodDefault];
[[NSURLCredentialStorage sharedCredentialStorage]
setDefaultCredential: credential
forProtectionSpace: protectionSpace];
[credential release];
[protectionSpace release];
i think you need to pass the username and password in the css and js includes also...