FirebaseAuthentication.net package in Xamarin Forms - get current user UID - c#

In my Xamarin.Forms project, I saw that the FirebaseAuthentication.Net package can be used for the cross-platform project. How would I get the current user's UID with this? I have figured out how to get the current user's email by saving the firebase refresh token and using NewtonSoft.JSON, but am not sure how to do this with the id. I want to be able to do this so that I can store the user's data in the database under their uid and retrieve it that way.
Here's what I have so far for getting the email address of the current user:
var authProvider = new FirebaseAuthProvider(new FirebaseConfig(WebAPIKey));
var savedfirebaseauth = JsonConvert.DeserializeObject<Firebase.Auth.FirebaseAuth>(Preferences.Get("FirebaseRefreshToken", ""));
var RefreshedContent = await authProvider.RefreshAuthAsync(savedfirebaseauth);
Preferences.Set("FirebaseRefreshToken", JsonConvert.SerializeObject(RefreshedContent));
string UsersEmailToDisplay = savedfirebaseauth.User.Email;
What I am storing as "FirebaseRefreshToken" is the following.
var auth = await authProvider.CreateUserWithEmailAndPasswordAsync(Email.Text, Password.Text);
var content = await auth.GetFreshAuthAsync();
var serializedcontent = JsonConvert.SerializeObject(content);
Please let me know if any more clarification of my question is needed.

I think you want to get the UserId which unique to the Firebase project.
You could try to call its LocalId after you sign in.
var authProvider = new FirebaseAuthProvider(new FirebaseConfig(""));
var auth = await authProvider.SignInWithOAuthAsync(authType, accessToken);
var uid = auth.User.LocalId;

Related

Get user data from a TokenCredential object (.NET)

I'm building a .NET core tool (Console app) that needs to access some Azure Keyvault secrets by using a SecretClient. This client needs a TokenCredential for which I use DefaultAzureCredential().
The client is successfully authenticated and retrieves the secrets, but can I know which method from the flow was used (i.e. Environment, Cache, CLI, interactive)? I want to display the username that was used for logged in, since you might have an account in SharedCache but you might want to use another account.
var credentials = new DefaultAzureCredential();
var secretClient = new SecretClient(new Uri(configuration["Authentication:KeyVaultUri"]), credentials);
// Just using the client to retrieve values
var settings = JsonSerializer.Deserialize<AppSettingsKeys>((await secretClient.GetSecretAsync(configuration["Authentication:SecretName"])).Value.Value);
I checked the credential object but didn't see anything useful to get the username. I want to Console.WriteLine something like Successfully logged in with pepe#test.com using SharedTokenCacheCredential
I was able to get the upn by first getting the jwt with the GetToken method, and then parsing it with a JwtSecurityTokenHandler.
Not the approach I was looking for but it works, I was wondering if there is cleaner way.
var credential = new DefaultAzureCredential();
var secretClient = new SecretClient(new Uri(configuration["Authentication:KeyVaultUri"]), credential);
var settings = JsonSerializer.Deserialize<AppSettingsKeys>((await secretClient.GetSecretAsync(configuration["Authentication:SecretName"])).Value.Value);
var token = await credential.GetTokenAsync(
new Azure.Core.TokenRequestContext(
new[] { "https://vault.azure.net/.default" }));
var handler = new JwtSecurityTokenHandler();
var jsonToken = handler.ReadToken(token.Token) as JwtSecurityToken;
var upn = jsonToken.Claims.First(c => c.Type=="upn").Value;

PowerBI embed token with RLS through C# API

