接收HttpError 403执行自定义google端点api时

时间:2016-07-19 03:11:25

标签: google-app-engine google-oauth google-app-engine-python

我使用python在Google Apps Engine中创建了一个端点api。 api需要oAuth2身份验证。该方法可以很好地从api资源管理器中运行,但我似乎无法弄清楚为什么我在运行时得到一个HttpError 403“Client_id是不允许的”。我知道客户端ID是有效的,因为我已经能够在api explorer中成功使用它。我知道我在这篇文章中揭露了我的客户秘密,但我需要帮助。一旦我开始工作,我将要求一个新的秘密和客户ID。

调用API的代码:

from apiclient.discovery import build
from oauth2client.appengine import OAuth2Decorator
import logging
import pprint
import webapp2

decorator = OAuth2Decorator(
    client_id='968442935974-happ8rfg8eq059v1p8364bv5mj8tjd4l.apps.googleusercontent.com',
    client_secret='q31TNSbsc70xfEwaTjXuVAPI',
    scope='https://www.googleapis.com/auth/userinfo.email')

# For for production
api_root = 'https://jamesste-school-app.appspot.com/_ah/api'
api = 'knowledge'
version = 'v1'
discovery_url = '%s/discovery/v1/apis/%s/%s/rest' % (api_root, api, version)

class TestHandler(webapp2.RequestHandler):
    @decorator.oauth_required
    def get(self):
        service = build(api,version,discoveryServiceUrl=discovery_url)
        self.response.headers['Content-Type'] = 'application/json'
        knowledge_list = service.knowledge_message().list()
        knowledge_list.execute(http=decorator.http())
        self.response.out.write(pprint.pformat(knowledge_list))


app = webapp2.WSGIApplication([
    ('/test', TestHandler),
    (decorator.callback_path, decorator.callback_handler())],
    debug=True)

API代码:

from google.appengine.ext import ndb
from models import Knowledge
from models import KnowledgeType
from models import Resource
from protorpc import message_types
from protorpc import messages
from protorpc import remote
from apiuser import ApiUser
import endpoints
import logging



def get_endpoints_current_user(raise_unauthorized=True):
    """Returns a current user and (optionally) causes an HTTP 401 if no user.
    Args:
        raise_unauthorized: Boolean; defaults to True. If True, this method
            raises an exception which causes an HTTP 401 Unauthorized to be
            returned with the request.
    Returns:
        The signed in user if there is one, else None if there is no signed in
        user and raise_unauthorized is False.
    """
    current_user = endpoints.get_current_user()
    if raise_unauthorized and current_user is None:
        raise endpoints.UnauthorizedException('Invalid token.')
    return current_user


class KnowledgeMessage(messages.Message):
    knowledge_key = messages.StringField(1)
    knowledge = messages.StringField(2)
    resource_key = messages.StringField(3)
    resource_name = messages.StringField(4)
    resource_section_key = messages.StringField(5)
    resource_section_name = messages.StringField(6)
    types = messages.StringField(7, repeated=True)
    page = messages.IntegerField(8)
    keywords = messages.StringField(9, repeated=True)
    user_email = messages.StringField(10)
    user_org_key = messages.StringField(11)

class KnowledgeMessageList(messages.Message):
    items = messages.MessageField(KnowledgeMessage, 1, repeated=True)

@endpoints.api(name="knowledge", version="v1", description="API for Knowledge management",
               auth_level=endpoints.AUTH_LEVEL.REQUIRED, 
               allowed_client_ids=['1-web-apps.apps.googleusercontent.com',
                                   '2-android-apps.apps.googleusercontent.com',
                                    endpoints.API_EXPLORER_CLIENT_ID])    
