Get "Forbidden. Need user" when request messagesWithDialogID - quickblox

I get the same response every time I request history messages from Quickblock.
I already search for some topics in here, and they say I'm not logged in or I don't have permission to do that. I'm pretty sure I'm logged in and I have a permission. Everything works fine I can send, receive message but I can't get the history.
Here is the code
[QBRequest messagesWithDialogID:myId extendedRequest:nil forPage:resPage successBlock:^(QBResponse *response, NSArray *messages, QBResponsePage *responcePage) {
} errorBlock:^(QBResponse *response) {
NSLog(#"error: %#", response.error);
}];

You have to be logged in as a user in order to request your messages
Read this guide about session creation
http://quickblox.com/developers/SimpleSample-chat_users-ios#Login_to_Chat
You can do [QBRequest createSession...] or [QBRequest logIn...]

Related

WKWebview cookie issue?

Background:
I'm upgrading my app to use WKWebview from UIWebview as it will no longer be accepted by App Store
The App Store will no longer accept new apps using UIWebView as of April 2020 and app updates using UIWebView as of December 2020.
Issue:
What happen is, I'm getting cookie return from Webview (WKWebview) after logged in. I will retrieve a token I need for API firing, however I'm constantly hitting HTTP 401 status for all the API(s) fired.
If I revert back to UIWebview, and repeat the same for login but re-using the SAME TOKEN from WKWebview. I'm getting HTTP 200 status. Purpose of re-using same token is to prove that is a valid token.
Noted that, I have not make any changes to the method calling API. It remains the same for both WKWebview and UIWebview. (Including the object request for POST method)
Am I missing something in WKWebview?
Do I need to set cookie or allow anything in specific?
Code snippet:
<WebView
style={{ width: this.state.webviewWidth }}
ref={(component) => {
this.webviewRef = component;
}}
source={{ uri: this.state.url }}
onLoadStart={this.webviewOnLoadStart}
onLoad={this.webviewOnLoadEnd}
onNavigationStateChange={this.onNavigationStateChange}
useWebKit={true}
sharedCookiesEnabled={true}
/>
Pacakge.json
"react-native": "0.61.5",
"react-native-webview": "^10.3.2",
"#react-native-community/cookies": "^3.0.0",
Apparently the issue is that WKWebview does not handle cookie passing into the request header for us. Hence I received 401 authentication failure every time when I reach the server.
Unfortunately React-Native-Webview does not has a way to handle this cookie header passing out of the box (Please correct me if I'm wrong). I'm fully aware of this 'custom header' function provided within the lib, unfortunately it didn't work as expected. The cookie is still not part of the request header.
My solution to this is as follow, did under method decidePolicyForNavigationAction:
Dive into native lib (React-Native-Webview)
Loop through all existing cookies within websiteDataStore.httpCookieStore
Look for my cookie (of course, you should know your cookie name)
Append the cookie into the HTTPHeaderField to your http request
Load the http request again!
if (#available(iOS 11.0, *)) {
[webView.configuration.websiteDataStore.httpCookieStore getAllCookies:^(NSArray<NSHTTPCookie *> * _Nonnull cookies) {
NSLog(#"All cookies in websiteDataStore %#", cookies);
for(NSHTTPCookie *cookie in cookies){
if([cookie.name isEqualToString:#"coookieName"]){
if([navigationAction.request valueForHTTPHeaderField:#"Cookie"] != nil ){
}else{
NSMutableURLRequest *req = [request mutableCopy];
NSString *newCookie = [NSString stringWithFormat:#"cookieName=%#" , cookie.value];
// As you can see, I'm appending the cookie value into header myself
[req addValue:newCookie forHTTPHeaderField:#"Cookie"];
[req setHTTPShouldHandleCookies:YES];
[webView loadRequest:req];
return;
}
}
}
}];
} else {
// Fallback on earlier versions
}

NSUrlSessionTaskDelegate server response

I'm using NSUrlSessionTaskDelegate to upload files into a server, but server codes aren't given back in the didCompleteWithError. This matches the apple documentation:
Server errors are not reported through the error parameter. The only
errors your delegate receives through the error parameter are
client-side errors, such as being unable to resolve the hostname or
connect to the host.
But is there any other way I can get the server error's like a 400 Bad Request or something? Because every file upload is a success now even when I get a bad request back..
Something like this should work. But I didn't test it. It is posted as an answer just because of easier code formatting...
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
if (!error)
{
NSHTTPURLResponse *response = task.response;
NSLog(#"StatusCode: %d",response.statusCode);
if (response.statusCode != 200) //note that other 2xx codes might be valid
{
//....
}
}
else
{
NSLog(#"Error: %#",error.description);
}
}
In SWIFT 5, you can do the same like below.
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
print(task.response ?? "")
if let urlResponse = task.response as? HTTPURLResponse {
print(urlResponse.statusCode)
}
}

AFNetworking incorrectly interpreted WP_Error error

I have client code that communicates with the server to create an account. The communication works, but the error response is not received correctly. In the Objective-C code below, I use AFNetworking to send the request. I purposely sent an invalid email address and expected the failure block to get executed, but my code kept going into the success block.
- (void)createAccount:(NSString *)email
andUsername:(NSString *)username
andPassword:(NSString *)password
success:(SuccessBlock)success
failure:(FailureBlock)failure
{
NSDictionary *params = #{
#"email": email,
#"username" : username,
#"password" : password,
#"client_id" : #"12345"
#"client_secret" : #"abcdef"
};
NSString *requestUrl = [self pathForEndpoint:#"users/new"
withVersion:ServiceRemoteRESTApibbPressExtVersion_1_0];
[self.api POST:requestUrl parameters:params
success:^(AFHTTPRequestOperation *operation, id responseObject) {
success(responseObject); // WENT IN THIS PATH
}
failure:^(AFHTTPRequestOperation *operation, NSError *error){
failure(error); // EXPECTS THIS PATH
}
];
}
On the server side, my PHP scripts is coded as follow. I did check the debug.log and saw the printed message: *** users_new_REST_API() email invalid
add_action( 'rest_api_init', function () {
register_rest_route( 'bbpress_ext/v1', '/users/new', array(
'methods' => 'POST',
'callback' => 'users_new_REST_API'
) );
} );
public function users_new_REST_API( $request ) {
$user_name = $request['username'];
$password = $request['password'];
$user_email = $request['email'];
$client_id = $request['client_id'];
$client_secret = $request['client_secret'];
if ( ! is_email( $user_email ) ) {
error_log('*** users_new_REST_API() email invalid');
return new WP_Error('email_invalid', 'Invalid email entered.', array( 'status' => 524) );
}
}
I can't tell if AFNetworking is misbehaving or the REST-API (beta version 2) for Wordpress is broken.
Your understanding of AFNetworking error handling is incomplete. The error handler is for networking errors. It doesn't trigger for HTTP error codes. That's up to your app to decipher and handle. So, whether WP_Error returns a non-2XX HTTP status, or it just returns some kind of JSON object with some error information, AFNetworking is going to report the request succeeded.
It's not the job of AFNetworking to deal with app-level protocol logic.

NSURLConnection returning error instead of response for 401

I have a web API that, for a specific request returns status code 200 if everything went ok, and 401 if the user is not logged in based on an Authorization token. Everything works fine if the response status is 200, but doesn't seem to work properly if the response status is 401, returning a connection error with code -1012, while the response is nil.
So, the following code:
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSLog(#"%#", response);
NSLog(#"%#", connectionError);
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
int statusCode = (int)[httpResponse statusCode];
NSLog(#"response status code: %d", statusCode);
will display
2015-04-01 15:58:18.511 MyProject[3618:694604] <NSHTTPURLResponse: 0x155facc0> { URL: *SOME_URL* } { status code: 200, headers {
"Access-Control-Allow-Headers" = "Content-Type, Accept, X-Requested-With";
"Access-Control-Allow-Methods" = "POST, GET, PUT, UPDATE, OPTIONS";
"Access-Control-Allow-Origin" = "*";
Connection = "keep-alive";
"Content-Type" = "application/json";
Date = "Wed, 01 Apr 2015 12:58:14 GMT";
Server = "Wildfly 8";
"Transfer-Encoding" = Identity;
"X-Powered-By" = "Undertow 1";
} }
2015-04-01 15:58:18.513 MyProject[3618:694604] (null)
2015-04-01 15:58:18.513 MyProject[3618:694604] response status code: 200
if the response status is 200, while if the status code is 401, I will get:
2015-04-01 16:05:55.988 MyProject[3633:695836] (null)
2015-04-01 16:05:55.992 MyProject[3633:695836] Error Domain=NSURLErrorDomain Code=-1012 "The operation couldn’t be completed. (NSURLErrorDomain error -1012.)" UserInfo=0x146137c0 {NSErrorFailingURLKey=*SOME_URL*, NSErrorFailingURLStringKey=*SOME_URL*, NSUnderlyingError=0x1459e6d0 "The operation couldn’t be completed. (kCFErrorDomainCFNetwork error -1012.)"}
2015-04-01 16:05:55.992 MyProject[3633:695836] response status code: 0
If I do the same request using Postman or an Android device, I will get status code 401 with the following headers(copied from Postman):
Connection → keep-alive
Content-Length → 30
Content-Type → application/json
Date → Wed, 01 Apr 2015 13:07:34 GMT
Server → Wildfly 8
X-Powered-By → Undertow 1
Is there any fix or maybe a library that could give me some accurate response status? I searched a bit about the -1012 error, but couldn't find much and I don't really want to base on that.
Edit: after a bit of research I found the following statement on Appl's documentation: "If authentication is required in order to download the request, the required credentials must be specified as part of the URL. If authentication fails, or credentials are missing, the connection will attempt to continue without credentials."
But then how can I know if this error will be after a 401 status? Can it appear after another type of request?
to check the 401 error, you can do this:
if (error != nil && error.code == NSURLErrorUserCancelledAuthentication) {
// do something for 401 error
}
hope this help
In order to get the 401 status code, I think you'll need to implement protocol NSURLConnectionDelegate and then connection:didReceiveAuthenticationChallenge:.
So, you'll also need to pass the delegate, maybe using [NSURLConnection connectionWithRequest:request delegate:self].
And, if you aren't trying to implement the authentication challenge, I would rather always return the 200 status code, but with different json content.
Hope it can help.
I have a web API that, for a specific request returns status code 200
if everything went ok, and 401 if the user is not logged in based on
an Authorization token. Everything works fine if the response status
is 200, but doesn't seem to work properly if the response status is
401, returning a connection error with code -1012, while the response
is nil.
I've run exactly into the same problem, REST API call returns 401 in Android and Postman, but status code 0 in iOS with a connection error with code -1012.
You can find more information about this problem in this SO post.
Seems to be an iOS bug (or at least very strange approach) happening both with async and sync requests.
I'm posting this just in case this might be useful for others bumping into the same issue. What I did in the code to manage the 401 status, right after the request, is to call a method that checks each managed http status code.
The method receives (NSError **)error and [(NSHTTPURLResponse *)response statusCode].
This is the 401 part - uses the error details stored inside userInfo structure.
// Auth failed or token problems
if (statusCode == 0 && [error userInfo] != nil) {
// Get error detailed informations
NSDictionary *userInfo = [error userInfo];
NSString *errorString = [[userInfo objectForKey:NSUnderlyingErrorKey] localizedDescription];
// If error message is of type authFailed or returns iOS code -1012 meaning auth failed
if ([errorString containsString:#"kCFErrorDomainCFNetwork"] || [errorString containsString:#"-1012"]) {
NSLog(#"%# - ConnectionError - Code 401 - Cause: authentication failed, token is invalid or expired", type);
} else {
NSLog(#"%# - ConnectionError - Cause: generic auth error", type);
}
// Alert user that auth failed
...
}
The other way is to check directly for this error code (-1012) as suggested by #ThuanDINH above. (edited the answer for objective c).
My code can be changed into:
// Auth failed - token problems
if (statusCode == 0 && [error code] == NSURLErrorUserCancelledAuthentication) {
// If error code is UserCanceledAuthentication
MPLog(MPLogLevelInfo, #"%# - ConnectionError - Cause: authentication failed, token is invalid or expired", type);
// Alert user that auth failed
...
}
But in this way you will not handle all other errors (you need to switch on each NSURLError code).
Here you can find the SO question with the list of all the NSURLError codes.
Based on Apple documentation https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/URLLoadingSystem/NSURLSessionConcepts/NSURLSessionConcepts.html,
Note: NSURLSession does not report server errors through the error parameter. The only errors your delegate receives through the error parameter are client-side errors, such as being unable to resolve the hostname or connect to the host. The error codes are described in URL Loading System Error Codes.
Server-side errors are reported through the HTTP status code in the NSHTTPURLResponse object. For more information, read the documentation for the NSHTTPURLResponse and NSURLResponse classes.
We need to make sure that we do not cancel the session in our code. For example, I was calling NSURLSessionAuthChallengeCancelAuthenticationChallenge in didReceiveChallenge delegate method, when previousFailureCount > 1. This was suppressing 401 response and also call to didReceiveResponse.
When I changed above value to NSURLSessionAuthChallengePerformDefaultHandling, I am receiving 401 Unauthorized response in didReceiveResponse delegate method and works as expected.

BSession openActiveSessionWithPublishPermissions always get public_pofile only

Hi Guys i want to share on facebook , when user is not login in I ask from login/permissions in following way
[FBSession openActiveSessionWithPublishPermissions:[NSArray arrayWithObjects:#"publish_actions",#"status_update",nil]
defaultAudience:FBSessionDefaultAudienceFriends
allowLoginUI:YES
completionHandler:^(FBSession *session,
FBSessionState status,
NSError *error)
{
if (error)
NSLog(#"Login failed");
else if (FB_ISSESSIONOPENWITHSTATE(status))
[self PostOnWall];
}];
};
In permission dailogs it always ask for just public profile and when I am trying to share some thing it shows following error
Error Domain=com.facebook.sdk Code=5 "The operation couldn’t be completed. (com.facebook.sdk error 5.)" UserInfo=0x16d40d20 {com.facebook.sdk:HTTPStatusCode=403, com.facebook.sdk:ParsedJSONResponseKey={
body = {
error = {
code = 200;
message = "(#200) Permissions error";
type = OAuthException;
};
};
code = 403;
},
Please help why its not asking for proper permissions
Ah I think I found the issue. You'll need update your FB app and submit for approval the additional permissions you need ("publish_actions"). If you don't do this, then only Facebook users listed in your app's roles will have extended permissions without FB approval