How to retrieve name of user in firebase - swift

I am creating an app (Xcode, swift) that has a profile page for each user and I want their name to appear on that page.
I have been able to get their email address through:
let email : String = (Auth.auth().currentUser?.email)!
How would I gather the users name? I have the users UID as well.
I am using firebase by the way

If you are not using Google or Facebook to log in with firebase, You need to manually create the profile for each user. See Update a user's profile

If you're using a social provider to sign in, you can get the display name from that provider through Firebase with:
Auth.auth().currentUser?.displayName
If you're signing in with another provider, the display name won't automatically be set, and you will (as Abdullah answered) have to create your own registration system where the user enters their name - and you then store it in the displayName property of Firebase Authentication.

To achieve what you requested, you either have to use a social auth provider (such as Google or Facebook) or change it yourself from the client, as the other answers suggest.
First of all, you would have to create a changeRequest, using the following code
let changeRequest = Auth.auth().currentUser?.createProfileChangeRequest()
Once the change request is created, you can change whatever basic information you need to (either the photo URL or the display name) with the following code:
changeRequest?.displayName = "Lorem ipsum"
changeRequest?.photoURL = "https://your_link/path_to_image.png"
Finally, you must send the change request to Firebase, which will handle it and possibly return an error for you to handle.
changeRequest?.commitChanges { error in
if let error = error {
print(error.localizedDescription)
// You can handle the given error here
return
}
}
As others have already pointed out, you can find this and more information on the official on the official Firebase docs website.

Related

How to get the user name/id of a google account linked with Dialog flow

