firebase authentication dotnet refresh token - c#

I'm using firebase authentication dotnet library that can be find here
https://github.com/step-up-labs/firebase-authentication-dotnet
but I need to manage the refresh of the user token someone can help me?
actually my login function is this from where I can get the token but after 1 hour it expire
async private void authentication()
{
var authProvider = new FirebaseAuthProvider(new FirebaseConfig(apiKey));
var auth = await authProvider.SignInWithEmailAndPasswordAsync("email", "password");
userAuth = auth.FirebaseToken;
Console.WriteLine(auth.FirebaseToken);
}
thanks

Related

How to refresh access token received with Azure authentication?

I have a usual (tutorial-like) piece of code in Azure Service App. The HomeController is initialized as:
public HomeController(ILogger<HomeController> logger, GraphServiceClient graphServiceClient, ITokenAcquisition tokenAcquisition)
{
var task = Task.Run(async () => await m_tokenAcquisition.GetAuthenticationResultForUserAsync(new[] { "some.allowed.scope" }));
var context = task.Result;
var accessToken = context.AccessToken;
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
client.DefaultRequestHeaders.Add("FeatureFlag", "00000004");
var newGraphClient = new GraphServiceClient(client);
}
The access token is good to go for 'GraphServiceClient'.
There is no use for the access token after it expires which happens in an hour or so. But the service needs to do periodic work on Azure account without bothering the user.
The main question is how should I proceed to prevent the user from frequent logins?
To access the refreshed token without asking users to login.
You need to customize the code for refreshing the token in application with the timer by checking the token expiry before it happens or by adding a listener for the token expiry event.
_timer = new Timer(TokenRefresh, null, _expiresIn * 1000 - 60000, Timeout.Infinite);
using (var client = new HttpClient())
{
var response = await client.PostAsync("https://authserver.com/token", new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("grantType", "tokenRefresh"),
new KeyValuePair<string, string>("tokenRefresh", _tokenRefresh)
}));
var responseContent = await response.Content.ReadAsStringAsync();
var json = JObject.Parse(responseContent);
_accessToken = (string)json["accessToken"];
_tokenRefresh = (string)json["tokenRefresh"];
_expiresIn = (int)json["expiresIn"];
//Expires in 1 hrs (3600)
}
_timer.Change(_expiresIn * 1000 - 60000, Timeout.Infinite);
You need to log into the application.
And the application has to send the login credentials to an authentication serverand has to verify them. And then returns an access token, refresh token.
Now you have the access token and refresh token securely on the client side.
When the access token expires, the application uses the refresh token to request a new access token from the authentication server.
The authentication server checks the refresh token and returns a new access token.
You need to customize the code for refreshing the token in application with the timer by checking the token expiry before it happens or by adding a listener for the token expiry event or delegate
As the refresh token has a shortlife, you need to use the new refresh token obtained from the token refresh process to get new access token again.
For Safety the refresh token and access token have to be stored securely and encrypted.
References taken from
Token Requests
Github Code

MS.Graph api - how to get another user's events when 'Application Permission'