class KnowledgeMessageApi(remote.Service):

    @endpoints.method(KnowledgeMessage, KnowledgeMessage, name="knowledge_message.insert", path="knowledge", http_method="POST")
    def insert_knowledge(self, request): 
        authenticated_user = ApiUser()
        logging.info("Logging: class KnowledgeMessageApi.insert_knowledge() - authenticated_user.email = " + authenticated_user.email)
        PARENT_KEY = authenticated_user.get_org_key()      
        logging.info("Logging: class KnowledgeMessageApi.insert_knowledge() - authenticated_user.get_org_key()") 

        logging.info("Logging: class KnowledgeMessageApi.insert_knowledge() - request.knowledge = " + request.knowledge) 
        logging.info("Logging: class KnowledgeMessageApi.insert_knowledge() - request.resource_key = " + request.resource_key) 
        logging.info("Logging: class KnowledgeMessageApi.insert_knowledge() - request.resource_section_key = " + request.resource_section_key)
        types_string = ""
        for item in request.types:
            types_string += item.strip()
        logging.info("Logging: class KnowledgeMessageApi.insert_knowledge() - request.types = " + types_string)

        logging.info("Logging: class KnowledgeMessageApi.insert_knowledge() - request.page = " + str(request.page)) 
        keywords_string = ""
        for item in request.keywords:
            keywords_string += item.strip()
        logging.info("Logging: class KnowledgeMessageApi.insert_knowledge() - request.keywords = " + keywords_string) 

        if request.knowledge_key:
            logging.info("Logging: class KnowledgeMessageApi.insert_knowledge() - request.knowledge_key = " + request.knowledge_key) 
            # If no key exists, then we can assume it needs to be inserted
            # into the datastore.  Overwrite any exiting values with what
            # is passed into the method
            kno=ndb.Key(urlsafe=request.knowledge_key).get()
            kno.knowledge = request.knowledge
            kno.resource = ndb.Key(urlsafe=request.resource_key)
            kno.resource_section = ndb.Key(urlsafe=request.resource_section_key)
            kno.types = request.types
            kno.page = request.page
            kno.keywords = request.keywords
            kno.put()

        else:
            #get resource key and name
            Knowledge(parent=PARENT_KEY,
                      knowledge=request.knowledge, 
                      resource = ndb.Key(urlsafe=request.resource_key),
                      resource_section = ndb.Key(urlsafe=request.resource_section_key),
                      types = request.types,
                      page = request.page,
                      keywords = request.keywords
                      ).put()

        return request


    @endpoints.method(message_types.VoidMessage, KnowledgeMessageList, name='knowledge_message.list', path='knowledge_messages', http_method='GET')
    def list_knowledge(self, unused_request):
        authenticated_user = ApiUser()
        if not authenticated_user.is_authenticated:
            logging.info("Logging: KnowledgeMessageApi.list_knowledge - user was not authenticated")
            raise endpoints.ForbiddenException()

        logging.info("finding current user info : " + authenticated_user.email)
        PARENT_KEY = authenticated_user.get_org_key()
        knos = []
        for kno in Knowledge.query(ancestor=PARENT_KEY):

            knos.append(KnowledgeMessage(knowledge_key=kno.key.urlsafe(),
                                         knowledge=kno.knowledge, 
                                         resource_key=kno.resource.urlsafe(),
                                         resource_name=kno.resource.get().name,
                                         resource_section_key=kno.resource_section.urlsafe(),
                                         resource_section_name=kno.resource_section.get().name,
                                         types=kno.types,
                                         page=kno.page,
                                         keywords=kno.keywords,
                                         user_email=authenticated_user.email,
                                         user_org_key=PARENT_KEY.urlsafe())
                        )
        return KnowledgeMessageList(items=knos)


app = endpoints.api_server([KnowledgeMessageApi])

我还会在发送问题之前提供一些我在探索过的证据图片。

enter image description here

我将非常感谢我收到的任何帮助。

1 个答案:

答案 0 :(得分:0)

经过大量工作后我发现了自己的错误:

在我的api中,我从未指定允许哪些client_ids。

@endpoints.api(name="knowledge", version="v1", description="API for Knowledge management",
               auth_level=endpoints.AUTH_LEVEL.REQUIRED, 
               allowed_client_ids=['1-web-apps.apps.googleusercontent.com',
                                   '2-android-apps.apps.googleusercontent.com',
                                    endpoints.API_EXPLORER_CLIENT_ID])    
class KnowledgeMessageApi(remote.Service):

显然代码'1-web-apps.apps.googleusercontent.com'是一个占位符,我从来没有用自己的替换它。这已得到纠正。