iOS fetch Safari Saved Credit Card information in 3rd party apps - ios

I have been poking around safari saved passwords recently and I went through the WWDC session that talks in detail about accessing saved credentials from safari and adding saved credentials.
https://developer.apple.com/videos/play/wwdc2014-506/
http://devstreaming.apple.com/videos/wwdc/2014/506xxeo80e5kykp/506/506_ensuring_continuity_between_your_app_and_web_site.pdf
I also read this and found this is the code to get the saved credentials out of Safari,
SecRequestSharedWebCredential(NULL, NULL, ^(CFArrayRef credentials, CFErrorRef error) {
if (error != NULL) {
// If an error occurs, handle the error here.
[self handleError:error];
return;
}
BOOL success = NO;
CFStringRef server = NULL;
CFStringRef userName = NULL;
CFStringRef password = NULL;
// If credentials are found, use them.
if (CFArrayGetCount(credentials) > 0) {
// There will only ever be one credential dictionary
CFDictionaryRef credentialDict =
CFArrayGetValueAtIndex(credentials, 0);
server = CFDictionaryGetValue(credentialDict, kSecAttrServer);
userName = CFDictionaryGetValue(credentialDict, kSecAttrAccount);
password = CFDictionaryGetValue(credentialDict, kSecSharedPassword);
}
});
It is pretty much evident that we can access shared credentials from safari, I have seen apps do these things and I also saw this tutorial that details the steps to do the integration.
All is well until this point, now I also see you can save credit card information in safari and it automatically helps the user to pre-fill credit card information on payment sites.
Now comes the question, can third party apps fetch the saved credit card information that is saved in safari and vice versa? I have done so many google searches and it is point black, no exact matches on how to do so programatically. Is it possible or not?

Presuming your app has a companion website/backend, one option is to use the Safari View Controller (SFSafariViewController) to launch an 'add credit card' page on your website - Safari view controller has access to saved credit card info (as well as other autofill info). Once the user has entered their new credit card, you can return back to your app's main flow.

Related

MAUI Healthkit Checking Sharing Permissions

I want to check the healthkit read permissions given by an IOS device.
Inside the appdelegate I have the following. The app loads and brings up the permissions and they save to the device.
private HKHealthStore healthKitStore = new HKHealthStore();
public override void OnActivated(UIApplication application)
{
ValidateAuthorization();
}
private void ValidateAuthorization()
{
var restingHeartRate = HKQuantityType.Create(HKQuantityTypeIdentifier.RestingHeartRate);
var typesToWrite = new NSSet();
var typesToRead = new NSSet(new[] { restingHeartRate});
healthKitStore.RequestAuthorizationToShare(
typesToWrite,
typesToRead,
ReactToHealthCarePermissions);
}
void ReactToHealthCarePermissions(bool success, NSError error)
{
var access = hks.GetAuthorizationStatus(HKQuantityType.Create(HKQuantityTypeIdentifier.RestingHeartRate));
if (access.HasFlag(HKAuthorizationStatus.SharingAuthorized))
{
}
}
the returned value from GetAuthorizationStatus can be either, Shared, Notdetermined and Notshared. There's no differentiation between read and write authorization. The code above shows resting heart rate is not shared, even though it has read access.
If I change the above to:
var typesToWrite = new NSSet(new[] { restingHeartRate});
var typesToRead = new NSSet();
Then the GetAuthorizationStatus returns as being shared but, I don't want write access, I only want read. Is there another way to check read authorization status only, accurately?
HKAuthorizationStatus gives you write authorization status only.
Due to privacy reasons, there is no way to determine read authorization status, as outlined in https://developer.apple.com/documentation/healthkit/protecting_user_privacy
For example, a user could let your app read step count data, but prevent it from reading blood glucose levels. To prevent possible information leaks, an app isn’t aware when the user denies permission to read data. From the app’s point of view, no data of that type exists.
You can't check the user's read permission status, Apple's official documentation says:
To help prevent possible leaks of sensitive health information, your
app cannot determine whether or not a user has granted permission to
read data. If you are not given permission, it simply appears as if
there is no data of the requested type in the HealthKit store. If your
app is given share permission but not read permission, you see only
the data that your app has written to the store. Data from other
sources remains hidden.
For more details, you can check the official documentation:
authorizationStatusForType | Apple

Firebase verifying email while being logged in

I have the following logic in my iOS app:
User registers
Firebase sends an email confirmation
Returns to login screen
Now if the user logs in, without verifying the email, then we have a user session and isEmailVerified is false.
I only need to check the isEmailVerified in a certain point in the app.
Also I think signing the user in, checking the field and signing the user out would be bad practise.
I'd need to reauthenticate the user, what is the best way of doing this? How can I, after the user has logged in, switch the status of isEmailVerified?
Thanks
First, you need to have the email and password to create a credential. Your user already provided this on the login page... So the email and password to persistent storage on iOS. In Android, the equivalent would be SharedPreferences.
I do not code in iOS, but this will give you the idea for the logic.
Then, when you get to that point in your app where email verified is called:
if (user.isEmailVerified) == true {
// you do not need to hold the email and password in persistent storage anymore.
// go into your persistent storage and delete the data.
} else {
// get the email and password the user saved in persistent storage.
String email = persistentStorage.getEmail();
String password = persistentStorage.getPassword();
var user = firebase.auth().currentUser;
var credentials = firebase.auth.EmailAuthProvider.credential(email, password);
user.reauthenticate(credentials);
// then, when finished reauthenticating, check whether isEmailVerified() == true;
}

Save email address to accounts app iOS

