Save email address to accounts app iOS - 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

Related

Firebase: How to get email from sign in with apple on real device?

I'm implementing a sign in with apple, this is my code on apple button press
onAppleButtonPress = async () => {
// performs login request
const appleAuthRequestResponse = await appleAuth.performRequest({
requestedOperation: AppleAuthRequestOperation.LOGIN,
requestedScopes: [
AppleAuthRequestScope.EMAIL,
AppleAuthRequestScope.FULL_NAME,
],
});
// Ensure Apple returned a user identityToken
if (!appleAuthRequestResponse.identityToken) {
console.log('no token');
throw 'Apple Sign-In failed - no identify token returned';
}
// Create a Firebase credential from the response
const {identityToken, nonce} = appleAuthRequestResponse;
const appleCredential = firebaseAuth.AppleAuthProvider.credential(
identityToken,
nonce,
);
//I WANT TO GET THE EMAIL HERE TO USE CHECK IT FROM FIREBASE IF EMAIL ALREADY EXISTS BY THIS CODE
firebaseAuth()
.fetchSignInMethodsForEmail(appleAuthRequestResponse.email)
.then(providers => {
});
}
It works on the simulator, but on real device the email is null.
Anyone who can help?
Apple only returns the full name and email on the first login, it will return null on the succeeding login so you need to save those data.
T receive these again, go to your device settings; Settings > Apple ID, iCloud, iTunes & App Store > Password & Security > Apps Using Your Apple ID, tap on your app and tap Stop Using Apple ID. You can now sign-in again and you'll receive the full name and `email.
Source here.

Given a users UID can I access his profile info?

I know that I can save user info to his profile with firebase. But I am wondering if I am able to get this same info when all I have is a UID?
As I understand it I can only do this to get the info:
Auth.auth().currentUser.displayName...
It seems like If I want to be able to fetch other users info I would have to keep a copy of their data in a users node.
Am I correct? Or can I access their profile info withought having to keep a copy?
If you use firebase authentication, then you can retrieve the current user info. So, if currently user X is logged in and he is authenticated, you can retrieve the following info about him:
let user = Auth.auth().currentUser
if let user = user {
// The user's ID, unique to the Firebase project.
// Do NOT use this value to authenticate with your backend server,
// if you have one. Use getTokenWithCompletion:completion: instead.
let uid = user.uid
let email = user.email
let photoURL = user.photoURL
// ...
}
If you want to retrieve information about other users, then in that case you need to use firebase database:
users
userId (firebase authentication)
name : user X
userId
name : user Y
Depending on the reason you need this data, you can actually get access to an auth user by using the firebase-admin package.
inside of your firebase function - or node.js backend - (this is only for backend node.js functions, not for front-end), you can get the user by doing the following:
const admin = require("firebase-admin");
const authUser = await admin.auth().getUser(uid);
authUser = authUser.toJSON(); // Optional
You can read more about retrieving user data here
If you want to load in multiple users at once, you can easily use the getUsers function and it's also possible to load in the user based on other information like email:
getUser(uid)
getUserByEmail(email)
getUserByPhoneNumber(phoneNumber)

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;
}

Can you only allow users with a specific email address to sign up and use your app

I currently have user authentication in my app using firebase and swift 3. Is there a way to only let users with a certain email address to sign up to use my app?
Essentially what you want to do is include a boolean test to determine whether the email text contains the domain you want.
Here is a function that determines whether or not the input text contains a set domain.
func isValidEmail(testEmail:String, domain:String) -> Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+#[\(domain)]+\\.[com]{3,\(domain.characters.count)}"
let emailTest = NSPredicate(format:"SELF MATCHES %#", emailRegEx)
let result = emailTest.evaluate(with: testEmail)
return result
}
Here's an example of me using it
let customDomain = "mycompanyname"
let test = "frank#mycompanyname.com"
if isValidEmail(testEmail: test, domain: customDomain) == true {
//Test succeedes... Here you would register the users as normal
print("register \(test)")
}else{
//Test fails... Here you might tell the user that their email doesn't check out
print("register failed")
}
Additionally, I would take a look at Apples App Distribution Guide for if you want to distribute your app locally to say an employee base.
Hope this helps.
You can do the following client and backend checks to enforce this:
On the client side, you can block sign-in when an invalid email domain is provided. If you are using some federated sign in with Google or Facebook, etc, you can on return check the currentUser.email and currentUser.delete the user if the email doesn't match your domain. Google also provides an 'hd' parameter to specify the user domain if you are using GSuite.
You can use Firebase Functions onCreate event to delete a user quickly every time one is created with an invalid email domain.
If you are using database rules, you can block access if the email doesn't match:
".read": "auth != null && auth.uid == $uid" && auth.token.email.matches(/.*#mydomain.com$/)
If you are using your own backend, when getting the ID token of a user, validate it, then get the email and make sure it matches your domain, if not, you can delete the user. The Firebase Admin SDKs provide the ability to verify an ID token and delete a user by UID.

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

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.

Resources