Android Firebase - add authenticated user into database - c#

Ok, so I am building xamarin.android applicationon in Visual Studio and there is quite a lot of questions of this type, but I really didn't find anything regarding xamarin.android, everything is Java based. I tried following those tutorials and answers but there was always something missing or not working on Xamarin android.
I have made authentication and it works great, no problems there. And i tried storing user information (info that user types in while registering) into database. It kind of worked, but with one problem. Here is code:
public void OnComplete(Task task)
{
if (task.IsSuccessful)
{
Toast.MakeText(this, "Successful", ToastLength.Long).Show();
FirebaseUser user = FirebaseAuth.GetInstance(app).CurrentUser;
id = user.Uid;
CreateUser();
buttonSignIn.PerformClick();
progressBar.Visibility = ViewStates.Invisible;
}
else
{
//something
}
}
And here is CreateUser() method:
private void CreateUser ()
{
Account user = new Account();
user.uid = id;
user.name = signup_inputName;
user.lastName = signup_inputLastName;
user.email = signup_inputEmail;
user.phone = signup_inputPhoneNumber;
var firebase = new FirebaseClient(FirebaseURL);
var item = firebase.Child("users").PostAsync<Account>(user);
}
Here is Account class code:
public class Account
{
public string uid { get; set; }
public string name { get; set; }
public string lastName { get; set; }
public string email { get; set; }
public string phone { get; set; }
}
This code stores user information under "users" node in database. But there is one more node under "user" with some random value and below are information about user (including uid). Here is output:
- Users
-LBGFtYFTfD3l1hmwHVn
email: "testuser#test.com"
lastName:"peric"
name: "pero"
phone: "12321"
uid: "18puc5CzSZfzbdflzekzNCHGHR62"
So, my question is, shouldn't this random value below "users" node be uid? If yes, how to set it that way?
I tried with this:
Account user = new Account();
user.uid = id;
user.name = signup_inputName;
user.lastName = signup_inputLastName;
user.email = signup_inputEmail;
user.phone = signup_inputPhoneNumber;
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("users").Child(uid).SetValue(user)
But that didn't work, I was getting this error:
Firebase No properties to serialize found on class
Even though I have set public getters and setters in users class.
I need to get that user info and show it on some places in my app, but I just can't get it to work. This is my first time using Firebase and I am used to SQL database so this is really confusing to me. Also, there is very little information online about xamarin.android and firebase, plus I am actually new to programming in general. Any help would be appreciate. This is my last try before switching to SQL online database.

When you call PostAsync the client creates a new child node under the location that you call it on. This is similar to the HTTP POST verb, and the push() method in most other Firebase SDKs.
To write data to a location that you exactly specify, use PutAsync:
var item = firebase.Child("users").Child(uid).PutAsync<Account>(user);
See the example from the Readme of Firebase.Xamarin.

Related

Updating Claims in Microsoft Identity 3.0.0 rc1 and persisting the data