I have two apps (eg: App1 and App2) which requires login with an account. What I need to achieve is when an user log-in successfully into the App1, the email address should get saved to the default Accounts app of the device. Then when the user opens up the App2, the email address saved from App1 should show up as a recommendation for the user if he need to use the same account to sign in to App2 as well. Just like some apps do if you click on sign in with Google or Facebook.
Since I am new to iOS, I need to ask if this is possible to achieve in iOS and if yes what procedure should I follow.
EDIT
I tried implementing KeyChain for this. Something like below :-
void StoreKeysInKeychain (string key, string value) {
var s = new SecRecord (SecKind.GenericPassword) {
ValueData = NSData.FromString (value),
Generic = NSData.FromString (key)
};
var err = SecKeyChain.Add (s);
}
void GetRecordsFromKeychain (string key)
{
SecStatusCode res;
var rec = new SecRecord (SecKind.GenericPassword) {
Generic = NSData.FromString (key)
};
var match = SecKeyChain.QueryAsRecord (rec, out res);
if (match != null) {
// nsdata object : match.ValueData;
}
}
This way when I login to the App1 with an email address it gets saved and when I open the App2 I get that email address. This works fine. But now the issue is that if I logout from App1 and login with another email address. That account is not visible in App2. How can I get a list of all the email address?
Any help is appreciated.
you need to use app Group to share information among app, Enable app Group from build settings in both app and certificate , assign same group to them , and put information for each other on a suite of NSuserdefault .
Xamarin documentation for app group is here : https://developer.xamarin.com/guides/ios/watch/working-with/app-groups/
I believe you can set up a ParseServer that user account management for both apps

How to force Google OAuth popup in Firebase when user already authenticated previously?

Whenever a user has previously authenticated with Google, it automatically defaults to logging them in with THAT account on subsequent attempts. I want to eliminate this and force the popup/redirect so that a user with multiple google accounts can choose which one to use. How?
Background:
The automatic logging in feature is proving problematic for me as I have a whitelisted set of e-mails for users allowed to use my app. If a Google user chooses the wrong account when first logging in, they can't go back and choose the one associated to their whitelisted e-mail.
Just as #nvnagr said, you can do this with the following code:
var provider = new firebase.auth.GoogleAuthProvider();
provider.setCustomParameters({
'prompt': 'select_account'
});
But I think you need to update the firebase version to 3.6.0 something.
Google supports a parameter in authentication url to deal with this issue.
If you add prompt=select_account in your request to Google authentication, it'll force the user to do an account selection. See the details and other values of prompt.
https://developers.google.com/identity/protocols/OpenIDConnect#authenticationuriparameters
I'm not sure if there is an easy way to add this parameter through firebase api.
When you're calling the oAuth function, you can pass a third options parameter to make the authentication last for the session only. This should solve your problem. Docs
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
ref.authWithOAuthPopup("google", function(error, authData) {
if (error) {
console.log("Login Failed!", error);
} else {
console.log("Authenticated successfully with payload:", authData);
}
}, {
remember: 'sessionOnly'
});

iOS OneDrive (skydrive) app displays permissions dialog every time it runs

I'm developing an iOS app that gives users access to their OneDrive/SkyDrive and I've run into a very annoying issue:
The very first time a user links the app to their OneDrive, everything goes as expected:
They have to enter a user id and password
Then they have to agree to let the app access their info
Then they get to browse their OneDrive
That's all good.
But, if the app closes, and you try to access the OneDrive again, rather than skipping straight to #3, and being able to access the OneDrive, they are stopped at step #2 (step 1 is skipped, as expected) and they have to agree again to let the app access their info.
The code is taken directly from the iOS examples in the online documentation (with some slight modification based on samples found here on Stack Overflow), but, here it is for inspection:
- (void) onedriveInitWithDelegate:(id)theDelegate {
self.onedriveClient = [[LiveConnectClient alloc] initWithClientId:MY_CLIENT_ID
delegate:theDelegate
userState:#"initialize"];
}
And then, theDelegate implements this:
- (void)authCompleted:(LiveConnectSessionStatus) status
session:(LiveConnectSession *) session
userState:(id) userState {
NSLog(#"Status: %u", status);
if ([userState isEqual:#"initialize"]) {
NSLog( #"authCompleted - Initialized.");
if (session == nil) {
[self.onedriveClient login:self
scopes:[NSArray arrayWithObjects:#"wl.basic", #"wl.signin", #"wl.skydrive_update", nil]
delegate:self
userState:#"signin"];
}
}
if ([userState isEqual:#"signin"]) {
if (session != nil) {
NSLog( #"authCompleted - Signed in.");
}
}
}
I thought that perhaps the status value might give a clue and that maybe I could avoid the login call, but it's always zero/undefined when I get to authCompleted after calling initWithClientId. (And session is always nil.)
Is there a scope I'm missing? Is there a different call to make rather than a straight-up login call? Or is it more complicated than that? I've seen reference to "refresh tokens" related to OAuth2 login, but I've not been able to find any concrete examples of how they might be used in this situation.
Any help and/or insights greatly appreciated.
Diz
Well, it turns out that the answer is pretty simple here. I just needed to add the "wl.offline_access" scope to my list of scopes during the initial login operation. The docs didn't really imply this type of behavior for this scope, but, that did the trick for me.
With this new scope added, subsequent invocations of the app no longer bring up the "agree to give the app these permissions" dialog, and I can go straight to browsing the OneDrive.
(Credit where it's due: Stephane Cavin over at the microsoft forums gave me the tip I needed to work this out. Gory details are here:
http://social.msdn.microsoft.com/Forums/en-US/8c5c7a99-7e49-401d-8616-d568eea3cef1/ios-onedrive-skydrive-app-displays-permissions-dialog-every-time-it-runs?forum=onedriveapi )
Diz

Resources