Cloud Endpoints 门户的身份验证问题

Authentication issues with Cloud Endpoints Portal

我在我的 App Engine 项目中实施了 Cloud Endpoints Framework,我想从已弃用的 API Explorer 迁移到新的 Endpoints 门户,但我遇到了身份验证问题。

我有一个端点启用了身份验证 Google ID token。但是,当用户在端点门户中单击 'Try This API' 时,他未通过身份验证。这适用于旧的 API 资源管理器。

我使用本教程中描述的项目:https://cloud.google.com/endpoints/docs/frameworks/java/get-started-frameworks-java

API管理已在documentation and I followed these steps中描述了对用户进行身份验证

我已将下面的 class 添加到示例代码中以测试带有身份验证的 API:

package com.example.echo;

import com.google.api.server.spi.auth.common.User;
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.response.UnauthorizedException;

@Api(
        name = "authenticatedApi",
        title = "Authenticated API",
        version = "v1",
        description = "Use OAuth 2.0 to authenticate",
        scopes = {"https://www.googleapis.com/auth/userinfo.email"},
        clientIds = {"*"}
)
public class AuthenticatedApi {

    @ApiMethod(name = "sayHello")
    public Message sayHello(User user) throws UnauthorizedException {
        if (user == null) {
            throw new UnauthorizedException("Invalid credentials");
        }

        Message message = new Message();
        message.setMessage("Hello " + user.getEmail());
        return message;
    }
}

documentation关于如何配置门户进行身份验证,但没有关于 OAuth 2.0

我使用 maven 插件和 gcloud 生成并部署 openapi.json 文件:

$ mvn endpoints-framework:openApiDocs
$ gcloud endpoints services deploy target/openapi-docs/openapi.json

我错过了什么?

所以我找到了一种方法,但找不到任何相关文档。

这个code sample suggest that the Cloud Endpoints Portal needs ESP. But unlike Cloud Endpoints with OpenApi, Cloud Endpoints Framework does not use ESP,但是:

a built-in API gateway that provides API management features that are comparable to the features that ESP provides for Endpoints for OpenAPI

因此,mvn endpoints-framework:openApiDocs 生成的 openapi.json 文件缺少一些信息。

这是我更改的内容:

在class级别,在@Api注解中:

  • 添加了观众(即使我没有 Android 客户,并且根据 documentation,观众仅供 Android 客户使用)
  • 添加了自定义验证器来处理 ESP,类似于 com.google.api.server.spi.auth.EspAuthenticator

在 openapi.json 文件中,用 mvn endpoints-framework:openApiDocs

生成后

来源:

API

package com.example.echo;

import com.google.api.server.spi.auth.common.User;
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.response.UnauthorizedException;

@Api(
        name = "authenticatedApi",
        title = "Authenticated API",
        version = "v1",
        description = "Use OAuth to authenticate",
        scopes = {"https://www.googleapis.com/auth/userinfo.email"},
        clientIds = {"*"},
        audiences = {"my-web-client-id.apps.googleusercontent.com"},
        authenticators = {CustomAuthenticator.class}
)
public class AuthenticatedApi {

    @ApiMethod(name = "sayHello")
    public Message sayHello(User user) throws UnauthorizedException {
        if (user == null) {
            throw new UnauthorizedException("Invalid credentials");
        }

        Message message = new Message();
        message.setMessage("Hello " + user.getEmail());
        return message;
    }
}

验证器

package com.example.echo;

import com.google.api.auth.UserInfo;
import com.google.api.control.ConfigFilter;
import com.google.api.control.model.MethodRegistry;
import com.google.api.server.spi.auth.EndpointsAuthenticator;
import com.google.api.server.spi.auth.common.User;
import com.google.api.server.spi.response.ServiceUnavailableException;

import javax.servlet.http.HttpServletRequest;

public class CustomAuthenticator extends EndpointsAuthenticator {
    private final com.google.api.auth.Authenticator authenticator;

    public CustomAuthenticator() {
        // ESP needs another authenticator
        this.authenticator = com.google.api.auth.Authenticator.create();
    }

    @Override
    public User authenticate(HttpServletRequest request) throws ServiceUnavailableException {
        User user = super.authenticate(request);

        // Testing the user is enough for the API Explorer, not for the Endpoints Portal
        if (user == null) {
            try {
                MethodRegistry.Info methodInfo = ConfigFilter.getMethodInfo(request);
                MethodRegistry.AuthInfo authInfo = methodInfo.getAuthInfo().get();
                String serviceName = ConfigFilter.getService(request).getName();
                UserInfo userInfo = this.authenticator.authenticate(request, authInfo, serviceName);
                user = new User(userInfo.getId(), userInfo.getEmail());
            } catch (Exception e) {
                return null;
            }
        }
        return user;
    }
}

openapi.json

{
  "swagger": "2.0",
  "info": {
    "version": "1.0.0",
    "title": "My Application"
  },
  "host": "my-application.appspot.com",
  "basePath": "/_ah/api",
  "schemes": [
    "https"
  ],
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "paths": {
    "/authenticatedApi/v1/sayHello": {
      "post": {
        "operationId": "AuthenticatedApiSayHello",
        "parameters": [],
        "responses": {
          "200": {
            "description": "A successful response",
            "schema": {
              "$ref": "#/definitions/Message"
            }
          }
        },
        "security": [
          {
            "google_id_token_https": ["https://www.googleapis.com/auth/userinfo.email"]
          }
        ],
        "x-security": [
          {
            "google_id_token_https": {
              "audiences": [
                "my-web-client-id.apps.googleusercontent.com"
              ]
            }
          }
        ]
      }
    }
  },
  "securityDefinitions": {
    "google_id_token_https": {
      "type": "oauth2",
      "authorizationUrl": "https://accounts.google.com/o/oauth2/v2/auth",
      "flow": "implicit",
      "x-google-issuer": "https://accounts.google.com",
      "x-google-jwks_uri": "https://www.googleapis.com/oauth2/v1/certs"
    }
  },
  "definitions": {
    "Email": {
      "properties": {
        "email": {
          "type": "string"
        }
      }
    },
    "Message": {
      "properties": {
        "message": {
          "type": "string"
        }
      }
    }
  }
}

这是 Google Cloud Endpoints 团队的当前功能请求:

https://issuetracker.google.com/issues/127623471