Apple sign in rejection [closed] - appstore-approval

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 3 years ago.
Improve this question
I have uploaded an app with Apple SignIn, In that after sign in success we are taking user info like First name, Last name , email But i got a rejection from apple .
1.1 Legal: Privacy - Data Collection and Storage
Guideline 5.1.1 - Legal - Privacy - Data Collection and Storage
We noticed that your app requires users to register with personal information that is not directly relevant to your app's core functionality. Specifically, the following fields are required but do not appear to be directly relevant to your app's core functionality:
First and Last Name (when using Sign In with Apple)
Email (when using Sign In with Apple)
Name and Email are supplied by Sign In with Apple, so asking for these separately is not appropriate. We encourage you to utilize Sign In with Apple and honor its intentions, to respect users privacy and personal information.
Next Steps
To resolve this issue, please either remove all required fields that are not relevant to the app or make those fields optional. Information requested during registration must be relevant to the features the app provides.

*Save all the data in keychain When you get the success data didCompleteWithAuthorization and after use keychain data.
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
// Create an account in your system.
// For the purpose of this demo app, store the these details in the keychain.
KeychainItem.currentUserIdentifier = appleIDCredential.user
KeychainItem.currentUserFirstName = appleIDCredential.fullName?.givenName
KeychainItem.currentUserLastName = appleIDCredential.fullName?.familyName
KeychainItem.currentUserEmail = appleIDCredential.email
print("User Id - \(appleIDCredential.user)")
print("User Name - \(appleIDCredential.fullName?.description ?? "N/A")")
print("User Email - \(appleIDCredential.email ?? "N/A")")
print("Real User Status - \(appleIDCredential.realUserStatus.rawValue)")
}
}
For changing any state of credentials you can track with the following code.
let appleIDProvider = ASAuthorizationAppleIDProvider()
appleIDProvider.getCredentialState(forUserID: KeychainItem.currentUserIdentifier) { (credentialState, error) in
switch credentialState {
case .authorized:
// The Apple ID credential is valid.
break
case .revoked:
// The Apple ID credential is revoked.
break
case .notFound:
// No credential was found, so show the sign-in UI.
}
default:
break
}
}

Related

Flutter dynamic links test

