【发布时间】:2018-03-28 17:33:06
【问题描述】:
我已将以下端点框架 API 部署到我的 Google appengine 应用程序 + 为 Google 的“客户端 API 服务”生成并部署了 OpenAPI 配置 + 成功地为我的 Android 应用程序生成了端点客户端 API:
@Api(
name = "endpoint",
version = "v1",
apiKeyRequired = AnnotationBoolean.TRUE,
authenticators = {EspAuthenticator.class},
issuers = {
@ApiIssuer(
name = "firebase",
issuer = "https://securetoken.google.com/MY_PROJECT_ID",
jwksUri = "https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken@system.gserviceaccount.com")
},
issuerAudiences = {
@ApiIssuerAudience(name = "firebase", audiences = "MY_PROJECT_ID")
},
namespace =
@ApiNamespace(
ownerDomain = "xxxxx",
ownerName = "xxxxx"
)
public class API {
@ApiMethod(name = "procesOrderRequest", path = "customer/orders/request")
public Order processCutomerOrderRequest(User user, OrderRequest orderRequest) throws UnauthorizedException {
log.info("procesOrderRequest(): CustomerId: " + orderRequest.getCustomer());
log.info("procesOrderRequest(): bagId: " + orderRequest.getBagId());
log.info("processCutomerOrderRequest(): customerId: " + orderRequest.getCustomer());
if (user == null) {
throw new UnauthenticatedException("Unauthorized user by RR");
}
Order order = new Order();
order.setBagId(orderRequest.getBagId());
order.setPriority(orderRequest.getPriority());
order.setOrderId(orderRequest.getBagId() + 1000);
return order;
}
}
正如您从上面看到的,我正在使用 firebase 身份验证和 API 密钥。
在我的 Android 应用程序中,我成功登录了我的 Firebase 用户,但如果我尝试执行以下端点客户端 API 请求
private class ContactBackendTask extends AsyncTask<Void, Void, Void> {
String mIDToken = null;
@Override
protected Void doInBackground(Void... voids) {
FirebaseUser user = mFirebaseAuthenticator.getCurrentUser();
user.getIdToken(true).addOnSuccessListener(new OnSuccessListener<GetTokenResult>() {
@Override
public void onSuccess(GetTokenResult result) {
mIDToken = result.getToken();
//Do whatever
Log.d("attempLogin", "GetTokenResult result = " + mIDToken);
}
});
Endpoint.Builder endpoint = new Endpoint.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null);
endpoint.setRootUrl("https://MY_PROJECT_ID.appspot.com/_ah/api/");
endpoint.setApplicationName("MY_PROJECT_ID");
Endpoint service = endpoint.build();
OrderRequest orderRequest = new OrderRequest();
orderRequest.setBagId(35);
orderRequest.setPriority(9);
orderRequest.setCustomer("someUser@gmail.com");
try {
Endpoint.ProcesOrderRequest request = service.procesOrderRequest(orderRequest);
Order order = request.setKey("MY_API_KEY").setOauthToken(mIDToken).execute();
Log.d("attempLogin", "OrderId result = " + order.getOrderId());
} catch (IOException ex) {
System.out.println(ex.getMessage());
}
return null
}
我从 Google 的 Endpoints Management 服务收到以下响应:
400 Bad Request
{
"code": 400,
"errors": [
{
"domain": "global",
"message": "java.lang.IllegalArgumentException: No auth providers are defined in the config.",
"reason": "badRequest"
}
],
"message": "java.lang.IllegalArgumentException: No auth providers are defined in the config."
}
知道吗,我在这里缺少什么?
我关注了以下Firebase specific authentication tutorial 以及以下Google Endpoints User Authentication tutorial。
非常感谢任何想法或提示。
更新:
这是用于将端点 API 部署到 Google 服务管理的 SERVICE_CONFIG_FILE。
来自 openenapi.json 的安全定义:
securityDefinitions":{
"api_key":{
"in":"query",
"name":"key",
"type":"apiKey"
},
"firebase":{
"authorizationUrl":"",
"flow":"implicit",
"type":"oauth2",
"x-google-issuer":"https://securetoken.google.com/my_project_id",
"x-google-jwks_uri":"https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken@system.gserviceaccount.com"
}
},
"swagger":"2.0"
更新 2:
来自 App Engine 控制台的 Stacktrace:
java.lang.IllegalArgumentException: No auth providers are defined in the config.
at com.google.api.auth.Authenticator.create (Authenticator.java:178)
at com.google.api.auth.Authenticator.create (Authenticator.java:171)
at com.google.api.server.spi.auth.EspAuthenticator.<init> (EspAuthenticator.java:54)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0 (Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance (NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance (DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance (Constructor.java:423)
at java.lang.Class.newInstance (Class.java:443)
at com.google.api.server.spi.request.Auth$1.apply (Auth.java:57)
at com.google.api.server.spi.request.Auth$1.apply (Auth.java:51)
更新 3:
<env-variables>
<env-var name="ENDPOINTS_SERVICE_NAME" value="my_project_id.appspot.com" />
<env-var name="ENDPOINTS_SERVICE_VERSION" value="2018-03-29r0" />
</env-variables>
当然,
“我的项目 ID”
只是这篇文章的一个示例 ID。我不想在这里发布我的真实项目 ID。
还有
“2018-03-29r0”
是部署openapi.json文件后生成的ID 用命令
gcloud 端点服务部署 target/openapi-docs/openapi.json
更新 4:
但是我现在从我的 appengine 后端应用程序得到以下响应
503 Service Unavailable
{
"code": 503,
"errors": [
{
"domain": "global",
"message": "com.google.api.auth.UnauthenticatedException: Unauthorized user by RR",
"reason": "backendError"
}
],
"message": "com.google.api.auth.UnauthenticatedException: Unauthorized user by RR"
}
在我的 Android 应用中执行时
Order order = request.setKey("MY_API_KEY").setOauthToken(mIDToken).execute();
异常 UnauthenticatedException 被触发是因为后端 API 方法 processCutomerOrderRequest() 验证了 user == null 虽然 firebase 身份验证的用户被指示为“成功登录”。
我的问题:这里有什么问题?也许我不应该在我的客户端应用程序中使用 setOauthToken() 方法?调用正确吗?
【问题讨论】:
-
听起来您需要重新部署服务(gcloud endpoints services deploy)。
-
我已经这样做了两次。不走运--> 我用“openapi.json”文件编辑了我的帖子。也许有助于分析。我想知道,为什么 openapi.json 文件不包含“processCutomerOrderRequest”API 方法中定义的任何“用户”键......
-
@saiyr 您需要更多信息吗?也许 Firebase 创建了“google-service.json”文件?
-
请从您的 openapi.json 粘贴安全定义。我不会从第三方网站下载文件。
-
@Saiyr 请在安全定义上方找到。如果您需要 openapi.json 文件中的更多信息,请告诉我。
标签: java android firebase firebase-authentication google-cloud-endpoints