Given an asp.net core api and working firebase auth using only the [Authorize] attribute, how can I add custom claims to the token to use [Authorize(Policy = "admin")]? The admin SDK is only available for node.js, Java, python or go and I can't find any docs on how to use the Firebase Admin API directly. From my understanding the user claims have to be stored in the Firebase Auth backend.

- 17,219
- 5
- 37
- 56

- 305
- 3
- 14
-
did you find a way? – Tzvi Gregory Kaidanov Oct 31 '18 at 14:30
-
there is a .net sdk https://github.com/firebase/firebase-admin-dotnet but at the time of writing only a small set of functions is supported: https://firebase.google.com/docs/admin/setup. – user3838018 Nov 13 '18 at 18:49
2 Answers
Since the Firebase Admin .NET SDK 1.1 is released the Control Access With Custom Claims feature is supported.
You can find the repository here: https://github.com/firebase/firebase-admin-dotnet
Setup guide and documentation: https://firebase.google.com/docs/admin/setup
Solution:
// Initialize the admin SDK with your service account keys
FirebaseApp.Create(new AppOptions()
{
Credential = GoogleCredential.FromFile("path/to/serviceAccountKey.json"),
});
// Create the custom user claim that has the role key
var claims = new Dictionary<string, object>
{
{ ClaimTypes.Role, "Administrator" }
};
// This will call the Firebase Auth server and set the custom claim for the user
await FirebaseAuth.DefaultInstance.SetCustomUserClaimsAsync(uid, claims);

- 649
- 7
- 16
To the best of my knowledge, with the C# Firebase Admin SDK you can't. I had the same issue and, at first, I used the token to get the user id, retrieved the roles for the user id from the database, set up a Claims array, and created a custom token with the added claims with the . Then I sent it to Firebase via their REST API to get a regular Firebase ID and Refresh token as explained in the reference guide. Finally i gave the token to the client. However, I had issues (mostly 404 errors) ad it is not well documented what changes you need to make to the verification middleware to accept the new reissued tokens, and I was never able to get the refresh Token as it was never in the REST API response. I even followed the steps in here and here and minted my own custom token according to Firebase instructions, but was never able to make the darn thing work.
So I ended up doing something a little different. I retrieved the user claims from the firebase IdToken and created my own token using using System.IdentityModel.Tokens.Jwt. There I added my own claims and roles and sent that to the client. Now the client logs in using FireBase but i have full control of the tokens to use my API
This is how I modified the startup. Keep in mind I haven't played with all options
var key = System.Text.Encoding.UTF8.GetBytes(Configuration["MyToken:Key"]);
services.AddAuthentication(
auth => {
auth.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
auth.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;})
.AddJwtBearer(options => {
options.RequireHttpsMetadata = false;
options.IncludeErrorDetails = true;
options.TokenValidationParameters = new TokenValidationParameters {
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true
};
});
this is the simplified Encoding function :
public string EncodeTokenMS(string uid, Claim[] claims)
{
var signingKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(<Secret key here>));
var signingCredentials = new SigningCredentials(signingKey, SecurityAlgorithms.HmacSha256Signature);
var now = DateTimeOffset.UtcNow;
var _claims = new[] {
new Claim(JwtRegisteredClaimNames.Iss, "https://auth.xxx.com"),
new Claim(JwtRegisteredClaimNames.Aud, "https://auth.xxx.com"),
new Claim(JwtRegisteredClaimNames.Sub, uid),
new Claim(JwtRegisteredClaimNames.AuthTime, now.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64),
new Claim(JwtRegisteredClaimNames.Iat, now.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64),
new Claim(JwtRegisteredClaimNames.Exp, now.AddMinutes(60).ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64),
// TODO Actually write the code to get tenancy, roles, and user info
new Claim("tenantId", "PippoBaudo" ),
new Claim(ClaimTypes.Role, "User")
};
//Create and sign the JWT, and write it to a string
var jwt = new JwtSecurityToken(
claims: _claims,
signingCredentials: signingCredentials);
return new JwtSecurityTokenHandler().WriteToken(jwt);
}
The drawback of this approach is there is an added roundtrip when the user signs up, however it is only when the user needs a token so it shouldn't add a great deal of latency, and I can increase the lifetime of the token to more than 60 minutes.
Suggestions and (constructive) comments on this approach are welcomed!
Hope this helps!

- 1,767
- 23
- 38