Edited Question :
I have an issue with Firebase Dynamic Links Packag , My goal is getting know if new user installed and opend my app for first time to give him a rewards like 10 point . I tried to search everywhere but no answer,in firebase website there is option to know if user install for first time.
My Goal is : Getting value for first time install & how to debug this code ?
initDynamicLinks when app Lanched :
void initDynamicLinks() async {
FirebaseDynamicLinks.instance.onLink(
onSuccess: (PendingDynamicLinkData dynamicLink) async {
final Uri deepLink = dynamicLink?.link;
if (deepLink != null) {
Navigator.pushNamed(context, deepLink.path);
}
},
onError: (OnLinkErrorException e) async {
print('onLinkError');
print(e.message);
}
);
final PendingDynamicLinkData data = await FirebaseDynamicLinks.instance.getInitialLink();
final Uri deepLink = data?.link;
if (deepLink != null) {
Navigator.pushNamed(context, deepLink.path);
}
}
.
You're mixing two things here.
The First-opens tab gives you the number of unique users who clicked on your Firebase Dynamic Link for the first time.
If you want to know how many unique users used your app, by clicking the Firebase Dynamic Link or not to get to your app, you have to implement the Firebase Analytics plugin to your app.
This way you'll get access to Dashboards showing you how many Unique users you have.
EDIT
Reading your comment, looks like your question is not related to your problem.
What you want here is to attribute rewards for users who invited their friends thanks to a referral link.
Since I never implemented this witout a dedicated backend, the only thing I can share is a use-case I used some time ago explaining the logic to follow to implement it.
https://firebase.google.com/docs/dynamic-links/use-cases/rewarded-referral
EDIT 2
The logic explained in the documentation is the following :
1- Generate a Dynamic Link for UserA.
2- UserA sends the Dynamic Link to someone (called UserB).
3- When UserB starts the app from a Dynamic Link, retrieve the referral informations in the app (to retrieve UserA's informations)
4- Call a route on your backend to attribute the reward to UserA (and check if UserB is really a new user in your database).
The point is, you shouldn't manage a referral/referrer relationship on the client's side (it would be way too easily abused/hacked).
It's the job of a backend (or cloud function) to manage this.
Once you have received the link clickthrough in your app use the google_analytics package to log an event.
Related thread here:
Flutter log event with google analytics
To be honest i have never used Firebase Dynamic Links , But if your Goal is to Achieve a first open or login token , you can always use the Sharedpreferences package , in my case iam using it to navigate to different pages passed on the first login value .
i think that Sharedpreferences is more reliable and easier than what you are trying to achieve with firebase
UPDATE:
what you actually want to do is make a firebase collection with IMEI numbers , when there is a new IMEI that means a new user , when that IMEI is in your collection that means that the app is not installed for the first time ,
you can use this package imei_plugin to get IMEI number and store it on firebase

Firebase + Flutter : get platform user used to sign in

I have an app with 3 sign in methods: Google, Facebook & mail.
I want to show the users that are signed in with mail a different screen.
Is it possible to get the sign in method form the package firebase authentication?
I know I can fix this by using firestore & checking if a statement is true or false. But that will cost me a read every time a user opens the app...
This seems to be what you want: https://firebase.google.com/docs/reference/android/com/google/firebase/auth/FirebaseUser.html#getProviderData()
In my app where I use Google logins only, I have firebaseUser.providerData[1].providerId == 'google.com'.
Btw, firebaseUser.providerData[0].providerId == 'firebase'.
I guess you could check them all and look for what providers you get for different kinds of users.
Edit: here's what I get when logging in with e-mail: https://postimg.cc/BXWGGN6h
Firebase has a special property providerId. But, as mentioned #GazihanAlankus it always returns firebase.
And, the property firebaseUser.providerData[1].providerId sometimes not exists (for example when user used anonymous login).
So, we should use appropriate approaches, for example:
FirebaseUser user = await _firebaseAuth.currentUser();
if (user.providerData.length < 2) {
// do something
}
else {
print(res.providerId);
}
The list of values, that are returned by property providerId:
EmailAuthProviderID: password
PhoneAuthProviderID: phone
GoogleAuthProviderID: google.com
FacebookAuthProviderID: facebook.com
TwitterAuthProviderID: twitter.com
GitHubAuthProviderID: github.com
AppleAuthProviderID: apple.com
YahooAuthProviderID: yahoo.com
MicrosoftAuthProviderID: hotmail.com
I got this list from the cool research here What is the full list of provider id's for firebase.UserInfo.providerId?
In my app I used
FirebaseAuth.instance.currentUser.providerData[0].providerId == 'google.com'.,
cause providerData[1] doesn't contain any value
For anyone reading this in 2022, Firebase now has nice new docs for Flutter and in it they have this, which I personally found super useful:
if (user != null) {
for (final providerProfile in user.providerData) {
// ID of the provider (google.com, apple.cpm, etc.)
final provider = providerProfile.providerId;
// UID specific to the provider
final uid = providerProfile.uid;
// Name, email address, and profile photo URL
final name = providerProfile.displayName;
final emailAddress = providerProfile.email;
final profilePhoto = providerProfile.photoURL;
}
}
Source: Firebase documentation
But that will cost me a read every time a user opens the app. THIS IS TRUTH!
Alternatively, you can create your own app DB using SQFLite, and create only one table (user) in that, having a field of signUpMethod having possible values are google, facebook and mail. Whenever you opens the app, first check that in your db, if this is mail, redirect to another screen which you want, else call firebase service
Cheers!

Firebase Auth: Is it possible to see user's Twitter ID?

I have just implemented the Twitter login to my Firebase web app. When the user successfully login, I'd like to see the user's Twitter ID (to enable Twitter-based communication among users).
According to the document (https://firebase.google.com/docs/auth/web/manage-users), the provider specific information is under providerData of the user info.
Under the providerData, I see the following
displayName: "Satoshi Nakajima" (as I expected)
email: null (as I expected)
phoneNumber: null (as I expected)
photoURL: "https://abs.twimg.com/..." (as I expected)
providerId: "twitter.com" (of course)
uid: "1129128..." (what is this?)
The uid seems like a unique id, but it is different from the Twitter ID we usually use, such as #snakajime (which is mine).
I am wondering why I don't see the Twitter id here. Am I missing something? Is there any API to get the Twitter ID from this strange uid?
You can actually get it immediately after sign-in, via AdditionalUserInfo.
Here is an example with the web API:
firebase.auth().signInWithPopup(new firebase.auth.TwitterAuthProvider())
.then((userCredential) => {
// Get the Twitter screen name.
console.log(userCredential.additionalUserInfo.username);
})
.catch((error) => {
// An error occurred.
});
As far as I know, the screen name you are looking for is not included as part of the Twitter OAuth provided through Firebase, but the uid that you have found is indeed the user's twitter user ID.
Using this ID you can use the Twitter API to get details about the user by passing it to the twitter API users/show endpoint. Since you plan on providing Twitter based communication, you will likely need to use this API anyway.
e.g.:
GET https://api.twitter.com/1.1/users/show.json?user_id={the_uid_from_provider_data}
RESPONSE:
{
"id": {the_uid_from_provider_data},
"id_str": "{the_uid_from_provider_data}",
"name": "Snakajime",
"screen_name": "snakajime", // <--- Here is the screen name you are looking for
...
}

How to use dialogflow Fulfillment Inline Editor to save users names and moods on a realtime database?

I built action on google using dialogflow for experience sampling purpose.
It's idea is: it asks specific users about their mood 3 times per day.
It sends these users then every week a weekly overview about their mood after it has been analysed by researchers.
So I need to save each user info with his mood entries on a database so they can be accessed later by researchers, analysed and sent back to users.
I'm using dialogflow fulfilment with index.js to connect to Firebase database to save the entries.
This agent should be integrated as action on google
On the database I get users names and moods but they are not related to each other so I cannot know which user entered which mood and, also I cannot do the userID check.
I would really appreciate if anybody could help me with the functions since I am totally unfamiliar with node.js or databases but I have to do it that way.
here is my code.
// See https://github.com/dialogflow/dialogflow-fulfillment-nodejs
// for Dialogflow fulfillment library docs, samples, and to report issues
'use strict';
const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');
//initialise DB connection
const admin = require('firebase-admin');
admin.initializeApp();
process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements
exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({ request, response });
console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
console.log('Dialogflow Request body: ' + JSON.stringify(request.body));
function saveName(agent) {
const nameParam = agent.parameters.name;
const context = agent.getContext('awaiting_name_confirm');
const name = nameParam || context.parameters.name;
agent.add('Hi ' + name + ' Are you ready to answer my question?' || 'Hi' + name + 'Have you got a moment for me? ' );
//agent.add('Hi' + name + 'Have you got a minute for me? ');
return admin.database().ref('/names').push({name: name}).then((snapshot)=>
{
console.log('database write sucessful: ' + snapshot.ref.toString());
});
}
function saveMood(agent) {
const moodParam = agent.parameters.mood;
const mood = moodParam;
agent.add('That is good! keep it up. Thanks for sharing with me! Bye ');
//agent.add('Hi' + name + 'Have you got a minute for me? ');
return admin.database().ref('/moods').push({mood: mood}).then((snapshot)=>
{
console.log('database write sucessful: ' + snapshot.ref.toString());
});
}
// Run the proper function handler based on the matched Dialogflow intent name
let intentMap = new Map();
intentMap.set('Get Name', saveName);
intentMap.set('Confirm Name Yes', saveName);
// intentMap.set('Confirm Name Yes', getName);
intentMap.set('attentiveness', saveMood);
agent.handleRequest(intentMap);
});
You have a few issues in your code and approach that you'll need to address:
You need to design your database so that you can associate the user's mood with their account. (And possibly other user information, such as their name or email address, while you're at it.)
You need a unique identity for the person.
A person's name isn't a unique identity. Two people may have the same name, or the system may hear the name differently each time, so you need to have a way to know who you're talking to.
You also need to know their email address and possibly other information, so you can send them their report at the end of the week.
You need to make sure you have their identity between calls to your Action during the same conversation.
Fortunately, you do one thing that is typically missed - you make your calls to the database using Promises. So that part works.
Unique Identity
Your example code asks the user for their name, which it sounds like you intend to use as their identity. Unfortunately, this is a bad idea for a few reasons:
The name isn't an identity. What happens if two people with the same name access your Action?
Names are easily discoverable, so other people could use it and report misleading information. This may not be too serious in your case, but it can still have trustworthiness implications.
Names can be Personally Identifiable Information (PII), so may be covered by additional privacy laws.
Users might want to terminate their account, and can't do this without "changing" their name.
Additionally, you may need other identity information later, such as their email address, and asking for that every time may become troublesome.
You have a few ways to deal with this:
If you're developing for the Google Assistant, you can also use Google Sign In for Assistant which will tell you the user's Google identifier, which you can use as a unique ID. You also get their email address and name as part of their profile.
You can ask for this information (name, email, etc) and save it against a user ID that you generate or a user name the user provides. This ID becomes the identifier. If you're developing for the Google Assistant, you can save this ID in the user's private storage - only you and the user have access to it or can delete it. If not, you may need to use the database to look up the ID. More on this later.
You may wish to use variants on this later point, depending what information you're getting and how you want the user to identify themselves every time. But the important part is that they need to identify themselves with something unique and that you can easily capture.
Use identity in the same session
If you're using Google Sign In, you don't have to worry about this. You'll get the same ID each session and for each call during a session.
If you're using the user's private storage with the Google Assistant, you'll have this as part of the userStore object.
But if you're not, you need to make sure that you get the user's ID in an early intent, and saving this as part of a Context so it is preserved in between calls to your webhook. In subsequent handlers, you can get the ID out of the context and then use it to access other information.
You don't need to store it in the database at this point. All you have is an identifier - this becomes the key that you will use for other information. You just need to remember it for later parts of the conversation.
So in your saveName() function, it might look something like
function saveName(agent) {
const nameParam = agent.parameters.name;
agent.add('Hi ' + nameParam + ' Are you ready to answer my question?');
agent.setContext({
name: 'user',
lifespan: 99,
parameters: {
id: nameParam
}
};
}
As an aside - your handler seems to try to determine if this is the user saying their name, or confirming their name. This is probably better handled as separate intents and separate handlers. Trying to combine them will confuse things.
Structuring and Accessing your Database
We have an ID. We have the user reporting the data. How do we associate the two?
There are a lot of ways to structure the data, and Firebase goes into some detail depending on how you intend to use it, access it, and make it available to the users or others.
In this case, it seems pretty straightforward that you want to store records about the user. Each record can use their ID as a key, and then contain some information about the user, including their mood.
One nice thing about the Firebase database is that you can (mostly) treat it like a Javascript object. If we think about it this way, it might look something like
{
"user": {
"id1":{...},
"id2":{...},
"id3":{
"moods": [
{"mood":"good"},
{"mood":"tired"}
]
},
"id4":{...}
}
}
And so forth. With Firebase, we would reference the moods of user "id3" with a path such as user/id3/moods. If we have the user id in a variable name, we might use the following code to get that reference
var ref = admin.database().ref('user').ref(name).ref('moods');
and then use code such as this to push an object with the mood onto the array (and return the Promise that we need to do):
var obj = {
mood: mood
};
return ref.push( obj ).then( snapshot => {
// Do stuff, including acknowledge to the user you saved it.
});
Keep in mind that you may want to also use this to store more information about each user (such as their name or email) on the user level, or more about the moods (such as a timestamp) in the mood object.

Cannot Create User Profile in Firebase

First off, thanks for taking the time; this is my first question posted!
I'm in the middle of coding my first mobile application in React Native: a stats managing App for my fraternity. Right now, I would like an admin user to be able to add other users to the app and set their initial profile information (first name, last name, position, dues paid etc).
Once they submit the details, the code below tells firebase to create a new user using the provided email and password, then adds their other profile information under the user parent in the Realtime Database.
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(() => {
console.log(key);
firebase.database().ref('/ChapterName/users/' + key)
.set({ firstName, lastName, rank, position, goodStanding, dues, communityService, chapters, mixers, brotherhoods });
})
The JSON tree created can be seen here: Firebase Tree
My problem is that when the new user logs in, I cannot find a way to access their profile information...ideally, I would set the key of each child under 'user' to the user's email: that way they could login and I could match their email to the key of their profile info and fetch it that way. Unfortunately, keys must be UTF-8 encoded and don't allow for me to include '# or .'
Does anyone know a way around this? I feel as if the firebase Admin API could be a solution but I can't seem to wrap my head around it.
Inside react-native with firebase, if they user already login and you already integrate firebase with redux, you can access the current user information inside redux using this line
state.firebase.profile
as per my suggestion, I think it's best for to integrate
react-native app + react-native-firebase + react-redux-firebase
thus, you dont have to use web firebase function as it's already exist in props.
if you need to update the profile after user already created you can use something like this
this.props.firebase.auth().createUserAndRetrieveDataWithEmailAndPassword(email, password).then((user) => {
this.props.firebase.updateProfile(
{
name: 'Hazim',
age: 24,
mode: 'Rampage'
}
)
}).catch((error) => {
//Error value
})
and inside any component, you can get current user info with connect function like this.
class Home extends Component {
}
export default compose(
firebaseConnect(),
connect( state => {
profile: state.firebase.profile
})
)(Home)

Resources