'Delegated permissions' works fine.
How to get another user's events when 'Application Permission' using Microsoft.Graph API.
I confirmed this error.
Microsoft.Graph.ServiceException: 'Code: ErrorAccessDenied
Message: Access is denied.Check credentials and try again.
ClientRequestId: Below is the code that causes the error and the permission of the JWT value.
Code
private string ClientId = "{ClientId}";
private string TenantId = "{TenantId}";
private string SecretKey = "{SecretKey}";
private string[] scopes = new[] { "https://graph.microsoft.com/.default" };
private async void Form1_Load(object? sender, EventArgs e)
{
await Test2();
}
private async Task Test2()
{
var confidentialClient = ConfidentialClientApplicationBuilder
.Create(ClientId)
.WithAuthority($"https://login.microsoftonline.com/{TenantId}/oauth2/v2.0/token")
.WithClientSecret(SecretKey)
.Build();
var authResult = await confidentialClient
.AcquireTokenForClient(scopes)
.ExecuteAsync();
GraphServiceClient graphClient =
new GraphServiceClient(new DelegateAuthenticationProvider(async (requestMessage) =>
{
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
})
);
if ((await graphClient.Users.Request()
.Filter("UserPrincipalName eq ' tester#tester.com'")
.GetAsync()).FirstOrDefault()
is User tester)
{
var calendar1 = await graphClient.Users[tester.Id].Events.Request().GetAsync();
// Raise Error
}
}
role ( JWT - Decode )
"roles": [
"User.ReadBasic.All",
"OnlineMeetings.Read.All",
"Calendars.Read",
"Mail.ReadBasic.All",
"Group.Read.All",
"EventListener.Read.All",
"Directory.Read.All",
"RoleManagement.Read.All",
"User.Read.All",
"Domain.Read.All",
"Schedule.Read.All",
"Calendars.ReadBasic.All",
"Team.ReadBasic.All",
"Mail.Read",
"AppRoleAssignment.ReadWrite.All",
"Mail.ReadBasic"
],
enter image description here
my work history. to resolve
permission changed
add/remove application permission & delegated permissions.
Authentication type change ( secure key <-> certificate )
testing other code (using github sample project)
JWT Check & tesing Grape-explorer
Limiting application permissions to specific Exchange Online mailboxes( add / remove )
Configure application access to online meetings( add /remove )
I need your help
Could you please try using Client Credential flow to securely obtain tokens without user interaction.
I am able to see you have Calendars.Read application permission ,as you want access on behalf of user could you please try adding Calendars.Read delegated permission .
Hope this helps .
Thanks

Passing a token from an authenticated app to another API to use OBO flow to Graph API

We have one app that is using MSAL and generating a token with Azure AD. We need that app to call another API and we're passing the current token. That all is good. We have two different apps and I'll include some code to show how the audience (other client id) is able to authenticate
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(opt =>
{
opt.Audience = Configuration["AzureAd:ResourceId"];
opt.Authority = $"{Configuration["AzureAd:Instance"]}/{Configuration["AzureAd:TenantId"]}";
opt.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidAudiences = new string[] { "e8zzz-3304-43e0-aaaa-zzzzzzzzz" }
};
});
So authentication isn't a problem. We are using the GraphServiceClient to access the graph api, but the token that we get from the Authorization header is the token passed from the other app and has a client id tied to the other app. It all runs fine until it gets to the line with AcquireTokenAsync and the issue being returned states "Assertion audience does not match the Client app presenting the assertion. The audience in the assertion was '{other app id}' and the expected audience is '{app id of the api}' or one of the Application Uris of this application with App ID '{app id of the api}'(API APP). The downstream client must request a token for the expected audience (the application that made the OBO request) and this application should use that token as the assertion."
public async Task<GraphServiceClient> GetAuthenticatedClient()
{
var httpContext = this.httpContextAccessor.HttpContext;
if (httpContext != null)
{
StringValues authorizationToken;
httpContext.Request.Headers.TryGetValue("Authorization", out authorizationToken);
var authHeader = authorizationToken.FirstOrDefault();
if (authHeader != null && authHeader.StartsWith("bearer", StringComparison.OrdinalIgnoreCase))
{
var token = authHeader.Substring("Bearer ".Length).Trim();
var clientCredential = new ClientCredential(_authOptions.ClientId, _authOptions.ClientSecret);
var authenticationContext = new AuthenticationContext($"https://login.microsoftonline.com/{_authOptions.TenantId}");
var authenticationResult = await authenticationContext.AcquireTokenAsync("https://graph.microsoft.com", clientCredential, new UserAssertion(token));
var delegateAuthProvider = new DelegateAuthenticationProvider((requestMessage) =>
{
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("bearer", authenticationResult.AccessToken);
return Task.FromResult(0);
});
return new GraphServiceClient(delegateAuthProvider);
}
}
throw new UnauthorizedAccessException("Invalid User token.");
}
The other point is that I have limited access to Azure AD beyond readonly. Another group controls that. It's kind of political so I am unable to update things to try things on my own and any changes take at least a day turnaround.
I also did set knownApplications in the manifest for the api.
I probably "could" have it use the client credentials from the other app just to see it work, but that's not a really good answer as we don't want to know those creds for other apps.. Surely, this is being done and I'm missing something obvious. Thanks so much ahead of time.. I hope, if anything, this is of use to someone else down the road.
Can you please try passing the token from App to API in the Postman and see if fetches the right App ID.
You can also try this sample for Calling a web API in a web app using Azure AD and OpenID Connect.

