C#调用REST API启用Firebase邮箱密码认证遇403权限问题求助
我尝试调用Identity Toolkit的REST API PATCH请求(地址:https://identitytoolkit.googleapis.com/v2/projects/{projectId}/config?key={apiKey})启用Firebase邮箱/密码认证,已替换控制台中的Project ID和Firebase Web API Key,但执行以下C#代码时返回403权限拒绝错误:
var credential = GoogleCredential.GetApplicationDefault() .CreateScoped(iam.IamService.Scope.CloudPlatform); var service = new iam.IamService(new BaseClientService.Initializer { HttpClientInitializer = credential }); var projectId = "myprojectidhere"; var serviceAccountName = "auto-service-acc"; var displayName = "Auto Service Account"; var serviceAccount = new iamData.ServiceAccount { DisplayName = displayName }; var createRequest = new iamData.CreateServiceAccountRequest { AccountId = serviceAccountName, ServiceAccount = serviceAccount, // Optional: specify a list of roles for the new service account. //Roles = new List<string> { "roles/editor" } }; var createdAccount = service.Projects.ServiceAccounts.Create( createRequest, $"projects/{projectId}").Execute(); var serviceAccountEmail = createdAccount.Email; var accessToken = credential.UnderlyingCredential.GetAccessTokenForRequestAsync( iam.IamService.Scope.CloudPlatform).Result; string apiKey = "myapikeyhere"; var url = $"https://identitytoolkit.googleapis.com/v2/projects/{projectId}/config?key={apiKey}"; var requestBody = new { // projectId, signIn = new { email = new { enabled = true, passwordRequired = true } } }; var httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); var response = await httpClient.PatchAsync(url, new StringContent(JsonConvert.SerializeObject(requestBody), Encoding.UTF8, "application/json")); Console.WriteLine(response); if (response.IsSuccessStatusCode) { // Authentication using email and password is now enabled. Console.WriteLine(" yes it is enabled"); } else { // Handle the error. // Console.WriteLine(" no it doesn't work"); var errorMessage = await response.Content.ReadAsStringAsync(); Console.WriteLine($"Error: {errorMessage}"); }
返回的错误信息:
StatusCode: 403, ReasonPhrase: 'Forbidden', Version: 1.1, Content: System.Net.Http.HttpConnectionResponseContent, Headers: { Date: Tue, 28 Mar 2023 08:29:15 GMT Pragma: no-cache Cache-Control: no-cache, no-store, max-age=0, must-revalidate Vary: X-Origin Vary: Referer Vary: Origin,Accept-Encoding Server: ESF X-XSS-Protection: 0 X-Frame-Options: SAMEORIGIN X-Content-Type-Options: nosniff Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000 Accept-Ranges: none Transfer-Encoding: chunked Expires: Mon, 01 Jan 1990 00:00:00 GMT Content-Type: application/json; charset=utf-8 } Error: { "error": { "code": 403, "message": "The caller does not have permission", "status": "PERMISSION_DENIED" } }
解决步骤
补全必要权限
当前使用的默认凭据(GoogleCredential.GetApplicationDefault()对应的账号)没有修改Firebase认证配置的权限。需要在Google Cloud控制台给该账号分配Firebase Admin SDK Administrator Service Agent角色,或者更细粒度的Identity Toolkit Admin角色。使用新创建的服务账号发起请求
代码里创建了新服务账号,但后续请求用的还是原来的默认凭据,根本没用到新账号。如果要使用新账号,需要为其生成密钥并初始化凭据:// 生成服务账号密钥 var keyRequest = service.Projects.ServiceAccounts.Keys.Create( new iamData.CreateServiceAccountKeyRequest(), $"projects/{projectId}/serviceAccounts/{serviceAccountEmail}").Execute(); // 将密钥保存为JSON文件(实际建议存到安全路径) File.WriteAllText("service-account-key.json", keyRequest.PrivateKeyData); // 用新密钥初始化凭据,指定正确的Scope var newCredential = GoogleCredential.FromFile("service-account-key.json") .CreateScoped(new[] { "https://www.googleapis.com/auth/identitytoolkit" }); // 获取新的AccessToken var newAccessToken = await newCredential.UnderlyingCredential.GetAccessTokenForRequestAsync( "https://www.googleapis.com/auth/identitytoolkit");之后用
newAccessToken作为Bearer Token发起PATCH请求。修正Scope范围
原来用的iam.IamService.Scope.CloudPlatform范围太宽泛且不匹配,调用Identity Toolkit API应该用专门的Scope:https://www.googleapis.com/auth/identitytoolkit,确保权限精准。移除不必要的API Key
服务端请求用Bearer Token做身份验证足够,URL中的key={apiKey}可以直接去掉,避免混淆。
内容的提问来源于stack exchange,提问作者Samaritan

