With AWS iOS SDK 2.4.0 Amazon's documentation fell behind. Pages on writing code to support Federated Identities, particularly how to refreshing token ids no longer reflected the code.
This page for example, http://docs.aws.amazon.com/cognito/latest/developerguide/open-id.html, refers to credentialsProvider.logins which isn't present in SDK 2.4.0
Does anyone know if anyone else has documented this aspect of Amazon's iOS SDK? Or Amazon somewhere else?
Amazon has now released 2.4.10 and its focus, I'd say, has moved to its User Pools product leading me to fear that AWS Federated Identities product may be soon deprecated.
Federated Identities is not about to be deprecated. We will be updating the docs. In the meantime, I can provide some stopgap instructions. In 2.4, the logins dictionary switched to a pull model. The SDK will ask you for an updated logins dictionary whenever the AWS credentials need to be refreshed. To use it, provide an implementation of AWSIdentityProviderManager to your credentials provider. Below is some partial code which shows you how to implement the logins method. It shows how to do it both synchronously if you have a current token and asynchronously if you have to call a service to get one.
Synchronously get the token
- (AWSTask<NSDictionary<NSString *, NSString *> *> *)logins {
return [AWSTask taskWithResult: #{ #"login.provider.com" : token}];
}
Asynchronously get the token
- (AWSTask<NSDictionary<NSString *, NSString *> *> *)logins {
AWSTaskCompletionSource<NSString*> *token = [AWSTaskCompletionSource new];
[self getOpenIdToken:token];
return [token.task continueWithSuccessBlock:^id _Nullable(AWSTask<NSString *> * _Nonnull task) {
return [AWSTask taskWithResult: #{ #"login.provider.com" : task.result }];
}];
}
- (void) getOpenIdToken: (AWSTaskCompletionSource <NSString*>*) token {
//call your server to get the token
//...
if(success){
token.result = oidcTokenFromServer;
}else {
[token setError:[NSError errorWithDomain:#"oidc"
code:-1
userInfo:#{#"error":#"Unable to get open id connect token"}]];
}
}
Related
What I need to implement that Face ID authentication will work on Xamarin.forms project?
You have to do this natively on your iOS project, and then expose it to your Forms project using a DependencyService or some kind of ioc.
You must add to your info.plist the NSFaceIDUsageDescription key, otherwise the app will crash when asking for authentication.
Here is a snippet that authenticates a user locally:
var context = new LAContext();
LAContextReplyHandler replyHandler;
NSError AuthError;
if (context.CanEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, out AuthError))
{
replyHandler = new LAContextReplyHandler((success, error) =>
{
// Handle authentication success or error
});
// Authenticate and ask for permission if needed.
context.EvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, "Authenticate", replyHandler);
}
We just noticed that our app which relies on Instagram as the primary login is no longer working. In investigating this further, it appears the callback URL for Instagram stopped working. Now whenever anyone logs in via Instagram or signs up via Instagram, they are taken to the Instagram app instead of being asked to authenticate or taken into our app experience.
I checked another app that I know if, called "Print Studio" and the same thing is happening to them.
Is this issue happening to anyone else? Any clue as to what is causing it and has anyone heard from Instagram on a possible fix?
Yes. seems to effect all applications (at least the apps that are using the approved 3rd party API). I saw this issue few days ago and it got resolved by itself. I assume Instagram engineers are rolling some updates and broke something.
I suggest reporting an issue from the developer portal. https://www.instagram.com/developer/clients/manage/. as many reports as they receive, the better.
UPDATE:
The issue seems to be related to cookies / session persistent changes made on Instagram side.
To workaround the issue, redirect the user to the original auth url when you detect the user got to the Instagram homepage. Because the user is already logged in, this should pass the user to the correct redirect url without logging in again.
for example, in swift:
// MARK: - WKNavigationDelegate
override func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: #escaping (WKNavigationActionPolicy) -> Void) {
if let urlString = navigationAction.request.url?.absoluteString {
if urlString == "https://instagram.com" || urlString == "https://instagram.com/" ||
urlString == "https://www.instagram.com" || urlString == "https://www.instagram.com/" ||
urlString == "http://instagram.com" || urlString == "http://instagram.com/" ||
urlString == "http://www.instagram.com" || urlString == "http://www.instagram.com/" {
decisionHandler(.cancel)
self.refresh(nil) // reloads the original auth url
return
}
}
super.webView(webView, decidePolicyFor: navigationAction, decisionHandler: decisionHandler)
}
I am trying to send the message by using pubnub.
But it gives me error for : PNAccessDeniedCategory
I am not finding any solution how to solve this.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
PNConfiguration *configuration = [PNConfiguration configurationWithPublishKey:#"pub-c-..."subscribeKey:#"sub-c-..."];
self.client = [PubNub clientWithConfiguration:configuration];
//Subscription process results arrive to listener which should adopt to PNObjectEventListener protocol and registered using:
[self.client addListener:self];
//Listeners callbacks:
[self.client subscribeToChannels: #[#"test123"] withPresence:YES];
NSLog(#"channel-->%#",self.client.channels);
configuration.uuid = #"test123";
}
- (void)client:(PubNub *)client didReceiveStatus:(PNSubscribeStatus *)status {
if (status.category == PNUnexpectedDisconnectCategory) {
// This event happens when radio / connectivity is lost
}
else if (status.category == PNConnectedCategory) {
// Connect event. You can do stuff like publish, and know you'll get it.
// Or just use the connected event to confirm you are subscribed for
// UI / internal notifications, etc
}
else if (status.category == PNReconnectedCategory) {
// Happens as part of our regular operation. This event happens when
// radio / connectivity is lost, then regained.
}
else if (status.category == PNDecryptionErrorCategory) {
// Handle messsage decryption error. Probably client configured to
// encrypt messages and on live data feed it received plain text.
}else if (status.category == PNAccessDeniedCategory) {
Nslog(#"It gives me this error");
}
}
Please advice. Whether this error is because my account is expired and that is the reason it is not allowing me to access ?
Do i have to create another free account ? or have to create new key ?
Please help.
PubNub Access Manager
You have Access Manager add-on enabled on your keys and so it is just doing its job - denying un-granted access to your keys. You must grant all access to use your keys once this is enabled. When you enable Access Manager a dialog pops up with a warning:
Warning: This action will enable Access Manager on your keyset. If you
are already using this keyset in a production application, please be
aware you will need to grant access to all existing channels in order
to continue use without interruptions.
Here is a snapshot of that dialog:
You can disable Access Manager until you are ready to implement the proper granting logic on your server and you will no longer get this error.
Before you go live with your app, you should implement the necessary granting logic and enable Access Manager to protect your keys from being wrongfully used.
I need to integrate Salesforce iOS native library in my iOS native application and I have to show salesforce login screen and flow as mentioned below:
I have a HOME screen in my iOS native application.
From there I have to navigate to Salesforce login screen.
User will enter credentials and Salesforce will validate it.
Once logged in success then it will back to my HOME screen with token/sessionID.
That token/sessionID I will use internally in my application.
To achieve this I have integrated "SalesforceMobileSDK-iOS-Distribution" from below link
https://github.com/forcedotcom/SalesforceMobileSDK-iOS-Distribution
in my application. But exactly I don't know from where to and how to start? which class will give me login screen of Salesforce. I tried something like
[SFUserAccountManager sharedInstance].oauthClientId = strClientID;
[SFUserAccountManager sharedInstance].oauthCompletionUrl = strCallbackURI;
[SFUserAccountManager sharedInstance].scopes = [NSSet setWithObjects:#"api",#"web", nil];
and
[SalesforceSDKManager sharedManager].connectedAppId = strClientID;
[SalesforceSDKManager sharedManager].connectedAppCallbackUri = strCallbackURI;
[SalesforceSDKManager sharedManager].authScopes = #[#"web", #"api"];
[[SalesforceSDKManager sharedManager] launch];
I have connected app information such as Client ID, Secret code and Redirect URI. How can I proceed?
If I use zkSforce library from this link https://github.com/superfell/zkSforce
Does it achieve my requirement?
Please help me. Thanks in advance.
Finally I achieved it and the good answer for this question is
Download "SalesforceMobileSDK-iOS-Distribution" from below link https://github.com/forcedotcom/SalesforceMobileSDK-iOS-Distribution .
Extract all the "-Release.zip" files and add those to your application.
Set Header Search path for all libraries as "$(SRCROOT)/your app name/your library name" and choose "recursive".
Set Other linker flags such as "-ObjC" and "-all_load".
Import "SFUserAccountManager.h", "SFAuthenticationManager.h" and "SFIdentityData.h" files.
Add below code snippet to your login action
[SFUserAccountManager sharedInstance].oauthClientId = strClientID;
[SFUserAccountManager sharedInstance].oauthCompletionUrl = strCallbackURI;
// [SFUserAccountManager sharedInstance].scopes = [NSSet setWithObjects:#"web", #"api", nil];
[[SFAuthenticationManager sharedManager] addDelegate:self];
[[SFAuthenticationManager sharedManager]
loginWithCompletion:(SFOAuthFlowSuccessCallbackBlock)^(SFOAuthInfo *info) {
NSLog(#"Authentication Done");
SFIdentityData *claims = [SFAuthenticationManager sharedManager].idCoordinator.idData;
NSLog(#"claims = %#",claims);
NSLog(#"accessToken = %#", [SFAuthenticationManager sharedManager].coordinator.credentials.accessToken);
}
failure:(SFOAuthFlowFailureCallbackBlock)^(SFOAuthInfo *info, NSError *error) {
NSLog(#"Authentication Failed");
// handle error hare.
}
];
#pragma mark - SFAuthenticationManager
- (void)authManager:(SFAuthenticationManager *)manager willDisplayAuthWebView:(UIWebView *)view{
}
- (void)authManagerDidFail:(SFAuthenticationManager *)manager error:(NSError*)error info:(SFOAuthInfo *)info{
}
hope it would helpful to you.
Note: According to me the "Call back URI" should not start with either "http" or "https".
Sales force uses oAuth login. The code should do the magic.
What is your main problem ? were u not able show the login page after running the above code ?
Other way to check how SFDC iOS SDK works is to install forceios npm package & create a native iOS application from the cmd it provides. [https://www.npmjs.com/package/forceios]
Application created gives you an glimpse on how the SFDC SDK works [login, Fetch Data from SFDC etc.]
1) integrate using CocoaPods
pod 'SalesforceSDKCore'
import <SFAuthenticationManager.h>
2) make sure you properly configure the OAuthRedirect URL
yourapp://authdone
add this redirect URL in salesforce server config
config redirect URL in your Info.plist
3) use Ganesh's code above, employing SFAuthenticationManager with the oauthCompletionUrl set to the OAuthRedirect URL you have configured. The callback will have the entire user object on success.
I've done some things using firebase (so cool).
I'm doing the custom login, I've generated a AUTH_TOKEN (using nodejs).
My question is if I need to pass in all my page that I wanna to protect the code below?
Peace,
Tulio Cruz
var dataRef = new Firebase("https://example.firebaseio.com");
// Log me in.
dataRef.auth(AUTH_TOKEN, function(error, result) {
if(error) {
console.log("Login Failed!", error);
} else {
console.log('Authenticated successfully with payload:', result.auth);
console.log('Auth expires at:', new Date(result.expires * 1000));
}
});
I'm not sure I fully understand your question. If you want to know if you need to call auth every time a page is loaded -- yes you do. When using custom login with the low-level auth() api call, we don't do any session management for you.
You only need to call auth() once per page load though -- not once for each Firebase reference.