I have integrated google assistant with my dialogflow agent. I need to get the user who is invoking the intent.
For eg, If an user account "ABC" have access to invoke my agent via Google assistant app, on the welcome intent I have to send a response like "Welcome ABC". How do I achieve this with google assistant app is my endpoint.
Thanks in Advance.
You have two questions here: How to get the user's name and how to get their id.
The first thing to realize is that this information is considered personally identifiable information (PII), so Google doesn't give it to you without the permission of the user. How you ask for that permission, and how it is delivered to you, depends on some of your exact needs.
User ID
Historically, you could get an anonymous user ID for the Assistant account. This would be different than the Google User ID that is available below and was meant to be a persistent identifier so you could keep track of returning users.
This has been deprecated, and if this is all you need, then you can create your own identifier and save it as part of the userStorage.
Requesting user information
The traditional way of getting their name is to request the user for permission to access their information. If you're using the actions-on-google library, you do this using the Permission object with something like this:
const options = {
// We just want permission to get their name
permissions: ['NAME'],
// Prompt them why we want the information
context: 'To address you by name'
};
conv.ask(new Permission(options));
If the user grants permission, the results will be available in conv.user.name. You should save this in the userStorage, since the permission is not persistent. So this might look something like:
var userStorageStr = conv.user.userStorage || '{}';
var userStorage = JSON.parse( userStorageStr );
var name = conv.user.name || userStorage.name;
userStorage.name = name;
// ...
conv.user.userStorage = JSON.stringify( userStorage );
With the multivocal library, you would indicate that the User/Name environment property is one of the Requirements for the action or intent you want. So this might be in your configuration as
Local: {
en: {
Requirements: {
"Action.multivocal.welcome": "User/Name"
}
}
}
The name will be available in the environment under User/Name.
If you're using JSON, then you need to use the user information helper. For Dialogflow, this would be under the payload.google.systemIntent property, while for the Actions SDK this would be in expectedInputs[0].possibleIntents[0]. You might specify something like this:
{
"intent": "actions.intent.PERMISSION",
"inputValueData": {
"#type": "type.googleapis.com/google.actions.v2.PermissionValueSpec",
"optContext": "To address you by name",
"permissions": [
"NAME"
]
}
}
The name will be under the originalDetectIntentRequest.payload.user.profile field if you are using Dialogflow and user.profile for the Action SDK.
All of this seems like a lot, just to get a name. And you can't get the email address if you want that in addition. But there are other options.
Requesting their Google Profile
Their Google Profile contains both their unique Google ID, their full name (in the "name" field, given_name, last_name, and typically some other information such as their email address (the email address isn't guaranteed since they can omit this from their profile, but is typically there). You would use Google Sign-In for the Assistant to request this information. There is some configuration required in the Action console, and then you would request permission to get it using the sign-in helper.
With the actions-on-google library, the line would be something like:
conv.ask(new SignIn());
Once the user granted it, you can get their profile in
conv.user.profile.payload
their name in
conv.user.profile.payload.name
and their email in, you guessed it,
conv.user.profile.payload.email
Note that unlike asking for the user information, the profile will be available in all future activity with you. You don't need to store it.
With multivocal, you would say that the User/IsAuthenticated environment setting is one of the Requirements for the action or intent you want. So this might be in your configuration as
Local: {
en: {
Requirements: {
"Action.multivocal.welcome": "User/IsAuthenticated"
}
}
}
The profile will be available in the environment under User/Profile, the name would be in User/Profile/name, and the email in User/Profile/email.
If you're using JSON, then you need to use the sign-in helper. For Dialogflow, this would be under the payload.google.systemIntent property, while for the Actions SDK this would be in expectedInputs[0].possibleIntents[0]. You might specify something like this:
{
"intent": "actions.intent.SIGN_IN",
"inputValueData": {}
}
You will get an identity token for the user in the originalDetectIntentRequest.payload.user.idToken field if you are using Dialogflow and user.idToken for the Action SDK. You will need to validate and decode this JWT. (The actions-on-google and multivocal libraries handle this step for you.)
The easiest would be to use Google Sign-In for the Assistant: https://developers.google.com/actions/identity/google-sign-in

Checking if a user already signed up

I built a custom authentication system using FirebaseAuthentication tokens.
My signup / login flow should work like this:
User presses login button
My server generates the authentication token and sends it to the client
Check if the user already exists (in the 'Auth' table or in my database?)
If true: sign in using FIRAuth.auth()?.signIn(withCustomToken:...
If false: Show a form to to enter custom information (name, etc..)
sign using FIRAuth.auth()?.signIn(withCustomToken:...
save the custom information to my database
My question is: How can I find out if the user has already signed up?
Would a publicly accessible database with only uid's be the way to go?
This is fairly opinion based, but yes, I would use a standalone DB that stores each user's username who has signed up. Then all that is required is a quick web request through a PHP file querying for any rows returned with that username.
The firebase sign in method will feedback in asynchronous callback.
FIRAuth.auth()?.signInWithEmail(email, password: password, completion: { (user , error) in
if let error = error {
print(error.localizedDescription)
return
}
self.signedIn(user)
})
If you haven't sign up yet. The error will print out
There is no user record corresponding to this identifier. The user may have been deleted.

Google Sign-In with Passportjs not getting authenticated

I'm using Sails with Passport for authentication. I'm using passport-google-oauth(OAuth2Strategy) and passport-facebook for enabling Google Sign-in.
I'm not too well-versed with Passport, so pardon me if this is a rookie question. I've set up login via Facebook and it works just fine. With Google, I do receive an authorization code after allowing access to the app, but the I'm eventually not authenticated. I'm guessing the same code should work for both Facebook and Google since the strategies are both based on oauth2.
I'm not even sure what code to share, since I'm using the auto-generated code from sails-generate-auth, but do let me know if there's anything else I can share.
Any ideas on why this might be happening? The app is locally hosted but that's unlikely to be the problem since I am getting to the authorization stage anyway.
I faced the same problem and it was located here in in api/services/passport.js:
// If the profile object contains a list of emails, grab the first one and
// add it to the user.
if (profile.hasOwnProperty('emails')) {
user.email = profile.emails[0].value;
}
// If the profile object contains a username, add it to the user.
if (profile.hasOwnProperty('username')) {
user.username = profile.username;
}
// If neither an email or a username was available in the profile, we don't
// have a way of identifying the user in the future. Throw an error and let
// whoever's next in the line take care of it.
if (!user.username && !user.email) {
return next(new Error('Neither a username nor email was available'));
}
The Google service was not returning a profile.username property.
Because of it, the user is not saved in the database and cannot be authenticated. Then the passport callback receives an empty user, so the function that handles errors is fired and the user is redirected to the login page.
This change allows to use the displayName property as the username:
// If the profile object contains a list of emails, grab the first one and
// add it to the user.
if (profile.hasOwnProperty('emails')) {
user.email = profile.emails[0].value;
}
// If the profile object contains a username, add it to the user.
if (profile.hasOwnProperty('username')) {
user.username = profile.username;
}
/** Content not generated BEGIN */
// If the username property was empty and the profile object
// contains a property "displayName", add it to the user.
if (!user.username && profile.hasOwnProperty('displayName')) {
console.log(profile); // <= Use it to check the content given by Google about the user
user.username = profile.displayName;
}
/** Content not generated END */
// If neither an email or a username was available in the profile, we don't
// have a way of identifying the user in the future. Throw an error and let
// whoever's next in the line take care of it.
if (!user.username && !user.email) {
return next(new Error('Neither a username nor email was available'));
}
You could also use the profile.id property because profile.displayName is not necessarily unique (ie: two Google accounts can have an identical displayName). But it is also true accross different services: a Twitter account could also have the same username than a Facebook account. If both register on your application, you will have a bug. This is a problem from the code generated by sails-generate-auth and you should adapt it with the behavior that you want.
I will propose a PR if this solution works for you too.
Alright, so this ultimately turned out to be a known issue with the API.
TL;DR: Enable the Google+ API and the Contacts API as mentioned here. (The Contacts API isn't required, as #AlexisN-o pointed out in the comments. My setup worked as desired with Contacts API disabled. This obviously depends on what scope you're using.)
I believe it's not a nice way of failing since this was an API error that was prevented from bubbling up. Anyway, I dug into passport.authenticate to figure out what was going wrong. This eventually calls the authenticate method defined in the package corresponding to the strategy (oauth2 in this case). In here (passport-google-oauth/lib/passport-google-oauth/oauth2.js) I found that the accessToken was indeed being fetched from Google, so things should be working. This indicated that there was a problem with the requests being made to the token urls. So I ventured a little further into passport-oauth2/lib/strategy.js and finally managed to log this error:
{ [InternalOAuthError: failed to fetch user profile]
name: 'InternalOAuthError',
message: 'failed to fetch user profile',
oauthError:
{ statusCode: 403,
data: '{
"error": {
"errors": [{
"domain": "usageLimits",
"reason": "accessNotConfigured",
"message": "Access Not Configured. The API (Google+ API) is not enabled for your project. Please use the Google Developers Console to update your configuration.",
"extendedHelp": "https://console.developers.google.com"
}],
"code": 403,
"message": "Access Not Configured. The API (Google+ API) is not enabled for your project. Please use the Google Developers Console to update your configuration."
}
}'
} }
This was the end of the hunt for me and the first result for the error search led to the correct answer. Weird fix though.

Parse - Unity3D : How to create a user after a Facebook Connect

'm using the Facebook SDK 6.0 for Unity3D.
After my user accept the connection, I want to save his ID, email etc ... on a Parse database, and have the possibility to get some info from this database for this player (for exemple : the list of unlock levels).
How can I do it ?
I know how create an object, but I want to know, after a connection on Facebook, how to save the user and some details on Parse, without using the Parse login (as on the official Parse tutorial).
I can't understand.
Thank you very very much in advance for your help.
Best regards,
AB
You can try saving this information in the local ParseUser Object. Just add custom fields with the necessary information. For more complex solutions you can create a custom parse object to save the information.
https://parse.com/docs/unity_guide#users
var user = new ParseUser()
{
Username = "my name",
Password = "my pass",
Email = "email#example.com"
};
// other fields can be set just like with ParseObject
user["IsUnlocked"] = true;
Task signUpTask = user.SignUpAsync();
and for Facebook there is a special signup method in the ParseFacebookUtils class
https://parse.com/docs/unity_guide#fbusers
Task<ParseUser> logInTask = ParseFacebookUtils.LogInAsync(userId, accessToken, tokenExpiration);

Facebook oAuth user details with MVC 4

I am using the OAuthWebSecurity with MVC to allow users of my website to login using Facebook's oAuth. Everything works fine, and I have a test user authenticating fine.
My question is based on the details Facebook can provide. I am currently returning the user details using the following...
AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication();
This will give the follwing details:
UserName (email)
ProviderUserId
I also get a ExternalData object which has:
UserName
Name
Gender
Do you know if it's possible to get further data, maybe DoB, photo etc?
Pardon me for not framing me the full answer. I am just supplying a link. Please check
http://blue-and-orange.net/articles/facebook/displaying-facebook-user-data-in-aspnet-mvc-4/
Everything is explained here.
For setting permission you can go through this documentation
https://developers.facebook.com/docs/facebook-login/permissions/
if you were to request a user's email address, but never asked them for the 'email' permission, you would receive an OAuth error as show below.
try {
var client = new FacebookClient("my_access_token");
dynamic result = client.Get("me/email");
var email = (string)result.email;
}
catch (FacebookOAuthException) {
// The access token expired or the user
// has not granted your app 'email' permission.
// Handle this by redirecting the user to the
// Facebook authenticate and ask for email permission.
}