I'm making an app based on iOS6 Social Framework...it was working fine but now after few months got an weird error.
My NSLog of imported JSON Facebook data to a NSDictionary is:
profiledictionary: {
error = {
code = 190;
"error_subcode" = 463;
message = "Error validating access token: Session has expired at unix time 1365610034. The current unix time is 1366032783.";
type = OAuthException;
Seems my access token has expired, but isn't iOS6 Social Framework supposed to take care of it automatically?
Any ideas about how can I solve it and also avoid future problems like that, so I can safe publish a real app?
finally got it...was necessary to check if NSDictionary had an object named "error" (in this case Facebook error about token expired), and if so call a method to renew ACAccount:
if([self.profileDictionary objectForKey:#"error"]!=nil)
{
[self attemptRenewCredentials];
}
-(void)attemptRenewCredentials{
[self.accountStore renewCredentialsForAccount:(ACAccount *)self.facebookAccount completion:^(ACAccountCredentialRenewResult renewResult, NSError *error){
if(!error)
{
switch (renewResult) {
case ACAccountCredentialRenewResultRenewed:
NSLog(#"Good to go");
[self getFacebookAccount];
break;
case ACAccountCredentialRenewResultRejected:
NSLog(#"User declined permission");
break;
case ACAccountCredentialRenewResultFailed:
NSLog(#"non-user-initiated cancel, you may attempt to retry");
break;
default:
break;
}
}
else{
//handle error
NSLog(#"error from renew credentials%#",error);
}
}];
}
Related
I'm new to the WTelegramClient C# Library and was used to TLSharp (not working anymore)
I'm trying to understand how I get User info after update is received,
I have the example code that listen to updates and write them in console
but I can't understand how I can respond to the user that sent the message (new update)
I think I need the user id/access_hash to send message to the sender but I can't understand how
Here is how I get the new messages but it can get only username or name/id
private static void DisplayMessage(MessageBase messageBase, bool edit = false)
{
if (edit) Console.Write("(Edit): ");
switch (messageBase)
{
case Message m: Console.WriteLine($"{Peer(m.from_id) ?? m.post_author} in {Peer(m.peer_id)}> {m.message}"); break;
case MessageService ms: Console.WriteLine($"{Peer(ms.from_id)} in {Peer(ms.peer_id)} [{ms.action.GetType().Name[13..]}]"); break;
}
}
Here i can get the name or username of sender(if have) and the message itself
MessageService ('user' not channel or group) for example get me only firstname and lastname
How to get all info of sender or chat itself (i want to try mark as read the message)
I'm used to TLSharp and the new library WTelegramClient is different.
Thanks!!!
Below is a quick example on how to modify DisplayMessage to react to a message sent in private from a user, get the details about this user, verify who it is and which text was sent to us, and then send him a message back.
Notes:
For this example to work, you will need the latest version of Program_ListenUpdates.cs with static variables
DisplayMessage is now async Task, in order to use await
You can pass user to send a message because class User is implicitly converted to InputPeerUser (with the user id/access_hash).
You can do similarly for messages coming from chats, using PeerChat/PeerChannel classes and the _chats dictionary to get chat details
private static async Task DisplayMessage(MessageBase messageBase, bool edit = false)
{
if (edit) Console.Write("(Edit): ");
switch (messageBase)
{
case Message m:
Console.WriteLine($"{Peer(m.from_id) ?? m.post_author} in {Peer(m.peer_id)}> {m.message}");
if (m.flags.HasFlag(Message.Flags.out_))
break; // ignore our own outgoing messages
if (m.Peer is PeerUser pu) // got a message in a direct chat with a user
{
if (_users.TryGetValue(pu.user_id, out var user)) // get user details
{
if (user.username == "Wiz0u" && m.message == "hello")
{
await Client.SendMessageAsync(user, $"hi {user.first_name}, I'm {My.first_name}");
}
}
}
break;
case MessageService ms:
Console.WriteLine($"{Peer(ms.from_id)} in {Peer(ms.peer_id)} [{ms.action.GetType().Name[13..]}]");
break;
}
}
I'm using the Android Amplify library. I am having trouble finding out what kind of error would be passed back from the Amplify.Auth.signIn() function. I'm not finding the documentation for this anywhere. Right now I am just kind of guessing as to what it will return. What I want is to tell the user how to recover from the error. Does the username not exist, was the password incorrect, was it of bad format, etc. Reading the source code I am given the impression that AmplifyException.recoveryMessage is what I want but that would still be problematic as it doesn't allow me to customize the message.
/**
* Sign in the user to the back-end service and set the currentUser for this application
* #param username User's username
* #param password User's password
*/
override fun initiateSignin(username : String, password : String) {
//Sign in the user to the AWS back-end
Amplify.Auth.signIn(
username,
password,
{result ->
if (result.isSignInComplete) {
Timber.tag(TAG).i("Sign in successful.")
//Load the user if the sign in was successful
loadUser()
} else {
Timber.tag(TAG).i("Sign in unsuccessful.")
//TODO: I think this will happen if the password is incorrect?
}
},
{error ->
Timber.tag(UserLogin.TAG).e(error.toString())
authenticationRecoveryMessage.value = error.recoverySuggestion
}
)
}
Authentication recovery message is LiveData that I want to update a snackbar which will tell the user what they need to do for a successful login. I feel there must be some way to get the error from this that I just haven't figured out yet. The ideal way to handle messages to the user is with XML strings for translation possibilities so I would really like to use my own strings in the snackbar but I need to know the things that can go wrong with sign-up and what is being communicated to me through the error -> {} callback.
I couldn't find them in the documentation myself, so i decided to log the possibles cases.
try {
const signInResult = await Auth.signIn({
username: emailOrPhoneNumber,
password
});
const userId = signInResult.attributes.sub;
const token = (await Auth.currentSession()).getAccessToken().getJwtToken();
console.log(userId, 'token: ', token);
resolve(new AuthSession(userId, token, false));
} catch (e) {
switch (e.message) {
case 'Username should be either an email or a phone number.':
reject(`${AuthError.usernameInvalid}: ${e.message}`);
break;
case 'Password did not conform with policy: Password not long enough':
reject(`${AuthError.passwordTooShort}: ${e.message}`);
break;
case 'User is not confirmed.':
reject(`${AuthError.userIsNotConfirmed}: ${e.message}`);
break;
case 'Incorrect username or password.':
reject(`${AuthError.incorrectUsernameOrPassword}: ${e.message}`);
break;
case 'User does not exist.':
reject(`${AuthError.userDoesNotExist}: ${e.message}`);
break;
default:
reject(`${AuthError.unknownError}: ${e.message}`);
}
}
SignIn uses Cognito's InitiateAuth under the hood, so error codes can be found here:
https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html#API_InitiateAuth_Errors
They are available in the code field of the error.
I am trying to build a Firebase hosted page that will connect to a (Django) HTTP web service using XMLHttpRequest in the below script.
<script>
function UserAction() {
var req = createRequest(); // defined below
// Create the callback functions:
var handleResponse = function (status, response) {
alert("status " + status + " response: " + response)
}
var handleStateChange = function () {
switch (req.readyState) {
case 0 : // UNINITIALIZED
case 1 : // LOADING
case 2 : // LOADED
case 3 : // INTERACTIVE
break;
case 4 : // COMPLETED
alert("case 4" + req.responseType);
handleResponse(req.status, req.responseJson);
break;
default: alert("error");
}
}
req.onreadystatechange = handleStateChange;
req.open("GET", "https://foo.org:/bar/getid/?Id=" + document.getElementById('ID').value, true);
req.send();
function createRequest() {
var result = null;
if (window.XMLHttpRequest) {
// FireFox, Safari, etc.
result = new XMLHttpRequest();
}
else if (window.ActiveXObject) {
// MSIE
window.alert("windows");
result = new ActiveXObject("Microsoft.XMLHTTP");
}
else {
// No known mechanism -- consider aborting the application
window.alert("no known mechanism");
}
return result;
}
}</script>
Using Chrome FireBase throws 404 error. Django server does not register any connection.
Using FireFox FireBase throws 404 error. But Django server throws
'code 400, message Bad HTTP/0.9 request type ('\x16\x03\x01\x00\xcc\x01\x00\x00\xc8\x03\x03\xdf\x04{\x9f\xe4\xb2\xc2ij\x8d\x14\xd5\xaa\xdcu\x14+&\xa4\xa1\xdf\xdc\xd8\x9b?\xea\xbdh\xb8')`
I did find this in the FireBase documentation here, making me think this is not possible. But hopefully I am wrong, or there is a way to do this in development/test, but not production.
SSL only: Firebase Hosting is SSL-only, meaning that content will only
be served over HTTPS. As you are developing your application make sure
that all external resources not hosted on Firebase Hosting are loaded
over SSL (HTTPS), including any external scripts. Most browsers do not
allow users to load "mixed content" (SSL and non-SSL traffic).
thanks
Following the answer here:
https://github.com/aws/aws-sdk-ios/issues/357
At the very bottom there is a mini guide on getting swift and cognito working.
I've made a AWSCustomIdentityProvider as such:
import Foundation
import AWSCognitoIdentityProvider
import AWSCognito
class AWSCustomIdentityProvider: NSObject, AWSIdentityProviderManager
{
private var dict = NSDictionary()
func addToken(value:NSString)
{
dict = ["graph.facebook.com":value]
}
public func logins() -> AWSTask<NSDictionary>
{
return AWSTask(result: dict)
}
}
And I have a login method from facebook:
public func loginButtonDidCompleteLogin(_ loginButton: FacebookLogin.LoginButton, result: FacebookLogin.LoginResult){
switch result {
case .failed(let error):
print("FACEBOOK LOGIN FAILED: \(error)")
case .cancelled:
print("User cancelled login.")
case .success(_, _, let accessToken):
let customIdentity = AWSCustomIdentityProvider()
let token = accessToken.authenticationToken
customIdentity.addToken(value: token as NSString)
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: REGIONTYPE, identityPoolId: "XXXXXXXXXXXXXXXXXXXXXXX", identityProviderManager:customIdentity)
credentialsProvider.clearKeychain()
credentialsProvider.clearCredentials()
let serviceConfiguration = AWSServiceConfiguration(region: REDIONTYPE, credentialsProvider: credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = serviceConfiguration;
credentialsProvider.getIdentityId().continue( { (task: AWSTask!) -> AnyObject! in
if (task.error != nil) {
print("Error: " + (task.error?.localizedDescription)!)// gets called
}
else {
print(task.result)//identityid
}
return nil
})
}
}
However I get the error:
Error Domain=com.amazonaws.AWSCognitoIdentityErrorDomain Code=8 "(null)" UserInfo={__type=NotAuthorizedException, message=Logins don't match. Please include at least one valid login for this identity or identity pool.}
Please let me know if you have any idea on how to resolve my issue. I've tried also following the docs and setting the logins directly "credentialsProvider.logins = {"graph.facebook.com": mytoken}
and that produces a different exception upon invoking a lambda method but DOES retrieve the identityID properly. However doing it according to the docs makes a warning that the method I'm using is deprecated.
The error I get:
UserInfo={NSLocalizedDescription=serialized object is neither a valid json Object nor NSData object: }
However that only happens sometimes. If I retry then i can potentially get the identity id but upon invoking a lambda method, I get the same error. I'm assuming it is a cognito issue.
UPDATE
If I use AWSCognitoLoginProviderKey.facebook.rawValue instead of graph.facebook.com in the first part, then it gives me the cognito ID and then I invoke the lambda method. I'll include the lambda method just incase that's the part I'm getting wrong but I'm decently sure that it's cognito that is preventing me from calling the lambda method:
import AWSLambda
import Foundation
struct AWSHelper{
let lambda = AWSLambda.default()
let APPLICATION_NAME = "MYAPPLICATION"
init(){
}
func getFunctionName(funcName: String) -> String{
return "\(funcName)_\(APPLICATION_NAME)"
}
func login(facebookID: String, cognitoID:String, callback:#escaping (Bool) -> Void){
let req = AWSLambdaInvocationRequest();
req?.invocationType = AWSLambdaInvocationType.requestResponse
req?.payload = ["cognitoID" : cognitoID, "facebookID" : facebookID]
req?.functionName = getFunctionName(funcName: "MYFUNCNAME")
lambda.invoke(req!) { (response: AWSLambdaInvocationResponse?,error: Error?) in
print(error)
let payload = response?.payload
print(payload)
callback(true)
}
}
}
Update 2
I have found out that calling a refresh method like this:
credentialsProvider.credentials().continue({ (task: AWSTask!) -> Any? in
print(task.result)
})
Causes an error like this:
AWSiOSSDK v2.4.10 [Error] AWSCredentialsProvider.m line:577 | __44-[AWSCognitoCredentialsProvider credentials]_block_invoke.352 | Unable to refresh. Error is [Error Domain=com.amazonaws.AWSCognitoIdentityErrorDomain Code=10 "(null)" UserInfo={__type=ResourceNotFoundException, message=Identity 'us-east-1:0db18266-1baa-4c59-9110-f9041dc92ead' not found.}]
I believe the big string that looks like an identitypoolID is actually the identityID for the given user that I have, so cognito has distributed an ID but is not able to query it?
the error:
Logins don't match. Please include at least one valid login for this identity or identity pool
Can also occur because you attempt to log in as another user without logging out, so the token in the logins dictionary is compared to the identityId for a different identity (and doesn't match). In this case the SDK usually recovers by retrying, clearing and reestablishing the identityId, and then it works.
But in your case since you are constructing your own logins dictionary, the issue is more likely that you have constructed a token that does not match. You can inspect tokens using https://jwt.io. (though I admit it works for google and cognito user pools, but not on facebook tokens (I don't know why this is)),
I think doesn't match means that the identityId records a different unique user than is specified in the token.
Are you sure the token is constructed correctly?
As you mentioned... the documentation.. well .. I find the documentation is not worth looking at, So I set up my projects so I can review working code and set breakpoints.
Here is a snippet of the code from Mobile Hub Helper's Facebook AWSSignInProvider, which shows what they use to get the token (token.tokenstring).
- (AWSTask<NSString *> *)token {
FBSDKAccessToken *token = [FBSDKAccessToken currentAccessToken];
NSString *tokenString = token.tokenString;
NSDate *idTokenExpirationDate = token.expirationDate;
if (tokenString
// If the cached token expires within 10 min, tries refreshing a token.
&& [idTokenExpirationDate compare:[NSDate dateWithTimeIntervalSinceNow:AWSFacebookSignInProviderTokenRefreshBuffer]] == NSOrderedDescending) {
return [AWSTask taskWithResult:tokenString];
}
AWSTaskCompletionSource *taskCompletionSource = [AWSTaskCompletionSource taskCompletionSource];
[FBSDKLoginManager renewSystemCredentials:^(ACAccountCredentialRenewResult result, NSError *error) {
if (result == ACAccountCredentialRenewResultRenewed) {
FBSDKAccessToken *token = [FBSDKAccessToken currentAccessToken];
NSString *tokenString = token.tokenString;
taskCompletionSource.result = tokenString;
} else {
taskCompletionSource.error = error;
}
}];
return taskCompletionSource.task;
}
Also... It bears mentioning. The AWSIdentityManager, and it's associated AWSSignInProviders is a nice architecture for getting signed in with Facebook and Google. Even if you don't use the rest of Mobile Hub Helper. Why re-invent the wheel, they did a very good job on the Identity portion of aws-mobilehub-helper-ios
I have a version of that library posted on github that adds an AWSSignInProvider for Cognito User Pools as well. SignIn-awsmhh it requires some fixes in the aws-mobilehub-helper-ios to use cognito user pools they are here aws-mobilehub-helper-ios (so if you clone do a clone --recursive and you will be set up for debugging using breakpoints in the library).
Few things that made it work I think.
I made the correct move by making my own identityprovidermanager and I think the main thing that was blocking me from executing a lambda method was actually the fact that I was using AWSLambda instead of AWSLambdaInvoker. After I switched it started making errors that made sense.
I am new in IOS development?
In my project I want to invite Facebook friend.when Facebook app is installed and not installed in both cases i want to invite my friend?
how can be done
//Below is my code
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:nil];
[FBWebDialogs presentRequestsDialogModallyWithSession:nil
message:[NSString stringWithFormat:#"I just smashed friends! Can you beat it?"]
title:#"StopNSwap"
parameters:params
handler:^(FBWebDialogResult result, NSURL *resultURL, NSError *error) {
if (error) {
// Case A: Error launching the dialog or sending request.
NSLog(#"Error sending request.");
} else {
if (result == FBWebDialogResultDialogNotCompleted) {
// Case B: User clicked the "x" icon
NSLog(#"User canceled request.");
} else {
NSLog(#"Request Sent.");
}
}}
friendCache:nil];
As far as I understand you are trying to send an app-to-user request to invite user's Facebook friends to start using your application, correct? Checkout the first answer here, Paul suggests an effective way of doing it using the Facebook SDK : How to send add friend request (to facebook user) from iOS application?