We want to provide embedded PowerBI reports to our customers. Initially, we're looking at using one report with a dataset that contains data for all customers. I have created a service principal (app only auth) that has access to a workspace where I've published the report. I've also created a role "business_customer" with a DAX expression ([CustomerNumber] = USERNAME()) on this report.
I'm trying to get an embed token for the report with row level security through the C# API (Microsoft.PowerBI.Api):
var tenantId = "<tenantId>";
var datasetId = "<datasetId>";
var reportId = "<reportId>";
var groupId = "<groupId>";
var applicationPassword = "<applicationPassword>";
var context = new AuthenticationContext($"https://login.microsoftonline.com/{tenantId}/");
var clientCredential = new ClientCredential(applicationId, applicationPassword);
var result = context.AcquireTokenAsync("https://analysis.windows.net/powerbi/api",
clientCredential).Result;
var authHeader = new TokenCredentials(result.AccessToken, "Bearer");
var client = new PowerBIClient(new Uri("https://api.powerbi.com"), authHeader);
var groups = client.Groups.GetGroups();
var tokenRequest = new GenerateTokenRequest(TokenAccessLevel.View, datasetId,
new EffectiveIdentity("username", new List<string> { datasetId },
new List<string> { "business_customer" }));
var embedToken = client.Reports.GenerateTokenInGroupAsync(new Guid(groupId), new Guid(reportId),
tokenRequest, cancellationToken: CancellationToken.None).Result;
This fails on the GenerateTokenInGroupsAsync call:
"Invalid request: Creating embed token for accessing dataset <datasetId> shouldn't have effective identity"
I've tried with different usernames and I've tried leaving the username blank, but all of my attempts have failed.
Is there a way of getting an embed token this way or am I on the wrong path? What would be the "correct" way of solving this case?
Thanks in advance

"The tenant for tenant guid does not exist" when using GraphAPI - Even with user type as Member

I am trying to access email using Microsoft Graph API. When I try to access the email I got the below error.
Microsoft.Graph.ServiceException: 'Code: OrganizationFromTenantGuidNotFound
Message: The tenant for tenant guid '<some id>' does not exist.
Here is the code to get the emails
var graphServiceClient = new GraphServiceClient(new DelegateAuthenticationProvider((requestMessage) =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
return Task.CompletedTask;
}));
var userId = "quicksilverconnect#outlook.com"; // Tried vijaynirmal#quicksilverconnectoutlook.onmicrosoft.com also
var messageId = "Actual message id";
var email = await graphServiceClient.Users[userId].Messages[messageId].Request().GetAsync();
Here is the code to get access token
private const string _clientId = "xxxxxxx-xxxxxx-xxxxxxx-xxxx";
private const string _clientSecret = "xxxxxxx-xxxxxx-xxxxxxx-xxxx";
private const string _tenantName = "ecd90453-34b6-xxxx-xxxx-xxxxxxxxx";
private readonly string _uri = $"https://login.microsoftonline.com/{_tenantName}/oauth2/v2.0/token";
private const string _grantType = "client_credentials";
private const string _scope = "https://graph.microsoft.com/.default";
public async Task<string> GetAccessTokenAsync()
{
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("Grant_Type", _grantType),
new KeyValuePair<string, string>("Scope", _scope),
new KeyValuePair<string, string>("Client_Id", _clientId),
new KeyValuePair<string, string>("Client_Secret", _clientSecret)
});
var responce = await _httpClient.PostAsync(_uri, content);
responce.EnsureSuccessStatusCode();
var jsonString = await responce.Content.ReadAsStringAsync();
var document = await JsonDocument.ParseAsync(jsonString.ToStream());
return document.RootElement.GetProperty("access_token").GetString();
}
I have searched in net for solutions. I found some solutions but none of them is working for me.
User Type must be a Member. My user type is already Member. Original issue - “The tenant for tenant guid does not exist” even though user is listed on users endpoint?
Using Domain as tenentId. Its not working. Original issue - Getting "The tenant for tenant guid '' does not exist"
private const string _tenantName = "quicksilverconnectoutlook.onmicrosoft.com";
Some interesting observations
I was able to get the user but not their mails. Note: In this below code, only user id is working not their email id.
var userId = "8685e56b-b1a8-45cf-a5d1-5c5ddadd0f3e";
// EmailId (quicksilverconnect#outlook.com) is not working here
var user = await graphServiceClient.Users[userId].Request().GetAsync();
I found out that if I use the access token generated by Graph Explorer then my code is working properly. So probably the issue is in my GetAccessTokenAsync code or its configuration details.
Update:
I want to use Application permissions not Delegated permissions because my application will use Notification Subscriptions to get a notification when a new mail is received by any users. Also, I want to get the full email details of the new mail. In short, this application will run in the background.
var graphServiceClient = new GraphServiceClient(new DelegateAuthenticationProvider((requestMessage) =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", accessToken);
return Task.CompletedTask;
}));
var subscription = await graphServiceClient.Subscriptions.Request().AddAsync(new Subscription()
{
Resource = "/users/quicksilverconnect#outlook.com/messages",
ChangeType = "created",
ExpirationDateTime = DateTimeOffset.Now.AddDays(3).AddHours(-1),
NotificationUrl = "https://asdasdasd.azurewebsites.net/Outlook/NewMailListener",
ClientState = Guid.NewGuid().ToString()
});
It seems the problem was caused by you don't have O365 subscription. Although you have azure subscription and have an email for your azure account, but you do not have O365 subscription. So you can just get the users by graph but can not get email messages by graph.
For this problem, you can just go to this page(login with you azure admin account) and buy O365 subscription.(for example: Office 65 E3)
Maybe you can also buy Exchange online(such as Exchange Online (Plan 2)) on the same page to access the email message.
By the way, there is a mistake in your code. You use client_credentials as "Grant_Type" and use DelegateAuthenticationProvider. If you want to use DelegateAuthenticationProvider, you need to set "Grant_Type" as password but not client_credentials.
To use client credential authentication, You need to install Microsoft.Graph.Auth. Note: this is a prerelease package. Here is a code snippet
var confidentialClientApplication = ConfidentialClientApplicationBuilder
.Create(configuration.ClientId)
.WithTenantId(configuration.TenantId)
.WithClientSecret(configuration.ClientSecret)
.Build();
var authProvider = new ClientCredentialProvider(confidentialClientApplication);
var graphServiceClient = new GraphServiceClient(_clientCredentialProviderauthProvider);

