Xamarin.Forms应用如何获取Firebase Auth的自定义Claims
Xamarin.Forms 跨端获取Firebase Auth自定义Claims方案
FirebaseAuthentication.net 库默认只映射了DisplayName、Email、PhoneNumber这类标准公开字段,自定义Claims实际存储在登录后下发的JWT格式ID Token的Payload中,不需要额外调用特殊接口,通过以下两种方案均可实现iOS、Android双端读取,完全兼容现有项目架构。
方案一:基于现有FirebaseAuthentication.net库直接解码(无需额外依赖)
这个方案不需要引入Firebase原生SDK,纯.NET Standard代码可直接放在共享项目中,双端通用。
- 获取有效ID Token
自定义Claims更新后,强制刷新Token避免读取到缓存的旧版本,再取出原始Token字符串:// 复用你现有的登录逻辑获取当前用户 var authConfig = new FirebaseConfig(你的Firebase Web API Key); var authProvider = new FirebaseAuthProvider(authConfig); var firebaseLoginResult = await authProvider.SignInWithEmailAndPasswordAsync(account, password); // 刚更新Claims时forceRefresh传true,常规场景传false减少请求 await firebaseLoginResult.User.GetIdTokenAsync(forceRefresh: false); string rawJwtToken = firebaseLoginResult.User.FirebaseToken; - 解码JWT Payload提取所有Claims
JWT的Payload段为Base64Url编码,直接解码即可拿到包含自定义字段的完整键值对,生产环境如果需要做Token合法性校验,可额外引入JWT校验库验证签名,仅读取业务字段时无需额外校验(Firebase服务端会自动校验Token有效性):using System; using System.Text; using System.Text.Json; using System.Collections.Generic; private Dictionary<string, object> ParseFirebaseTokenClaims(string rawJwt) { // JWT结构为 [头部].[Payload].[签名],固定取第二段 var payloadPart = rawJwt.Split('.')[1]; // 处理Base64Url编码转标准Base64的补位 payloadPart = payloadPart.Replace('-', '+').Replace('_', '/'); payloadPart = (payloadPart.Length % 4) switch { 2 => payloadPart + "==", 3 => payloadPart + "=", _ => payloadPart }; var payloadBytes = Convert.FromBase64String(payloadPart); var payloadJson = Encoding.UTF8.GetString(payloadBytes); return JsonSerializer.Deserialize<Dictionary<string, object>>(payloadJson); } - 读取自定义Claims
解码后直接按自定义字段的Key取值即可:var allClaims = ParseFirebaseTokenClaims(rawJwtToken); // 读取你存储的内部API凭证 if (allClaims.TryGetValue("internal_api_credential", out var apiCred)) { string internalApiCredential = apiCred.ToString(); } // 读取其他自定义字段,注意和你在服务端设置的类型匹配 if (allClaims.TryGetValue("user_permission_level", out var level)) { int permissionLevel = int.Parse(level.ToString()); }
方案二:基于Firebase原生SDK获取(适合已接入原生Firebase组件的项目)
如果你的项目已经引入了Xamarin.Firebase.Auth(Android)、Xamarin.Firebase.iOS.Auth(iOS)原生绑定包(通常接入Storage、Realtime Database时会用到),可以直接用原生SDK解析Claims,不需要自行处理JWT解码逻辑,稳定性更高。
- 在共享项目定义依赖服务接口:
public interface IFirebaseAuthService { Task<Dictionary<string, object>> GetCurrentUserClaims(bool forceRefresh = false); } - Android端实现:
using Firebase.Auth; public class DroidFirebaseAuthService : IFirebaseAuthService { public async Task<Dictionary<string, object>> GetCurrentUserClaims(bool forceRefresh = false) { var currentUser = FirebaseAuth.Instance.CurrentUser; if (currentUser == null) throw new InvalidOperationException("用户未登录"); var tokenResult = await currentUser.GetIdToken(forceRefresh); return tokenResult.Claims.ToDictionary(item => item.Key, item => item.Value); } } - iOS端实现:
using Firebase.Auth; public class IosFirebaseAuthService : IFirebaseAuthService { public Task<Dictionary<string, object>> GetCurrentUserClaims(bool forceRefresh = false) { var tcs = new TaskCompletionSource<Dictionary<string, object>>(); var currentUser = Auth.DefaultInstance.CurrentUser; if (currentUser == null) { tcs.SetException(new InvalidOperationException("用户未登录")); return tcs.Task; } currentUser.GetIdToken(forceRefresh, (idToken, err) => { if (err != null) { tcs.SetException(new Exception(err.LocalizedDescription)); return; } var claims = idToken.Claims.ToDictionary(item => item.Key, item => item.Value); tcs.SetResult(claims); }); return tcs.Task; } } - 共享项目中通过依赖服务调用即可拿到所有Claims,取值逻辑和方案一一致。
注意事项
- Firebase ID Token默认有效期为1小时,本地会自动缓存,非必要场景不要每次都强制刷新Token,避免产生多余网络请求
- 自定义Claims总大小不能超过1000字节,这是Firebase的官方硬限制,超出会导致Token下发失败
- 客户端获取的Claims仅可用于UI渲染、业务参数传递,所有接口权限校验必须在服务端完成,不可信任客户端传递的Claims值
- 通过Admin SDK更新用户自定义Claims后,必须强制刷新客户端Token才能获取到最新值,否则会最长延迟1小时(等旧Token过期)才能生效
内容的提问来源于stack exchange,提问作者Timothy Belvin
相关产品推荐
相关产品推荐