I've run into an issue when working with Microsoft MVC 5 and Identities 3.0.0 rc1-final.
So I've modified the AppUser.cs model that extends IdentityUser to include a FirstName and LastName column. My next objective is to create a claim for the user that stores there FullName, a concatenate of Firstname and Lastname. I've successfully done this when seeding the database. I can also successfully update the database when a user modifies there profile by changing there names. When a user makes a change to there profile I'd like to update the "FullName" claim within the database claims table as well as the users cookie so that I can display there full name in the header of the page. The problem is I can't seem to persist the data into the table. I am able to update the claims within the User object but that's about it. I've researched and tried a dozen different things but there doesn't seem to be a solution to my problem, below is some of my code:
AppUser.cs Model
public class AppUser : IdentityUser {
[StringLength(255)]
public string FirstName { get; set; }
[StringLength(255)]
public string LastName { get; set; }
}
Helper Classes. This was derived from my research and came accross this post. I realize I'm missing part of his method, the last 2 lines, but I could never get past compiliation errors when calling the authentication manager.
public static void AddUpdateClaim(this IPrincipal currentPrincipal, string key, string value) {
var identity = currentPrincipal.Identity as ClaimsIdentity;
if (identity == null)
return;
// check for existing claim and remove it
var existingClaim = identity.FindFirst(key);
if (existingClaim != null)
identity.RemoveClaim(existingClaim);
// add new claim
identity.AddClaim(new Claim(key, value));
}
ManageController, this is the post method for updating user profile:
public async Task<IActionResult> Index(IndexViewModel model) {
if (!ModelState.IsValid) {
return View(ModelState);
}
var user = await base.GetCurrentUserAsync();
if (user != null) {
user.Email = model.Email;
user.FirstName = model.FirstName;
user.LastName = model.LastName;
User.AddUpdateClaim("FullName", "Test User");
var result = await _userManager.UpdateAsync(user);
if (result.Succeeded) {
return RedirectToAction(nameof(Index), new { Message = ManageMessageId.AccoutUpdated });
} else {
_logger.LogError(1, "Error updating user: {username}", user.UserName);
base.AddErrors(result);
return View(model);
}
}
// If we got this far, something failed, redisplay form with errors.
return View(model);
}
Any help at this point would be greatly appreciated as I've beaten my head against this wall for a while now!
I figured this out a couple days ago... basically I over complicated it. :P

Neo4JClient Cyper.Create Deprecated

