以下 .NET8 控制台应用程序尝试使用 Firebase 的新 V1 API 发送推送。
我从 Firebase 控制台生成的 configuration.json 文件创建一个 Firebase JWT 不记名令牌,其中包含:
{
"type": "service_account",
"project_id": "myProject",
"private_key_id": "my private key id",
"private_key": "-----BEGIN PRIVATE KEY-----\n DATA \n-----END PRIVATE KEY-----\n",
"client_email": "firebase-adminsdk-XXXX.gserviceaccount.com",
"client_id": "999999999999",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-xxxxxx.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}
尝试发送请求时失败。 它返回:
{
"error": {
"code": 401,
"message": "Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"status": "UNAUTHENTICATED"
}
}
我可以在 Visual Studio 中看到从 GetJwtToken 返回的令牌是一个有效的 JWT 令牌,距离过期还有一个小时。
我犯了什么明显的错误? 我是否误认为它需要 JWT 令牌?
是否有一个 Firebase 例程可以为我提供它似乎期望的“OUath 2 访问令牌”?
using Google.Apis.Auth.OAuth2;
using RestSharp;
class Program {
static async Task Main(string[] args) {
// Send notification
await SendNotificationAsync();
}
public static async Task SendNotificationAsync() {
const string kMyToken = "myToken";
// Get JWT token
var bearerToken = await GetJwtToken();
// Create client
var client = new RestClient("https://fcm.googleapis.com/v1");
// Create request
var request = new RestRequest("projects/myProject/messages:send", Method.Post);
// Set auth header
request.AddHeader("Authorization", "Bearer " + bearerToken);
// Set content type
request.AddHeader("Content-Type", "application/json");
// Construct notification payload
var payload = new {
message = new {
token = kMyToken,
notification = new {
title = "Test Title",
subtitle = "Test Sub-title",
body = "Test body.",
content_available = true
},
data = new {
key_1 = "posJob",
key_2 = "Value for key_2"
}
}
};
// Add payload to request
request.AddJsonBody(payload);
// Send request
var response = await client.ExecuteAsync(request);
}
public static async Task<string> GetJwtToken() {
try {
// Read credentials file
var json = File.ReadAllText("credentials.json");
// Parse JSON credentials
var credentials = GoogleCredential.FromJson(json);
var scopes = "https://www.googleapis.com/auth/firebase.messaging";
var accessToken = await credentials.UnderlyingCredential.GetAccessTokenForRequestAsync(scopes);
return accessToken;
} catch (Exception ex) {
Console.WriteLine($"Exception: {ex.Message}");
return "";
}
}
}
HTTP v1 API 确实需要 OAuth 2.0 访问令牌而不是 jwt 访问令牌。您需要修改解决方案以获得正确类型的令牌。
根据文档:
GetAccessTokenForRequestAsync(字符串,CancellationToken)
获取访问令牌以授权请求。 OAuth2 访问令牌 从TokenServerUrl获取到的会在下面两个中返回 案例:
- 如果此凭证具有关联的范围,但 UseJwtAccessWithScopes 是假的;如果此凭据与域范围委派一起使用,则 即,用户已设置;否则,将返回本地签名的 JWT。
- 签名的 JWT 将包含“范围”声明,其范围位于 Scopes 中 如果有的话,否则它将包含一个“aud”声明 authUri。如果可能的话,使用缓存的令牌,并且该令牌仅 快过期了就刷新。
您需要首先确定您的凭据范围,然后将其传递给 GetAccessTokenForRequestAsync 函数。
试试这个:
var credentials = GoogleCredential.FromJson(json).CreateScoped("https://www.googleapis.com/auth/firebase.messaging");
var accessToken = await credentials.UnderlyingCredential.GetAccessTokenForRequestAsync();
而不是这个:
var credentials = GoogleCredential.FromJson(json);
var scopes = "https://www.googleapis.com/auth/firebase.messaging";
var accessToken = await credentials.UnderlyingCredential.GetAccessTokenForRequestAsync(scopes);