Get bearer Token for Azure Blockchain project

I'm trying to create an application that automatically sends data to my Smartcontract on my Azure Blockchain Workbench.
The problem is, I do not understand how to get the bearer token. There is an example online where I can yee how to call the API with GET and POST requests. But I have to submit a client app ID, a client secret, and a resource ID. Where do I get them from?
thanks a lot for your help and ideas !!
class Program
{
public static readonly string AUTHORITY = "https://login.microsoftonline.com/XXX";
public static readonly string WORKBENCH_API_URL = "https://XXX-api.azurewebsites.net";
public static readonly string RESOURCE = "XXX";
public static readonly string CLIENT_APP_Id = "XXX";
public static readonly string CLIENT_SECRET = "XXX";
static async Task Main(string[] args)
{
AuthenticationContext authenticationContext = new AuthenticationContext(AUTHORITY);
ClientCredential clientCredential = new ClientCredential(CLIENT_APP_Id, CLIENT_SECRET);
// Sample API Call
try
{
// Getting the token, it is recommended to call AcquireTokenAsync before every Workbench API call
// The library takes care of refreshing the token when it expires
var result = await authenticationContext.AcquireTokenAsync(RESOURCE, clientCredential).ConfigureAwait(false);
Console.WriteLine(result.AccessToken);
// Using token to call Workbench's API
//HttpClient client = new HttpClient();
//client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
//client.DefaultRequestHeaders
// .Accept
// .Add(new MediaTypeWithQualityHeaderValue("application/json"));
//// Get Users
//var response = await client.GetAsync($"{WORKBENCH_API_URL}/api/v1/contracts");
//var users = await response.Content.ReadAsStringAsync();
var client = new HttpClient();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("Bearer", result.AccessToken);
var content = await client.GetStringAsync($"{WORKBENCH_API_URL}/api/v1/contracts");
Console.WriteLine(content);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}
}
}
According to my test, when we successfully created Azure blockchain workbench, we need to configure Azure AD when we access Azure blockchain workbench at the first time and we will create Azure AD application at the same time. The resource is the application ID or the app url of the Azure AD application. For more details, please refer to the document.
For example
Access Azure Blockchain workbench
Configure Azure AD
Create a Service Principal to Access Workbench API
cd; Invoke-WebRequest -Uri https://aka.ms/createWorkbenchServicePrincipalScript -OutFile createWorkbenchServicePrincipal.ps1
./createWorkbenchServicePrincipal.ps1 -TenantName <the tenant you use above> -WorkbenchAppId <the appid you copy> -MakeAdmin (optional)
Get token
Method: POST
URL: https://login.microsoftonline.com/<tenant id>/oauth2/token
Headers: Content-Type: application/x-www-form-urlencoded
Body:
grant_type: client_credentials
client_id: <sp client id>
client_secret:<sp client secret>
resource: <the app id>
Call rest api
URL: {WORKBENCH_API_URL}/api/v1/users
Headers: Authorization Bearer <access_token>

Unable to obtain username from WebAPI in ADFS4-OAuth2 OpenID