AADSTS500011 - PowerBi C# .NET (resource x not found in tenant y)

I am trying to integrate the power bi embedded with C#, I always have this same error that comes out, I put it to you just below, as well as the versions of the packages and the code (basic) which is supposed to do the work .
Thank you for all your answers
Microsoft.PowerBI.Api (v2.0.12)
Microsoft.PowerBI.JavaScript (v2.5.1)
Microsoft.IdentityModel.Clients.ActiveDirectory (v3.13.9)
Microsoft PowerBI JavaScript (v2.5.1)
Microsoft IdentityModel Clients.ActiveDirectory (v3.13.9)
Note that the two head variables are temporary.
The error always come out at this line : var authenticationResult = await authenticationContext.AcquireTokenAsync(this.resourceUrl, this.applicationId, credential);
There is the error message : "exceptionMessage": "AADSTS500011: The resource principal named https://analysis.windows.net/powerbi/api/ was not found in the tenant named x. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant.
public async Task<EmbedConfigResource> EmbedReport([FromUri]string username, [FromUri]string roles)
{
roles = "None";
username = this.pbiUsername;
var result = new EmbedConfigResource { Username = username, Roles = roles };
var credential = new UserPasswordCredential(this.pbiUsername, this.pbiPassword);
var authenticationContext = new AuthenticationContext(this.authorityUrl);
var authenticationResult = await authenticationContext.AcquireTokenAsync(this.resourceUrl, this.applicationId, credential);
var tokenCredentials = new TokenCredentials(authenticationResult.AccessToken, "Bearer");
using (var client = new PowerBIClient(new Uri(this.apiUrl), tokenCredentials))
{
var reports = await client.Reports.GetReportsInGroupAsync(this.workspaceId);
Report report = reports.Value.FirstOrDefault(r => r.Id == this.reportId);
var datasets = await client.Datasets.GetDatasetByIdInGroupAsync(this.workspaceId, report.DatasetId);
result.IsEffectiveIdentityRequired = datasets.IsEffectiveIdentityRequired;
result.IsEffectiveIdentityRolesRequired = datasets.IsEffectiveIdentityRolesRequired;
GenerateTokenRequest generateTokenRequestParameters;
var rls = new EffectiveIdentity(this.pbiUsername, new List<string> { report.DatasetId });
if (!string.IsNullOrWhiteSpace(roles))
{
var rolesList = new List<string>();
rolesList.AddRange(roles.Split(','));
rls.Roles = rolesList;
}
generateTokenRequestParameters = new GenerateTokenRequest(accessLevel: "view", identities: new List<EffectiveIdentity> { rls });
var tokenResponse = await client.Reports.GenerateTokenInGroupAsync(this.workspaceId, report.Id, generateTokenRequestParameters);
result.EmbedToken = tokenResponse;
result.EmbedUrl = report.EmbedUrl;
result.Id = report.Id;
return result;
}
}
You must log into Azure portal, go to Azure Active Directory -> App registrations, select your app, click View API permissions, and then grant admin consent by clicking the button at the bottom:
If you don't have access to the portal, or the button is disabled, you must ask your admin to do it for you.

