Google Cloud Endpoints + Firebase Auth: method_info is not set

这一生的挚爱 提交于 2019-12-01 06:16:21

问题


So I am running the sample code provided by Google:

package com.neat.backend;
/**
 * An endpoint class we are exposing
 */
@Api(
        name = "myApi",
        version = "v1",
        namespace = @ApiNamespace(
                ownerDomain = "backend.neat.com",
                ownerName = "backend.neat.com",
                packagePath = ""
        ),
        issuers = {
        @ApiIssuer(
                name = "firebase",
                issuer = "https://securetoken.google.com/" + PROJECT_ID,
                jwksUri = "https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com")
})
public class MyEndpoint {

    @ApiMethod(
            path = "firebase_user",
            httpMethod = ApiMethod.HttpMethod.GET,
            authenticators = {EspAuthenticator.class},
            issuerAudiences = {@ApiIssuerAudience(name = "firebase", audiences = {PROJECT_ID})}
    )
    public Email getUserEmailFirebase(User user) throws UnauthorizedException {
        if (user == null) {
            throw new UnauthorizedException("Invalid credentials");
        }

        Email response = new Email(user.getEmail());
        return response;
    }

}

I am getting a Firebase token from my Android client and try to send it to the backend by:

curl -H "Authorization: Bearer FIREBASE_JWT_TOKEN" \
     -X GET \
     http://localhost:8080/_ah/api/echo/v1/firebase_user

The error I see in the logs is the following:

[INFO] java.lang.IllegalStateException: method_info is not set in the request
[INFO]  at com.google.api.server.spi.auth.EspAuthenticator.authenticate(EspAuthenticator.java:67)
[INFO]  at com.google.api.server.spi.request.Auth.authenticate(Auth.java:100)
[INFO]  at com.google.api.server.spi.request.ServletRequestParamReader.getUser(ServletRequestParamReader.java:191)
[INFO]  at com.google.api.server.spi.request.ServletRequestParamReader.deserializeParams(ServletRequestParamReader.java:136)
[INFO]  at com.google.api.server.spi.request.RestServletRequestParamReader.read(RestServletRequestParamReader.java:123)
[INFO]  at com.google.api.server.spi.SystemService.invokeServiceMethod(SystemService.java:350)
[INFO]  at com.google.api.server.spi.handlers.EndpointsMethodHandler$RestHandler.handle(EndpointsMethodHandler.java:114)
[INFO]  at com.google.api.server.spi.handlers.EndpointsMethodHandler$RestHandler.handle(EndpointsMethodHandler.java:102)
[INFO]  at com.google.api.server.spi.dispatcher.PathDispatcher.dispatch(PathDispatcher.java:49)
[INFO]  at com.google.api.server.spi.EndpointsServlet.service(EndpointsServlet.java:71)
[INFO]  at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

I have tried deploying the exact same code to App Engine and it works perfectly. I have tried debugging EspAuthenticator and it seems that it is expecting the Servlet filters to inject some attributes in the request.


回答1:


It took me a while and a bit of debugging to realize that the filter that is supposed to inject method_info was not being fired.

I could fix it by modifying the mapping in web.xml adding the following dispatcher tags:

<filter-mapping>
    <filter-name>endpoints-api-configuration</filter-name>
    <servlet-name>EndpointsServlet</servlet-name>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>



回答2:


generat and deploy the OpenAPI configuration file

$ mvn clean package endpoints-framework:openApiDocs -DskipTests
$ gcloud endpoints services deploy target/openapi-docs/openapi.json
$ mvn appengine:run 



回答3:


I got the same error message, and eventually tracked it down to making a request with a trailing / in the URL where my API did not specify one. The trailing slash only causes an error for calls that provide an authorization token.

Apparently ControlFilter (and therefore also GoogleAppEngineControlFilter) did not recognize it as a valid endpoint and therefore did not bother attaching method_info to the request. But then EndpointsServlet thought it was valid and tried to authenticate without all the needed info!

The fix was easy: remove the trailing slash from the URL in my request. Tracking down the problem, however, was not! I see this was not your problem, but maybe this answer will help someone else.




回答4:


@Kevendra's answer highlights that this issue can be caused if an openapi.json file is missing a reference to the endpoint API method. Firebase may be using this to reference and discover the API method.

From the Google OpenAPI Overview:

Basic structure of an OpenAPI document:

An OpenAPI document describes the surface of your REST API, and defines information such as:

The name and description of the API. The individual endpoints (paths) in the API. How the callers are authenticated.

Follow these steps to regenerate and deploy the openapi.json file:


generate:

$ mvn clean package endpoints-framework:openApiDocs -DskipTests
  • mvn clean - run a Maven goal to clean your project. package - compile and package it
  • endpoints-framework:openApiDocs generate OpenAPI documents. This will generate the openapi.json file at the location: target/openapi-docs/openapi.json- see generating and deploying an api configuration.
  • -DskipTests skips running any tests, to avoid any test failure due to the openapi.json not yet being generated

deploy:

(As a precaution you can first validate the project ID returned from the following command to make sure that the service isn't created in the wrong project - gcloud config list project)

  $ gcloud endpoints services deploy target/openapi-docs/openapi.json

Deploys the openapi.json file from its generated location (in the 'generate' step above). See the Google docs on Deploying the OpenAPI document



来源:https://stackoverflow.com/questions/42749021/google-cloud-endpoints-firebase-auth-method-info-is-not-set

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!