Disqus Password Credentials OAuth - ios

I'm trying to authenticate a user in my iOS app but all I get is a 400 error.
According to the documentation, "this type of flow is restricted to approved applications only, so you must request access first".
So how do I approve my application to be able to accomplish this flow?
Part of my request:
NSURL *url = [NSURL URLWithString:#"https://disqus.com/api/oauth/2.0/access_token/"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:WS_TIMEOUT];
NSString *strAuth = [NSString stringWithFormat:#"%#:%#", username, password];
NSString *strAuthBase64 = [[strAuth dataUsingEncoding:NSUTF8StringEncoding] base64EncodedString];
NSString *postString = [NSString stringWithFormat#"grant_type=password&client_secret=%#&client_id=%#&scope=read,write", DISQUS_SECRET, DISQUS_KEY];
[request addValue:[NSString stringWithFormat:#"Basic %#", strAuthBase64] forHTTPHeaderField:#"Authorization"];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:[postString dataUsingEncoding:NSUTF8StringEncoding]];
Thanks in advance.

This is something we'd have to enable for your application from our end. However, I'd instead recommend hosting a page to handle the authentication with the standard server-side flow. You can then pull the access token and other variables from the page into your application after the user has authorized.
The reason is so you don't have to deal with form validation, error messaging, and can take advantage of our updates to the form without touching your code.
Some server-side OAuth examples in PHP and Python can be found on this page: https://github.com/disqus/DISQUS-API-Recipes/tree/master/oauth

Try this library which solves Disqus authorization issue in a slick manner. Really nice solution https://github.com/moqod/disqus-ios

Related

Why do i get authenticationchallenge with NSURLRequest when switching to HTTPS?

I've used NSMutableURLRequest for a long time to connect to my server.
In order to avoid double roadtrips, i set the usr/pwd right away in the header, like this:
NSMutableURLRequest *request = [NSMutableURLRequest
requestWithURL:[NSURL URLWithString:url]
cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:HTTP_REQUEST_TIMEOUT];
NSString *authStr = [NSString stringWithFormat:#"%#:%#", inUsr, inPwd];
NSString *authValue = [NSString stringWithFormat:#"Basic %#", [[authStr dataUsingEncoding:NSISOLatin1StringEncoding] base64EncodedStringWithOptions:0]];
[request setValue:authValue forHTTPHeaderField:#"Authorization"];
This has worked fine, the "willSendRequestForAuthenticationChallenge" is never called unless there is some error, so that method has always looked like:
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
NSDictionary *errorInfo = ((NSHTTPURLResponse *) challenge.failureResponse).allHeaderFields;
NSError *error; = [NSError errorWithDomain:#"httprequesthandler" code:WRONG_CREDENTIALS userInfo:errorInfo];
[delegate finishedWithErrors:error];
Now however, i'm using the same URL's as always, only "https" instead of "http", and suddenly this method is called every time.
I want my request to work as per normal, i.e. populate basic header and only one request to the server.
I'm not sure what i'm missing, so pointers would be much appreciated!
Using https as your scheme (or protocol) requests the connection be made securely, both by encrypting the data that is transferred as well as offering some information to you about the authenticity of the server you are connecting to.
The delegate method being invoked here (connection:willSendRequestForAuthenticationChallenge:), is not related to you authenticating yourself with the server, but the server authenticating itself with you. If you dig into the challenge object (NSURLAuthenticationChallenge), you can find the credentials the server is offering to let you know that it is the server you were actually trying to connect to, instead of an impostor.
Normally you don't need to use this method unless you want to validate the server in a way that goes beyond what the OS is doing for already.

Authentication Issue with REST call for iOS

I am currently trying to make a REST call from an iOS device. My code is below
NSString *restCallString = [NSString stringWithFormat:#"MyURL"];
NSURL *url = [NSURL URLWithString:restCallString];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60];
[request setHTTPMethod:#"GET"];
[request addValue:Value1 forHTTPHeaderField:#"Header1"];
[request addValue:Value2 forHTTPHeaderField:#"Header2"];
[request setURL:[NSURL URLWithString:restCallString]];
#try{
_currentConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}
#catch(NSError *e){
NSLog(#"%#", e.description);
}
Whenever this is called, I get the following error: Authentication credentials were not provided. However, what confuses me is that if I send an identical GET request via a HTTP web console, it works perfectly. In other words, using the same URL and the same 2 header-value pairs, I get a valid response on a web console, and see no authentication errors. What could be causing this?
You are setting the HTTP headers. This won't work, because the HTTP header is not contained in $_GET or $_POST because they're are not content, but description of the content expected.
Try this instead:
NSURL *url = [NSURL URLWithString:[restCallString stringByAppendingFormat:#"?Header1=%#&Header2=%#", Value1, Value2]];
Of cause you have to be aware that the URL is RFC 1738 compliant.
if I send an identical GET request via a HTTP web console, it works perfectly
I suspect your web console is leveraging SessionAuthentication — i.e. If you're already logged in to your site in your browser the API will authenticate you based on your session cookie.
Django Rest Framework provides various authentication methods and there are third-party options too. The simplest to get going is probably the provided Token Auth method.
Make sure this is enabled. Create a token in the admin (or via the provided view) and make sure you've set the Authorization header. It needs to look like this:
Authorization: Token 9944b09199c62bcf9418ad846dd0e4bbdfc6ee4b
So your Objective-C will go something like:
[request addValue:[NSString stringWithFormat:#"Token %#", yourToken]
forHTTPHeaderField:#"Authorization"];
Hopefully that gets you started.

NSURLConnection Authorization Header not Working

I am trying to send an OAuth access token in an HTTP header via NSURLConnection but it doesn't seem to be sending the header because the API keeps giving me an error saying that "must provide authorization token".
This is the code that I am using:
NSURL *aUrl = [NSURL URLWithString: #"http://generericfakeapi.com/user/profile"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:aUrl
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:30.0];
[request addValue:[NSString stringWithFormat:#"OAuth %#", token] forHTTPHeaderField:#"Authorization"];
[request setHTTPMethod:#"GET"];
NSError *error = nil;
NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error: &error];
NSDictionary *JSONDictionary = [NSJSONSerialization JSONObjectWithData:returnData options:kNilOptions error:&error];
NSLog(#"Response : %#", JSONDictionary);
And this is an example of the cURL command for the API:
curl 'http://generericfakeapi.com/user/profile' -H 'Authorization: OAuth YourAuthToken'
Is this not what I am essentially doing through NSURLConnection?
Any help would be appreciated.
Change this line:
NSURL *aUrl = [NSURL URLWithString: #"http://generericfakeapi.com/user/profile"];
To:
NSURL *aUrl = [NSURL URLWithString: #"http://generericfakeapi.com/user/profile/"];
Apparently iOS drops the Authorization header if there isn't a slash at the end of a URL. This problem literally cost me my sleep for two days.
#isair's answer is truly a lifesaver.
Just to add on the root cause if you're interested:
NSURLRequest defines a set of reserved HTTP headers. And surprisingly, Authrorization is part of it.
The URL Loading System handles various aspects of the HTTP protocol for you (HTTP 1.1 persistent connections, proxies, authentication, and so on). As part of this support, the URL Loading System takes responsibility for certain HTTP headers:
Content-Length
Authorization
Connection
Host
Proxy-Authenticate
Proxy-Authorization
WWW-Authenticate
If you set a value for one of these reserved headers, the system may ignore the value you set, or overwrite it with its own value, or simply not send it. Moreover, the exact behavior may change over time. To avoid confusing problems like this, do not set these headers directly.
In #isair's case, it's highly likely that URLs without a trailing slash had triggered such "filtering" behaviour. This maybe an inconsistency in the implementation but we don't have access to the source code to verify that.
In my case, I was writing a React webapp that uses Authorization header to authenticate with the backend Django server. The app behaved perfectly on desktop Chrome but always failed to access login-required APIs on the iPhone (both Safari and Chrome), due to the missing Authorization header.
The ideal solution is to avoid using Authorization at all. But if you're communicating with a backend framework that specifically requires it (e.g. Django Rest Framework's token authentication). #isair's answer can be a good workaround.
For me it look fine. Are you sure you gave a valid token?
Try catch the error like this
if (error) {
NSLog(#"error : %#", error.description);
}
My code work well :
NSURL *jsonURL = [NSURL URLWithString:[NSString stringWithFormat:#"http://....ID=%i", cellID]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:jsonURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:120.0];
[request setValue:#"Basic ...." forHTTPHeaderField:#"Authorization"];
NSURLResponse *response;
NSError * error = nil;
NSData *POSTReply = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
hope it helps
I had same problem. In my case I changed "http" to "https" and everything works fine

GetListCollection SOAP request always returns root collection in SharePoint 2010

I'm working on a mobile share point application. I'm facing issue while trying to retrieve list collection of a sub-site. Went through so many blogs and tried different approaches but of no use.
My Home site has two sub sites (SampleSubsite & SampleSubsite2) in which I've document libraries created.
The GetSite web service defined in /_vti_bin/SiteData.asmx returns the following response.
Url = "http://sp2010.lab.xyz.local:20852";
Url = "http://sp2010.lab.xyz.local:20852/SampleSubsite";
Url = "http://sp2010.lab.xyz.local:20852/SampleSubSite2";
Now, when I try to fetch the List Collection of a sub site (in this case for example SampleSubsite), I'm constructing the URL as follows.
http://sp2010.lab.xyz.local:20852/SampleSubsite/_vti_bin/Lists.asmx
I've tried multiple options but of no use. (Test is the root site name). In all the below 3 cases, I get the root collection itself.
http://sp2010.lab.xyz.local:20852/Sites/SampleSubsite/_vti_bin/Lists.asmx
http://sp2010.lab.xyz.local:20852/Sites/Test/SampleSubsite/_vti_bin/Lists.asmx
http://sp2010.lab.xyz.local:20852/Test/SampleSubSite/_vti_bin/Lists.asmx
Could anyone through some light on it.
Code snippet Below:
#define kFetchListCollectionXML #"<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
#"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
#"<soap:Body>"\
#"<GetListCollection xmlns=\"http://schemas.microsoft.com/sharepoint/soap/\" />"\
#"</soap:Body>"\
#"</soap:Envelope>"\
- (void)getListCollectionOfSite:(NSString *)sitePath {
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#/_vti_bin/Lists.asmx",sitePath]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setValue:#"text/xml; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
[request setValue:#"http://schemas.microsoft.com/sharepoint/soap/GetListCollection" forHTTPHeaderField:#"SOAPAction"];
[request setValue:[NSString stringWithFormat:#"%ld",(unsigned long)kFetchListCollectionXML.length] forHTTPHeaderField:#"Content-Length"];
[request setHTTPBody:[kFetchListCollectionXML dataUsingEncoding:NSUTF8StringEncoding]];
[self performConnectionWithRequest:request];
}
The issue worked fine after creating the Alternate Access Mapping and creating the request for the the subsites as follows:
For subsite "SampleSubsite" with URL "http://sp2010.lab.xyz.local:20852/SampleSubsite", the request URL should be constructed as follows.
http://sp2010.lab.xyz.local:20852/SampleSubsite/_vti_bin/Lists.asmx
I was struggling with this using the New-WebServiceProxy cmdlet. The problem went away when I added ?WSDL to the end of the query string, as suggested here http://blogs.msdn.com/b/powershell/archive/2010/06/24/using-new-webserviceproxy-to-get-modify-and-add-items-to-a-list-in-sharepoint-2007.aspx

iOS app http post/get request

I need some tutorial, how to use HTTP POST (or GET) request from my iOS app. I want to send one string to my server and than write it to database. I've found this piece of code:
NSString *post = #"key1=val1";
NSData *postData = [post dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES];
NSString *postLength = [NSString stringWithFormat:#"%d", [postData length]];
NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
[request setURL:[NSURL URLWithString:#"http://www.nowhere.com/sendFormHere.php"]];
[request setHTTPMethod:#"POST"];
[request setValue:postLength forHTTPHeaderField:#"Content-Length"];
[request setValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
[request setHTTPBody:postData];
I add it to UIAction button, but it don't send anything to my server. On my server, I have a PHP script that takes that "key1" from post and than it write it to db.
<?
$postr = $_POST["key1"];
$con0 = mysql_connect("server","db","pass");
mysql_select_db("table", $con0);
mysql_set_charset('utf8',$con0);
mysql_query("INSERT INTO tok (token) VALUES ('$postr')");
mysql_close();
?>
Can anybody tell me what I am doing wrong?
Look at AFnetworking and work through their api. Sending a post request using the api is very fast, and is what most apps use for web connectivity.
Also please dont be discouraged by sarcastic comments. You should tag iOS projects as iOS and not xcode (unless you actually need help with the actual program xcode). But I don't think it's productive to harrass everyone that comes in and makes this mistake. A more tactful way would be a personal message as opposed to a public retort
https://github.com/AFNetworking/AFNetworking
AFNetworking is a very powerful library that can help you to reduce the effort on create your HTTP requests, you can find several examples on how to use this library on its github page.
You may find this answer useful for your needs: AFNetworking Post Request

Resources