OneDrive auto login after initial authorisation

I want to be able login user automatically in my WPF C# app after he/she accepts it and login manually for the first time. Currently my code to login using prompt window works:
try
{
_msaAuthenticationProvider = new MsaAuthenticationProvider("XXXX",
"https://login.live.com/oauth20_desktop.srf", new[] {"onedrive.readonly", "wl.signin", "wl.offline_access" });
await _msaAuthenticationProvider.AuthenticateUserAsync();
_oneDriveClient = new OneDriveClient("https://api.onedrive.com/v1.0", _msaAuthenticationProvider);
Item item = await _oneDriveClient
.Drive
.Root
.Request()
.GetAsync();
Print("Logged in as " + item.CreatedBy.User.DisplayName);
}
catch (Exception exc)
{
PresentServiceException(exc);
}
Now the question is how do I save some info (tokens maybe?) and use them next time my app is launched to log in a specific user without showing that prompt window? I've read about GetSilentlyAuthenticatedMicrosoftAccountClient method on OneDriveClient but it seems not to be included in Microsoft.OneDrive.SDK 2.0.0 (all samples that use this and OneDriveClientExtensions reference to SDK in version 1.1.5). Do you have any idea how to accomplish that?
// your code
_msaAuthenticationProvider = new MsaAuthenticationProvider("XXXX", "https://login.live.com/oauth20_desktop.srf", new[] {"onedrive.readonly", "wl.signin", "wl.offline_access" });
await _msaAuthenticationProvider.AuthenticateUserAsync();
_oneDriveClient = new OneDriveClient("https://api.onedrive.com/v1.0", _msaAuthenticationProvider);
await _msaAuthenticationProvider.AuthenticateUserAsync();
// add this
// save refresh token
var refreshtoken = (((MsaAuthenticationProvider)oneDriveClient.AuthenticationProvider).CurrentAccountSession).RefreshToken;
// store this refresh token secure between sessions.
// ------------------------------------
// later, if you want to connect to OneDrive, create AccountSession and use that stored RefreshToken
AccountSession session = new AccountSession();
session.ClientId = <<your id>>; // your "XXXX"
session.RefreshToken = refreshtoken;
_msaAuthenticationProvider = new MsaAuthenticationProvider(....
_oneDriveClient = new OneDriveClient(....
_msaAuthenticationProvider.CurrentAccountSession = session;
await _msaAuthenticationProvider.AuthenticateUserAsync();
Indeed this was available in the previous version of the SDK. When it was refactored for v2, not quite all of the authentication mechanisms were re-implemented. I have opened a Github issue to deal with this. https://github.com/OneDrive/onedrive-sdk-dotnet-msa-auth-adapter/issues/7

Categories

Resources