I am creating a program that uses Firebase Google auth to SignIn/SignUp in c#. And Firestore as a database. I need to save the data of new users who signup. But I don't know how to differentiate new user who signs up and old user who sign in using google auth.
How to find this
Nothing i tried works.
private void OnSignIn()
{
GoogleSignIn.Configuration = configuration;
GoogleSignIn.Configuration.UseGameSignIn = false;
GoogleSignIn.Configuration.RequestIdToken = true;
AddToInformation("Calling SignIn");
GoogleSignIn.DefaultInstance.SignIn().ContinueWith(OnAuthenticationFinished);
}
internal void OnAuthenticationFinished(Task<GoogleSignInUser> task)
{
if (task.IsFaulted)
{
using (IEnumerator<Exception> enumerator = task.Exception.InnerExceptions.GetEnumerator())
{
if (enumerator.MoveNext())
{
GoogleSignIn.SignInException error = (GoogleSignIn.SignInException)enumerator.Current;
AddToInformation("Got Error: " + error.Status + " " + error.Message);
}
else
{
AddToInformation("Got Unexpected Exception?!?" + task.Exception);
}
}
}
else if (task.IsCanceled)
{
AddToInformation("Canceled");
}
else
{
AddToInformation("Welcome: " + task.Result.DisplayName + "!");
// AddToInformation("User Status: "+ task.Result.)
AddToInformation("Email = " + task.Result.Email);
AddToInformation("Google ID Token = " + task.Result.IdToken);
AddToInformation("Email = " + task.Result.Email);
SignInWithGoogleOnFirebase(task.Result.IdToken);
}
}
private void SignInWithGoogleOnFirebase(string idToken)
{
Credential credential = GoogleAuthProvider.GetCredential(idToken, null);
auth.SignInWithCredentialAsync(credential).ContinueWith(task =>
{
AggregateException ex = task.Exception;
if (ex != null)
{
if (ex.InnerExceptions[0] is FirebaseException inner && (inner.ErrorCode != 0))
AddToInformation("\nError code = " + inner.ErrorCode + " Message = " + inner.Message);
}
else
{
AddToInformation("Sign In Successful.");
}
});
}
When SignInWithCredentialAsync completes, you get back a FirebaseUser object. This object has Metadata property with two values: CreationTimestamp and LastSignInTimestamp. If those values are the same or really close to each other, the user was just created.
I'm trying to make a database that stores dental records. I'm using firesharp library. I made a form called Register UI that registers details of new patients. Then another form called DatabaseUI where records could be retrieved from the database. Here is what my firebase structure looks like:
Firebase Parent/child structure (General Records>Patient Name>PatientDetails)
I used this code to connect to firebase:
{
IFirebaseConfig config = new FirebaseConfig {
AuthSecret = "\\mysecretcode",
BasePath = "\\firebase url"
};
IFirebaseClient client;
client = new FireSharp.FirebaseClient(config);
The Register Form code looks like this ("Data" is a class):
public async void subbtn_Click(object sender, EventArgs e) {
//For Gender Radio Buttons
string gender = "";
if (maleradio.Checked) {
gender = "Male";
} else {
gender = "Female";
}
//Data to be stored into Firebase
var data = new Data {
Name = lastnametbox.Text + ", " + firstnametbox.Text + " " + mitbox.Text,
Age = agetbox.Text,
Gender = gender,
Birthdate = dateTimePicker1.Value.Date.ToString("MM/dd/yyyy")
};
if (selectdbase.Text == "General") //Store in General Records Category
{
SetResponse response = await client.SetAsync("General Records/" + data.Name, data);
Data result = response.ResultAs < Data > ();
} else //Store in Orthodontics Records Category
{
SetResponse resp2 = await client.SetAsync("Orthodontics Records/" + data.Name, data);
Data result = resp2.ResultAs < Data > ();
};
MessageBox.Show("Registered!");
this.Close();
}
Here's the code for the database form:
private async void searchbtn_Click(object sender, EventArgs e) {
FirebaseResponse response = await client.GetAsync("General Records/" + data.Name); //'data' is unknown here
Data obj = response.ResultAs < Data > ();
searchtbox.Text = obj.Name;
}
Adding of records works fine. In retrieving from firebase, the error is at "data.Name" since that variable is in the RegistrationUI Form. The output on the textbox is always null. What path after the "General Records/" should I put since the nodes under this are varying (since they are names of patients)? Please please help.
Hello people im new with Unity and C#.
I have this script to create/login users and post in firebase database (with email and password).
I copied it from a youtube tutorial with a little few modifications
using System.Collections;
using System.Collections.Generic;
using FullSerializer;
using Proyecto26;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using Firebase.Auth;
public class PlayerScores : MonoBehaviour
{
public Text scoreText;
public InputField getScoreText;
public InputField emailText;
public InputField usernameText;
public InputField passwordText;
private System.Random random = new System.Random();
User user = new User();
private string databaseURL = "testingurl";
private string AuthKey = "testingapikey";
public static fsSerializer serializer = new fsSerializer();
public static int playerScore;
public static string playerName;
private string idToken;
public static string localId;
private string getLocalId;
private void Start()
{
playerScore = random.Next(0, 101);
scoreText.text = "Score: " + playerScore;
}
public void OnSubmit()
{
PostToDatabase();
Debug.Log("datos subidos a database");
}
public void OnGetScore()
{
GetLocalId();
}
private void UpdateScore()
{
scoreText.text = "Score: " + user.userScore;
}
private void PostToDatabase(bool emptyScore = false, string idTokenTemp = "")
{
if (idTokenTemp == "")
{
idTokenTemp = idToken;
}
User user = new User();
if (emptyScore)
{
user.userScore = 0;
}
RestClient.Put(databaseURL + "/" + localId + ".json?auth=" + idTokenTemp, user);
}
private void RetrieveFromDatabase()
{
RestClient.Get<User>(databaseURL + "/" + getLocalId + ".json?auth=" + idToken).Then(response =>
{
user = response;
UpdateScore();
});
}
public void SignUpUserButton()
{
SignUpUser(emailText.text, usernameText.text, passwordText.text);
}
public void SignInUserButton()
{
SignInUser(emailText.text, passwordText.text);
}
private void SignUpUser(string email, string username, string password)
{
string userData = "{\"email\":\"" + email + "\",\"password\":\"" + password + "\",\"returnSecureToken\":true}";
RestClient.Post<SignResponse>("https://www.googleapis.com/identitytoolkit/v3/relyingparty/signupNewUser?key=" + AuthKey, userData).Then(
response =>
{
string emailVerification = "{\"requestType\":\"VERIFY_EMAIL\",\"idToken\":\"" + response.idToken + "\"}";
RestClient.Post(
"https://www.googleapis.com/identitytoolkit/v3/relyingparty/getOobConfirmationCode?key=" + AuthKey,
emailVerification);
localId = response.localId;
playerName = username;
PostToDatabase(true, response.idToken);
Debug.Log("SingUp Correcto");
}).Catch(error =>
{
Debug.Log("falta email/password");
Debug.Log(error);
});
}
private void SignInUser(string email, string password)
{
string userData = "{\"email\":\"" + email + "\",\"password\":\"" + password + "\",\"returnSecureToken\":true}";
RestClient.Post<SignResponse>("https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPassword?key=" + AuthKey, userData).Then(
response =>
{
string emailVerification = "{\"idToken\":\"" + response.idToken + "\"}";
RestClient.Post(
"https://www.googleapis.com/identitytoolkit/v3/relyingparty/getAccountInfo?key=" + AuthKey,
emailVerification).Then(
emailResponse =>
{
fsData emailVerificationData = fsJsonParser.Parse(emailResponse.Text);
EmailConfirmationInfo emailConfirmationInfo = new EmailConfirmationInfo();
serializer.TryDeserialize(emailVerificationData, ref emailConfirmationInfo).AssertSuccessWithoutWarnings();
if (emailConfirmationInfo.users[0].emailVerified)
{
idToken = response.idToken;
localId = response.localId;
GetUsername();
Debug.Log("Login Correcto");
SceneManager.LoadScene("SignInEdit"); //para logear correctamente solo necesita que el email y password sean correctos, el username no importa.
}
else
{
Debug.Log("You are stupid, you need to verify your email dumb");
}
});
}).Catch(error =>
{
Debug.Log(error);
});
}
private void GetUsername()
{
RestClient.Get<User>(databaseURL + "/" + localId + ".json?auth=" + idToken).Then(response =>
{
playerName = response.userName;
});
}
private void GetLocalId()
{
RestClient.Get(databaseURL + ".json?auth=" + idToken).Then(response =>
{
var username = getScoreText.text;
fsData userData = fsJsonParser.Parse(response.Text);
Dictionary<string, User> users = null;
serializer.TryDeserialize(userData, ref users);
foreach (var user in users.Values)
{
if (user.userName == username)
{
getLocalId = user.localId;
RetrieveFromDatabase();
break;
}
}
}).Catch(error =>
{
Debug.Log(error);
});
}
}
my problem is I cant save my firebase login between scenes, When I change scene I cant interact anymore with my firebase database.
I tried make a dontdestroyonload script and add a unity gameobject what is containing my PlayerScore script, but dont worked.
I readed im need to store my userid in a static variable to call it from anywhere but I dont know how because im prettly new with c# coding
Can someone give some guidance?, thanks.
PS: the script of above need another 3 script to works, where store/get some values.
If is necessary I add them.
I think that there might be some confusion here as I see a reference to the official Firebase Unity SDK mixed with raw REST calls in RestClient. I'll answer this assuming that you're ok with using the Unity SDK. This is a far simpler integration than attempting to manually use the Firebase SDK (and gets you nice benefits - such as local caching).
1) Firebase Authentication
Once Firebase Authentication is initialized, FirebaseAuth.DefaultInstance.CurrentUser will always contain your currently signed in user or null if the user is not signed in. This value is actually stored in C++ and accessed through C#, meaning that it doesn't actually know about or abide by Unity's typical object lifecycles. That means that once you've signed in a user, this value will always hold the current user without the need to persist it across scene boundaries. In fact, this value is even preserved across runs of your game (meaning that your players don't have to log in every time).
A warning about this though: CurrentUser is updated asynchronously -- that is that there is no real guarantee that CurrentUser is up to date -- so it's generally safe to register a StateChanged listener as Puf suggested from the documentation:
Firebase.Auth.FirebaseAuth auth;
Firebase.Auth.FirebaseUser user;
// Handle initialization of the necessary firebase modules:
void InitializeFirebase() {
Debug.Log("Setting up Firebase Auth");
auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
auth.StateChanged += AuthStateChanged;
AuthStateChanged(this, null);
}
// Track state changes of the auth object.
void AuthStateChanged(object sender, System.EventArgs eventArgs) {
if (auth.CurrentUser != user) {
bool signedIn = user != auth.CurrentUser && auth.CurrentUser != null;
if (!signedIn && user != null) {
Debug.Log("Signed out " + user.UserId);
}
user = auth.CurrentUser;
if (signedIn) {
Debug.Log("Signed in " + user.UserId);
}
}
}
void OnDestroy() {
auth.StateChanged -= AuthStateChanged;
auth = null;
}
I would highly recommend watching my tutorial on Firebase Authentication to see how I think about integrating this with a game. The link you shared is appropriate, but I'm a little curious about the various REST calls I see in your code.
If you're using the Firebase Unity SDK, email/password authentication should be as easy as:
auth.CreateUserWithEmailAndPasswordAsync(email, password).ContinueWith(task => {
if (task.IsCanceled) {
Debug.LogError("CreateUserWithEmailAndPasswordAsync was canceled.");
return;
}
if (task.IsFaulted) {
Debug.LogError("CreateUserWithEmailAndPasswordAsync encountered an error: " + task.Exception);
return;
}
// Firebase user has been created.
Firebase.Auth.FirebaseUser newUser = task.Result;
Debug.LogFormat("Firebase user created successfully: {0} ({1})",
newUser.DisplayName, newUser.UserId);
});
to create a user and
auth.SignInWithEmailAndPasswordAsync(email, password).ContinueWith(task => {
if (task.IsCanceled) {
Debug.LogError("SignInWithEmailAndPasswordAsync was canceled.");
return;
}
if (task.IsFaulted) {
Debug.LogError("SignInWithEmailAndPasswordAsync encountered an error: " + task.Exception);
return;
}
Firebase.Auth.FirebaseUser newUser = task.Result;
Debug.LogFormat("User signed in successfully: {0} ({1})",
newUser.DisplayName, newUser.UserId);
});
to sign them in. That is, there should be no need to use RestClient.
2) Realtime Database
Once you're authenticated, any calls to the Firebase Realtime Database SDK will automatically use the CurrentUser value (as I mentioned before - it persists on the C++ side of the SDK).
If you're hoping to use rules to secure user data such as:
{
"rules": {
"users": {
"$user_id": {
// grants write access to the owner of this user account
// whose uid must exactly match the key ($user_id)
".write": "$user_id === auth.uid"
}
}
}
}
Then writing data:
Database.DefaultInstance.GetReference($"/users/{FirebaseAuth.DefaultInstance.CurrentUser.UserId}/mySecret").SetValueAsync("flowers");
should just work.
I hope that all helps!
--Patrick
The Firebase SDK automatically persists the authentication state, and tries to restore it automatically too. You'll just need to write code to pick it up, which involves attaching a listener to the auth state.
See the first snippet in the Firebase documentation on getting the currently signed in user:
The recommended way to get the current user is by setting a listener on the Auth object:
Firebase.Auth.FirebaseAuth auth;
Firebase.Auth.FirebaseUser user;
// Handle initialization of the necessary firebase modules:
void InitializeFirebase() {
Debug.Log("Setting up Firebase Auth");
auth = Firebase.Auth.FirebaseAuth.DefaultInstance;
auth.StateChanged += AuthStateChanged;
AuthStateChanged(this, null);
}
// Track state changes of the auth object.
void AuthStateChanged(object sender, System.EventArgs eventArgs) {
if (auth.CurrentUser != user) {
bool signedIn = user != auth.CurrentUser && auth.CurrentUser != null;
if (!signedIn && user != null) {
Debug.Log("Signed out " + user.UserId);
}
user = auth.CurrentUser;
if (signedIn) {
Debug.Log("Signed in " + user.UserId);
}
}
}
void OnDestroy() {
auth.StateChanged -= AuthStateChanged;
auth = null;
}
I have this line which needs to recieve a message from the discord text channel.
choice = video[int.Parse(CommandHandler.message .Content)-1].Url;
I tried a lot of things, including searching in the api but I don't have a clue.
Here is the command
[Command("join", RunMode= RunMode.Async), Summary("joins voice channel")]
public async Task joinvoice([Remainder, Summary("The text to echo")] string searchP="")
{
IVoiceChannel voicechannel = (CommandHandler.Last as IGuildUser).VoiceChannel;
if (voicechannel == null)
{
await ReplyAsync("u have to be in a channel first");
return;
}
string choice = "";
VideoSearch SearchRisolts = new VideoSearch();
if (searchP != "")
{
if (searchP.Contains("https://"))
choice = searchP;
else
{
List<VideoInformation> video = SearchRisolts.SearchQuery(searchP, 1);
await ReplyAsync("1) " + video[0].Title + "\n\n2) " + video[1].Title + "\n\n3) " + video[2].Title);
choice = video[int.Parse(CommandHandler.message .Content)-1].Url;//here i need to recive a message from the chat
}
}
if (voicechannel != Program.voicechannel)
{
Program.audioClient = await voicechannel.ConnectAsync();
Program.voicechannel = voicechannel;
}
if (Program.audioClient!=null)
await SendAsync(Program.audioClient, choice);
}
The class containing this function should derive from BaseModule<ICommandContext>
This BaseModule contains the Context, which in place contains the message you are looking for.
Context.Message.Content
I have this script to interact with my database which is on mySql
string dataSubmitURL = "http://localhost/HighScore/AddScore.php?";
string dataGetURL = "http://localhost/HighScore/GetScore.php?";
// Use this for initialization
void Start () {
StartCoroutine(GetScores());
}
// Update is called once per frame
void Update () {
}
IEnumerator PostScores(string playerName, int score) {
string submitURL = dataSubmitURL + "name="+ playerName + "&score=" + score;
print(submitURL);
WWW submitData = new WWW(submitURL);
yield return submitData;
if (submitData.error != null)
{
Debug.LogError("Error occur when Submitting data : " + submitData.error);
Debug.LogError("Error occur when Submitting data : " + submitData.text);
Debug.LogError("Error occur when Submitting data : " + submitData.responseHeaders);
//submitData.text
}
else {
print(" Submitted");
}
IEnumerator GetScores() {
WWW getData = new WWW(dataGetURL);
yield return getData;
if (getData.error != null)
{
Debug.LogError("There was an error getting the high score: " + getData.error);
}
else {
print(getData.text);
}
}
}
But the problem is i am getting
There was an error getting the high score: Empty reply from server
Although these both urls
string dataSubmitURL = "http://localhost/HighScore/AddScore.php?";
string dataGetURL = "http://localhost/HighScore/GetScore.php?";
working fine in browser when i directly put it. I also added this crossDomain.xml in my root folder so that it can accessible to all. What I am doing wrong.
<?xml version="1.0"?>
<cross-domain-policy>
<allow-access-from domain="*"/>
</cross-domain-policy>
I don't know what was the problem all the code is correct and it works by changing the IP Address only.
string dataSubmitURL = "http://YouripAddress/HighScore/AddScore.php?";
string dataGetURL = "http://YouripAddress/HighScore/GetScore.php?";