I have just started to explore Graph databases and Neo4jClient library for Neo4J. I am using Neo4JClient v1.1.0.11 downloaded from NuGet in Visual Studio. I want to create a Node in Neo4J and for that I am using this code (C#):
var client = new GraphClient(new Uri("http://localhost:7474/db/data"), "user", "pass");
client.Connect();
client.Cypher.Create();
But on Cypher.Create Intellisense shows that it is deprecated. My question is what is the alternate way of creating a Node? An example would be appreciated.
In this particular case I have a User that I want to create in the database. The class looks like:
public class User
{
public Int32 ID { get; set; }
public String UserName { get; set; }
public String Name { get; set; }
public Boolean Active { get; set; }
public String Email { get; set; }
public String Password { get; set; }
}
Thanks
I believe only one overload on the Create method has been marked as obsolete - unless there is something I am not aware of. The following code should do what you need and does not show as being deprecated.
var client = new GraphClient(new Uri("http://localhost:7474/db/data"), "user", "pass");
client.Connect();
var user = new User
{
// initialise properties
};
client.Cypher
.Create("(u:User {user})")
.WithParams(new { user = user })
.ExecuteWithoutResults();
There are a number of variations on this that will work but it should get you started.
As an aside, were you to use the first overload on the Create method you would indeed see it marked as deprecated. For example, this code
client.Cypher
.Create("(u:User {0})", user)
.ExecuteWithoutResults();
would give you the following warning in Visual Studio
'Neo4jClient.Cypher.ICypherFluentQuery.Create(string, params object[])' is obsolete: 'Use Create(string) with explicitly named params instead. For example, instead of Create("(c:Customer {0})", customer), use Create("(c:Customer {customer})").WithParams(new { customer }).'

Azure Active Directory Users (type=User with an existing user account) Json to List Model is giving null

I want to deserialize Json result into a model.
I am using Azure Single sign on method. when I am login with new new created user in ad (new user in your organization) i am getting proper user info. but if i created new user in AzureAd with "User with an existing user account".I am able to log in and request is also authenticated. but i am not getting user profile. user profile is null. but "responseString" contains all values for user. can any one help me for that ?
UserProfile profile = JsonConvert.DeserializeObject<UserProfile>(responseString);
public class UserProfile
{
public string DisplayName { get; set; }
public string GivenName { get; set; }
public string Surname { get; set; }
}
Json
User with an existing user account
{"odata.metadata":"https://graph.windows.net/780cdd84-48ba-4be3-8d66-b40b8bee6b0b/$metadata#directoryObjects/Microsoft.WindowsAzure.ActiveDirectory.User","value":[{"odata.type":"Microsoft.WindowsAzure.ActiveDirectory.User","objectType":"User","objectId":"****************","accountEnabled":true,"assignedLicenses":[],"assignedPlans":[],"city":null,"country":null,"department":null,"dirSyncEnabled":null,"displayName":"mahesh","facsimileTelephoneNumber":null,"givenName":"map","jobTitle":null,"lastDirSyncTime":null,"mail":null,"mailNickname":"devb_azureteam.com#EXT#","mobile":null,"otherMails":["devb#azureteam.com"],"passwordPolicies":"None","passwordProfile":null,"physicalDeliveryOfficeName":null,"postalCode":null,"preferredLanguage":null,"provisionedPlans":[],"provisioningErrors":[],"proxyAddresses":[],"state":null,"streetAddress":null,"surname":"map","telephoneNumber":null,"usageLocation":null,"userPrincipalName":"devb_azureteam.com#EXT##AzureteamLoginTest.onmicrosoft.com"},
{"odata.type":"Microsoft.WindowsAzure.ActiveDirectory.User","objectType":"User","objectId":"****************","accountEnabled":true,"assignedLicenses":[],"assignedPlans":[],"city":null,"country":null,"department":null,"dirSyncEnabled":null,"displayName":"Education at AzureTeam","facsimileTelephoneNumber":null,"givenName":"Education","jobTitle":null,"lastDirSyncTime":null,"mail":null,"mailNickname":"education_azureteam.com#EXT#","mobile":null,"otherMails":["education#azureteam.com"],"passwordPolicies":null,"passwordProfile":null,"physicalDeliveryOfficeName":null,"postalCode":null,"preferredLanguage":null,"provisionedPlans":[],"provisioningErrors":[],"proxyAddresses":[],"state":null,"streetAddress":null,"surname":"at AzureTeam","telephoneNumber":null,"usageLocation":null,"userPrincipalName":"education_azureteam.com#EXT##AzureteamLoginTest.onmicrosoft.com"},
{"odata.type":"Microsoft.WindowsAzure.ActiveDirectory.User","objectType":"User","objectId":"*****************","accountEnabled":true,"assignedLicenses":[],"assignedPlans":[],"city":null,"country":null,"department":null,"dirSyncEnabled":null,"displayName":"mahesh","facsimileTelephoneNumber":null,"givenName":"mahesh","jobTitle":null,"lastDirSyncTime":null,"mail":null,"mailNickname":"mahesh","mobile":null,"otherMails":["map#azureteam.com"],"passwordPolicies":"None","passwordProfile":null,"physicalDeliveryOfficeName":null,"postalCode":null,"preferredLanguage":null,"provisionedPlans":[],"provisioningErrors":[],"proxyAddresses":[],"state":null,"streetAddress":null,"surname":null,"telephoneNumber":null,"usageLocation":null,"userPrincipalName":"mahesh#AzureteamLoginTest.onmicrosoft.com"}]}
New user in organization
{"odata.metadata":"https://graph.windows.net/780cdd84-48ba-4be3-8d66-b40b8bee6b0b/$metadata#directoryObjects/Microsoft.WindowsAzure.ActiveDirectory.User/#Element","odata.type":"Microsoft.WindowsAzure.ActiveDirectory.User","objectType":"User","objectId":"************","accountEnabled":true,"assignedLicenses":[],"assignedPlans":[],"city":null,"country":null,"department":null,"dirSyncEnabled":null,"displayName":"mahesh","facsimileTelephoneNumber":null,"givenName":"mahesh","jobTitle":null,"lastDirSyncTime":null,"mail":null,"mailNickname":"mahesh","mobile":null,"otherMails":["map#azureteam.com"],"passwordPolicies":"None","passwordProfile":null,"physicalDeliveryOfficeName":null,"postalCode":null,"preferredLanguage":null,"provisionedPlans":[],"provisioningErrors":[],"proxyAddresses":[],"state":null,"streetAddress":null,"surname":null,"telephoneNumber":null,"usageLocation":null,"userPrincipalName":"mahesh#AzureteamLoginTest.onmicrosoft.com"}
You actually get different JSON's. I simplified them to show the problem. For new user JSON looks like that:
{
"odata.metadata":"...Microsoft.WindowsAzure.ActiveDirectory.User/#Element",
"odata.type":"Microsoft.WindowsAzure.ActiveDirectory.User",
"displayName":"mahesh",
"givenName":"mahesh",
"surname":null
}
Deserialization will work with your model. But for existing user JSON is:
{
"odata.metadata":"...Microsoft.WindowsAzure.ActiveDirectory.User",
"value":[
{
"odata.type":"Microsoft.WindowsAzure.ActiveDirectory.User",
"displayName":"mahesh",
"givenName":"map",
"surname":"map"
},
{ },
{ }
]
}
As you can see you have a value property that holds an array of users. So to be able to deserialize it you will need to create new model:
public class RootObject
{
public List<UserProfile> Value { get; set; }
}
And then:
var obj = JsonConvert.DeserializeObject<RootObject>(json);
I'm not similar with Azure Active Directory but you should check why odata.metadata property is different for these responses.
I got the saluting :)
Add this block in your global.asax
protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
ClaimsIdentity id = ((ClaimsIdentity)User.Identity);
Claim claim = id.FindFirst(ClaimTypes.Email);
if (claim != null)
{
string email = claim.Value;
id.AddClaim(new Claim(ClaimTypes.Name, email));
}
}