I am trying to use ADFS Authentication with OAuth to communicate between my webapp and webapi. I am using ADFS4 and have configured application group with Server application and Webapi accordingly. I am trying to receive the userdetails, particularly the username from the webapi controller. Is it possible to pass the username details within the access token passed to webapi. Here is what I did from the Webapp side:
In the webapp controller after adfs authentication,
authContext = new AuthenticationContext(Startup.authority, false);
ClientCredential credential = new ClientCredential(Startup.clientId, Startup.appKey);
string accessToken = null;
bool isAuthenticated = User.Identity.IsAuthenticated; //return true
string username = User.Identity.Name; // returns username
string userId = ClaimsPrincipal.Current.FindFirst(ClaimTypes.Name).Value; // returns username
HttpClient httpClient = new HttpClient();
try
{
result = authContext.AcquireTokenAsync(Startup.apiResourceId, credential).Result;
accessToken = result.AccessToken;
}
catch (AdalException ex)
{
}
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
HttpResponseMessage response = httpClient.GetAsync(Startup.apiResourceId + "/api/ConfApi").Result;
From the Webapi end, in Startup.Auth.cs, I have added these code
public void ConfigureAuth(IAppBuilder app)
{
JwtSecurityTokenHandler.InboundClaimTypeMap.Clear();
app.UseActiveDirectoryFederationServicesBearerAuthentication(
new ActiveDirectoryFederationServicesBearerAuthenticationOptions
{
MetadataEndpoint = ConfigurationManager.AppSettings["ida:AdfsMetadataEndpoint"],
TokenValidationParameters = new TokenValidationParameters() {
SaveSigninToken = true,
ValidAudience = ConfigurationManager.AppSettings["ida:Audience"]
}
});
}
However, within the ConfApi controller, I cannot find any claims with user details.
What can I do to receive user details in the Webapi controller?
Thanks for any help.
Are you actually receiving the claims?
Did you configure claims rules for the web API on the ADFS side?
What did you use for Name - Given-Name, Display-Name etc?
Use something like Fiddler to monitor the traffic. After the OIDC authentication, you should see access tokens, id tokens etc.
Take the token and copy into jwt.io.
This will show you what you are actually receiving.
However, the OWIN classes translate the simple OAuth attributes e.g. "aud" into the claim type URI e.g. http://claims/this-claim so breakpoint and see what is in the claims collection and what type has been assigned to each.
The answer to this is the same answer to the question: MSIS9649: Received invalid OAuth request. The 'assertion' parameter value is not a valid access token
You have to use authorization code flow (instead of client credentials grant flow) to get the server app (web app in this case) to talk to the web API with the user's context. Authorization code flow will pass the claims in the JWT Token. Just make sure you pass thru any claims you need for the web API in the web API's RPT claim issuance transform rules.
Vittorio has a nice post on authorization code flow, although it talks about azure.
In order to use authorization code flow, you need to handle the AuthorizationCodeReceived Event via Notifications on the OpenIdConnectAuthenticationOptions from Startup.ConfigureAuth(IAppBuilder app)
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions {
...
Notifications = new OpenIdConnectAuthenticationNotifications {
AuthorizationCodeReceived = async code => {
ClientCredential credential = new ClientCredential(Startup.clientId, Startup.appKey);
AuthenticationContext authContext = new AuthenticationContext(Startup.authority, false);
AuthenticationResult result = await authContext.AcquireTokenByAuthorizationCodeAsync(
code.Code,
new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path)),
credential,
Startup.apiResourceId);
}
}
When you are ready to make the call you acquire your token silently.
var authContext = new AuthenticationContext(Startup.authority, false);
var credential = new ClientCredential(Startup.clientId, Startup.appKey);
var claim = ClaimsPrincipal.Current.FindFirst(ClaimTypes.NameIdentifier).Value;
var userId = new UserIdentifier(claim, UserIdentifierType.UniqueId);
result = await authContext.AcquireTokenSilentAsync(
Startup.apiResourceId,
credential,
userId);
HttpClient httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(
"Bearer",
result.AccessToken);

Categories

Resources