Creating Login/Password in C# (compare List<> to string)

Hello im trying to create a login using wcf but somehow looks like my program dont work as I wanted ;(
public class UserService : IUserService
{
[DataMember]
public string Login { get; set; }
[DataMember]
public string Password { get; set; }
[DataMember]
public string Type { get; set; }
[DataMember]
public int ID { get; set; }
public List<UserInfo> GetUserInformation()
{
QuizDBEntities contex = new QuizDBEntities();
var UserInfo = from a in contex.UserInfoes select a;
return UserInfo.ToList();
}
}
I created
protected void Button1_Click(object sender, EventArgs e)
{
string username = TextBox1.Text;
string password = TextBox2.Text;
UserService vs = new UserService();
List<UserInfo> alfa = new List<UserInfo>();
}
I used few foreach/if loop but every time I do something wrong and my list act like its empty ( I tried grindwiev and did get all data ;( ) Anyone can help me and give hint how can I compare List to login/password ?
A WCF service isn't actually a service until it's hosted somewhere (IIS, self-hosted, etc). Simply adding the attributes [ServiceContract] and [OperationContract] do not magically make it a service.
SOAP Web services like WCF are not directly accessed by the client - the client goes through a proxy to interact with the service. This proxy can be generated automatically by Visual Studio through either Add Service Reference or the command line svcutil.exe. An easy way to do this is to create a new WCF Service Application - this will be hosted in IIS. There are different (and in my opinion better) ways to host the service, but for simplicity and sake of illustration we'll go with this one.
So let's assume you have a WCF service application up and running, and it has the code you posted above. You could then choose Add Service Reference in the VS Solution Explorer to add a service reference to your service. This will generate a proxy for you to use. The name of the proxy is usually UserServiceClient (i.e., Visual Studio adds Client to the end).
To call a method in your service with this proxy, you would do this:
UserServiceClient proxy = new UserServiceClient();
List<UserInfo> users = proxy.GetUserInformation;
This would give you a list of all the users in your database. You would probably want to either markup the UserInfo entity as a DataContract, or create a new class that has the properties in it as a DataContract - your current code doesn't do anything to set the properties it has in it, and services themselves don't do anything with properties (not to mention your code isn't setting any values for them anyway).
Now for your other question - "how can I compare List to login/password"? In a nutshell, you can't. Your List<UserInfo> is a list of UserInfo objects, and you're attempting to compare a string to this list. That won't work.
What you could do, however, is create another method in your service that would accept a username and a password and return that user's information if it is found. It might look something like below, but first let's make a DataContract to hold the UserInfo (basically moving the DataMembers from the service to a separate class:
[DataContract]
public class UserInformation
{
[DataMember]
public string Login { get; set; }
[DataMember]
public string Password { get; set; }
[DataMember]
public string Type { get; set; }
[DataMember]
public int ID { get; set; }
}
public UserInformation GetUser(string userName, string password)
{
UserInformation user = new UserInformation();
using (QuizDBEntities context = new QuizDBEntities())
{
user = (from a in context.UserInfoes
where a.UserName == userName && a.Password == password
select new UserInformation() {
Login = a.UserName,
Password = a.Password,
Type = a.Type,
ID = a.ID}).SingleOrDefault();
}
return user;
}
The UserInformation class contains the DataMembers you originally had in your service. The LINQ query selects the user that has the matching UserName and Password and populates the UserInformation class (property names are conjecture as I don't know what your UserInfo entity looks like). The SingleOrDefault() at the end selects one matching result, or if no match is found returns the default value - which in this case will be null.
You could then use it like this:
UserServiceClient proxy = new UserServiceClient();
UserInformation user = proxy.GetUser("someName", "somePassword");
proxy.Close();
if (user == null)
{
// No match was found, so do something
}
else
{
// Match was found, so proceed with what you were doing
}
All of the above is primarily for illustration purposes, but you should be able to adapt to your program's needs. I would also suggest Googling for some good tutorials on how to create and host a WCF service.

Session State MVC3

I am having a problem I can not find a tutorial or some code where I am able to do some session state. For example I would like to create a application where when a user logs in, he or she can only view there information for example a student viewing his grades an no other student can see that information. I have achieved this in VB 2008 last year but need help in MVC3 as it is not the same as the language as i am using C#. In vb 2008 i achieved this connecting a table from the ASP.net database (users) and joined to my employee table by a foreign key. And added the following code:
Session("ID") = objUser
Dim db As New DataClassesDataContext
Dim info = From a In db.tblCourses _
Where a.CourseTitle = ddlCourseName.SelectedItem.Value _
Select a.CourseId Order By CourseId Descending
crseID = info.FirstOrDefault()
Session("Course") = crseID
sdsAddStudent.Insert()
FName.Text = ""
LName.Text = ""
Address.Text = ""
ddlCourseName.SelectedIndex = 0
Session("UserID2") = objUser
Session("RoleID2") = "f13b9bf3-593d-4170-bfaa-bc43655773e2"
sdsRoleStudent.Insert()
I know VB is different to C# MVC3 as this is 2008 and not MVC3 am just showing this code so people know that I am not after free code and have tried to make an effort which has not succeed.
Thank You For Your Kind Help People
I'm not clear what exactly are you trying to achieve.
If you want to limit users access exclusively to the data that belongs to them, you need to have this data related their IDs in Users table. There is very little that you have told about table structure, but I think it is safe to assume that you have Courses table and something like UsersInCourses that would map many users to a single Course. All you would have to do is to select courses have User's Id assigned to them. To get currently logged in user you just have refer to
User.Identity.Name
in your application's code.
So let's assume your class is cooking reciepe :
public class Recipe
{
public int Id { get; set; }
public string Name { get; set; }
public string Author { get; set; }
public string PreparationInstructions { get; set; }
public DateTime CreationDate { get; set; }
}
and you want to have an Action that returns recipes for currently logged in user
public ActionResult ShowMyRecipes()
{
var myRecipes = dbContext.Recipes.Where(recipe => recipe.Author.Equals(User.Identity.Name)).ToList();
return View(myRecipes);
}
public ActionResult CreateRecipe(Recipe recipe)
{
// set Author to curently logged in user's key
recipe.Author = Membership.GetUser().ProviderUserKey;
// save changes
dbContext.Recipes.Add(recipe);
}

Categories