Support for Making Google ID Token Authorized Calls from Python API Client

437 views
Skip to first unread message

jkr...@appirio.com

unread,
Aug 7, 2018, 2:11:33 PM8/7/18
to Google Cloud Endpoints
Hello,

Is it currently possible to make an authorized call with a Google ID Token to a Cloud Endpoints API with the Python API Client library?

I am running Cloud Endpoints on App Engine Standard in Python. This uses the Cloud Endpoints Framework instead of ESP. I do not think this should have any affect but calling this out in case it does. Furthermore, I am authorizes requests with a service account not a user.

Google's current documentation gives an example with user credential and not a Google ID Token.

If it is possible to send a Google ID Token with a request built with the Python API Client library, can you provide an example?


Regards,

James Krimm

Andrew Gunsch

unread,
Aug 7, 2018, 2:24:53 PM8/7/18
to jkr...@appirio.com, google-clou...@googlegroups.com
I believe you're right that it shouldn't matter that you're using Endpoints Frameworks vs ESP --- from a client's perspective that should be indistinguishable.

Have you tried the sample instructions for making calls with a Google ID Token from here? (full example on GitHub, assuming you're using a service account key file)

If you can get an access token that way, I believe the way to combine that with the Python API Client Library is by using AccessTokenCredentials with the access token you've retrieved from above, rather than a credentials object from OAuth2WebServerFlow.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-cloud-endpoints/CANMRvhk%2BJJ71dR-dts683Koew2G6Vq%2Bk0e8dBBYnY9PKMc58HQ%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

jkr...@appirio.com

unread,
Aug 7, 2018, 3:39:33 PM8/7/18
to gun...@google.com, Google Cloud Endpoints
Thanks Andrew,

Never crossed my mind to generate a credential with the Google ID Token. That worked.

The next issue is sending query string parameters with a get request. See my other open question for why I am not using a Resource Container. https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!topic/google-cloud-endpoints/phd8kQGCaps


Regards,

James Krimm

Message has been deleted

aoinami.1...@gmail.com

unread,
Aug 14, 2018, 10:25:50 AM8/14/18
to Google Cloud Endpoints
Hello Andrew,

I was trying to make authentication as you suggested (on the same echo GAE SE example for backend from here https://cloud.google.com/endpoints/docs/frameworks/python/get-started-frameworks-python). 
In my client I am using suggested AccessTokenCredentials, but unfortunately fails with error:

"The access_token is expired or invalid and can\'t be refreshed.')
AccessTokenCredentialsError: The access_token is expired or invalid and can't be refreshed."


but doing call as following:

class MainPage(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        token = get_id_token()
        api_root = 'https://myprojectid.appspot.com/_ah/api'
        api = 'echo'
        version = 'v1'
        discovery_url = '%s/discovery/v1/apis/%s/%s/rest' % (api_root, api, version)
        credentials = AccessTokenCredentials(token, 'my-user-agent/1.0')
        http = httplib2.Http()
        http = credentials.authorize(http)       
        service = build(api, version, discoveryServiceUrl=discovery_url, http=http)
        response = service.get_user_email().execute()
        # response
        self.response.write(response)

Could you please give me a hint what is wrong with my call? How to refresh token?
or may be because oath2client deprecation as said here http://google-auth.readthedocs.io/en/latest/oauth2client-deprecation.html

Any help is highly appreciated!

Thank you

Marina

On Wednesday, August 8, 2018 at 3:24:53 AM UTC+9, Andrew Gunsch wrote:
I believe you're right that it shouldn't matter that you're using Endpoints Frameworks vs ESP --- from a client's perspective that should be indistinguishable.

Have you tried the sample instructions for making calls with a Google ID Token from here? (full example on GitHub, assuming you're using a service account key file)

If you can get an access token that way, I believe the way to combine that with the Python API Client Library is by using AccessTokenCredentials with the access token you've retrieved from above, rather than a credentials object from OAuth2WebServerFlow.

On Tue, Aug 7, 2018 at 11:11 AM <jkr...@appirio.com> wrote:
Hello,

Is it currently possible to make an authorized call with a Google ID Token to a Cloud Endpoints API with the Python API Client library?

I am running Cloud Endpoints on App Engine Standard in Python. This uses the Cloud Endpoints Framework instead of ESP. I do not think this should have any affect but calling this out in case it does. Furthermore, I am authorizes requests with a service account not a user.

Google's current documentation gives an example with user credential and not a Google ID Token.

If it is possible to send a Google ID Token with a request built with the Python API Client library, can you provide an example?


Regards,

James Krimm

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

Andrew Gunsch

unread,
Aug 14, 2018, 1:05:56 PM8/14/18
to aoinami.1...@gmail.com, google-clou...@googlegroups.com
I don't see anything obviously wrong with the code, but you could probably debug by trying:
(a) Sending the Access Token along with a regular HTTP request (similar to this) to the same URL, to make sure that `token` is valid
(b) Then trying with AccessTokenCredentials again

if you just fetched the token, it shouldn't need to be refreshed --- so it seems more likely that maybe it's not valid in the first place for some reason.

To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-cloud-endpoints/c9477cfd-bfc1-4114-88e3-d24751ec4db6%40googlegroups.com.

aoinami.1...@gmail.com

unread,
Aug 14, 2018, 9:35:17 PM8/14/18
to Google Cloud Endpoints
Hello Andrew!
Thank you very much for your reply.
I tried your suggestion (a)(b) and sent with a regular HTTP request similar to this
        res = make_request(token)
        self.response.write(res)

unfortunately I got 
 "error": {
  "code": 401, 
  "errors": [
   {
    "domain": "global", 
    "message": "", 
    "reason": "required"
   }
  ], 
  "message": ""
 }
}
Checking my token at jwt.io I received: 
 "aud": "https://apiserverprojectid.appspot.com",
 "azp": "clientp...@appspot.gserviceaccount.com",
 "sub": "110920313756597865336",
 "email": "clientp...@appspot.gserviceaccount.com",
 "email_verified": true,
 "exp": 1534299670, 
 "iss": "https://accounts.google.com", 
 "iat": 1534296070
}

seems not to be expired as exp is 2018-08-15 11:21:10 JST and I accessed around 2018-08-15 10:21:10 JST.

Thank you in advance for looking at this.
Sincerely
Marina

To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

Andrew Gunsch

unread,
Aug 14, 2018, 10:08:20 PM8/14/18
to aoinami.1...@gmail.com, google-clou...@googlegroups.com
Hey Marina,

The sample you linked is a known working sample --- so any debugging depends on what you've changed from it, and the error message doesn't tell much. Could you include the full code sample you're using?

- Andrew

To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-cloud-endpoints/7daf49ab-78b7-4609-8aee-e32450a50d2b%40googlegroups.com.

aoinami.1...@gmail.com

unread,
Aug 14, 2018, 10:43:57 PM8/14/18
to Google Cloud Endpoints
Thank you, Andrew! 

Changes only includes my default service account mail: CLIENT...@appspot.gserviceaccount.com and API server HOST = SERVER_PRJ_ID.appspot.com

SERVICE_ACCOUNT_EMAIL = "CLIENT...@appspot.gserviceaccount.com"
TARGET_AUD = "https:// SERVER_PRJ_ID.appspot.com"


def generate_jwt():
    """Generates a signed JSON Web Token using the Google App Engine default
    service account."""
    now = int(time.time())

    header_json = json.dumps({
        "typ": "JWT",
        "alg": "RS256"})

    payload_json = json.dumps({
        "iat": now,
        # expires after one hour.
        "exp": now + 3600,
        # iss is the service account email.
        "iss": SERVICE_ACCOUNT_EMAIL,
        # target_audience is the URL of the target service.
        "target_audience": TARGET_AUD,
        # aud must be Google token endpoints URL.
        #"email": SERVICE_ACCOUNT_EMAIL
    })

    header_and_payload = '{}.{}'.format(
        base64.urlsafe_b64encode(header_json),
        base64.urlsafe_b64encode(payload_json))
    (key_name, signature) = app_identity.sign_blob(header_and_payload)
    signed_jwt = '{}.{}'.format(
        header_and_payload,
        base64.urlsafe_b64encode(signature))

    return signed_jwt


def get_id_token():
    """Request a Google ID token using a JWT."""
    params = urllib.urlencode({
        'grant_type': 'urn:ietf:params:oauth:grant-type:jwt-bearer',
        'assertion': generate_jwt()})
    headers = {"Content-Type": "application/x-www-form-urlencoded"}
    conn = httplib.HTTPSConnection("www.googleapis.com")
    conn.request("POST", "/oauth2/v4/token", params, headers)
    res = json.loads(conn.getresponse().read())
    conn.close()
    return res['id_token']


def make_request(token):
    """Makes a request to the auth info endpoint for Google ID token."""
    headers = {'Authorization': 'Bearer {}'.format(token)}
    conn = httplib.HTTPSConnection(HOST)
    conn.request("GET", '/_ah/api/echo/v1/echo/getUserEmail', None, headers)
    res = conn.getresponse()
    conn.close()
    return res.read()


class MainPage(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        token = get_id_token()
        self.response.write(token)
        #api_root = 'https:// SERVER_PRJ_ID.appspot.com/_ah/api'
        #api = 'echo'
        #version = 'v1'
        #discovery_url = '%s/discovery/v1/apis/%s/%s/rest' % (api_root, api, version)
        #credentials = AccessTokenCredentials(token, 'my-user-agent/1.0')
        #http = httplib2.Http()
        #http = credentials.authorize(http)       
        #service = build(api, version, discoveryServiceUrl=discovery_url, http=http)
        #response = service.get_user_email().execute()
        # response
        #self.response.write(response)
        
        res = make_request(token)
        self.response.write(res)

app = webapp2.WSGIApplication([
    ('/', MainPage),
], debug=True)


@endpoints.api(
name='echo',
version='v1',
issuers={'serviceAccount': endpoints.Issuer(
audiences={'serviceAccount': 'https://www.googleapis.com/oauth2/v4/token'})


And also set security definitions in Open API doc as following (I added gae_default_service_account because first attempt was to use https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/endpoints/getting-started/clients/service_to_service_gae_default as I am usind service default account of Client GAE app to authentication, but it was also 401 error and documentation saying about google id token https://cloud.google.com/endpoints/docs/openapi/service-account-authentication so I switched to use google id token for authentication) 
..
  "securityDefinitions": {
    "api_key": {
      "in": "query",
      "name": "key",
      "type": "apiKey"
    },
    "google_id_token": {
      "authorizationUrl": "",
      "flow": "implicit",
      "type": "oauth2",
      "x-google-issuer": "CLIENT...@appspot.gserviceaccount.com",
      "x-google-jwks_uri": "www.googleapis.com/oauth2/v4/token",
      "x-google-audiences": "www.googleapis.com/oauth2/v4/token"
    },
    "google_id_token-c0b0c9d9": {
      "authorizationUrl": "",
      "flow": "implicit",
      "type": "oauth2",
      "x-google-audiences": "www.googleapis.com/oauth2/v4/token",
      "x-google-issuer": "https://accounts.google.com",
      "x-google-jwks_uri": "www.googleapis.com/oauth2/v4/token"
    },
    "gae_default_service_account": {
     "authorizationUrl" : "",
     "flow": "implicit",
     "type": "oauth2",
     "x-google-issuer": "CLIENT...@appspot.gserviceaccount.com",
     "x-google-audiences": "www.googleapis.com/oauth2/v4/token"
     }
  },
  "swagger": "2.0"

hope this clarify my settings 
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

Andrew Gunsch

unread,
Aug 15, 2018, 6:12:53 PM8/15/18
to aoinami.1...@gmail.com, google-clou...@googlegroups.com
> And also set security definitions in Open API doc as following (I added gae_default_service_account because first attempt was to use https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/endpoints/getting-started/clients/service_to_service_gae_default as I am usind service default account of Client GAE app to authentication, but it was also 401 error and documentation saying about google id token https://cloud.google.com/endpoints/docs/openapi/service-account-authentication so I switched to use google id token for authentication) 

I think we might need a big warning on the OpenAPI docs that says "nothing in here applies to Endpoints Frameworks" :) Since you have an Endpoints Frameworks app, the API annotations are the only part that matters here in terms of authentication.

That said, I'm not seeing much that's obviously wrong. If you're willing to privately send me your project ID / URL you've deployed this app on, we can try making auth'd requests directly to it and look at the logs.

To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-cloud-endpoints/08fb76bc-7636-4a95-928b-96351f5c6c02%40googlegroups.com.

Marina Lanyugina

unread,
Aug 16, 2018, 1:23:47 PM8/16/18
to Andrew Gunsch, google-clou...@googlegroups.com
Thanks Andrew!

"I think we might need a big warning on the OpenAPI docs that says "nothing in here applies to Endpoints Frameworks" :) " yes, I think I started to mix  OpenAPI and Endpoints docs :)
So, does this mean that frameworks v2 library will generate appropriate Open API docs and there will be no need to add some additional sections manually?
my URL of client making call to API is https://api-ml-213516.appspot.com/
API backend GAE Std URL is https://apitest-ml-server.appspot.com

Thank you 
Marina

Sincerely Yours,
KUZMENKO MARINA

On Wed, Aug 15, 2018 at 3:12 PM, Andrew Gunsch <gun...@google.com> wrote:
> And also set security definitions in Open API doc as following (I added gae_default_service_account because first attempt was to use https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/endpoints/getting-started/clients/service_to_service_gae_default as I am usind service default account of Client GAE app to authentication, but it was also 401 error and documentation saying about google id token https://cloud.google.com/endpoints/docs/openapi/service-account-authentication so I switched to use google id token for authentication) 

I think we might need a big warning on the OpenAPI docs that says "nothing in here applies to Endpoints Frameworks" :) Since you have an Endpoints Frameworks app, the API annotations are the only part that matters here in terms of authentication.

That said, I'm not seeing much that's obviously wrong. If you're willing to privately send me your project ID / URL you've deployed this app on, we can try making auth'd requests directly to it and look at the logs.

On Tue, Aug 14, 2018 at 7:44 PM <aoinami.1...@gmail.com> wrote:
Thank you, Andrew! 

Changes only includes my default service account mail: CLIENT_PRJ_ID@appspot.gserviceaccount.com and API server HOST = SERVER_PRJ_ID.appspot.com

audiences={'serviceAccount': 'https://www.googleapis.com/oauth2/v4/token'})


And also set security definitions in Open API doc as following (I added gae_default_service_account because first attempt was to use https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/endpoints/getting-started/clients/service_to_service_gae_default as I am usind service default account of Client GAE app to authentication, but it was also 401 error and documentation saying about google id token https://cloud.google.com/endpoints/docs/openapi/service-account-authentication so I switched to use google id token for authentication) 
..
  "securityDefinitions": {
    "api_key": {
      "in": "query",
      "name": "key",
      "type": "apiKey"
    },
    "google_id_token": {
      "authorizationUrl": "",
      "flow": "implicit",
      "type": "oauth2",
      "x-google-issuer": "CLIENT_PRJ_ID@appspot.gserviceaccount.com",
      "x-google-jwks_uri": "www.googleapis.com/oauth2/v4/token",
      "x-google-audiences": "www.googleapis.com/oauth2/v4/token"
    },
    "google_id_token-c0b0c9d9": {
      "authorizationUrl": "",
      "flow": "implicit",
      "type": "oauth2",
      "x-google-audiences": "www.googleapis.com/oauth2/v4/token",
      "x-google-issuer": "https://accounts.google.com",
      "x-google-jwks_uri": "www.googleapis.com/oauth2/v4/token"
    },
    "gae_default_service_account": {
     "authorizationUrl" : "",
     "flow": "implicit",
     "type": "oauth2",
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

D. T.

unread,
Aug 16, 2018, 4:41:08 PM8/16/18
to aoinami.1...@gmail.com, Andrew Gunsch, Google Cloud Endpoints
Pardon my confusion, but if you're trying to use Google ID tokens with service accounts, why does your @api annotation use a service account issuer?

Daniel Tang | Software Engineer | ta...@google.com | Google LLC



On Thu, Aug 16, 2018 at 10:23 AM Marina Lanyugina <aoinami.1...@gmail.com> wrote:
Thanks Andrew!

"I think we might need a big warning on the OpenAPI docs that says "nothing in here applies to Endpoints Frameworks" :) " yes, I think I started to mix  OpenAPI and Endpoints docs :)
So, does this mean that frameworks v2 library will generate appropriate Open API docs and there will be no need to add some additional sections manually?
my URL of client making call to API is https://api-ml-213516.appspot.com/
API backend GAE Std URL is https://apitest-ml-server.appspot.com

Thank you 
Marina

Sincerely Yours,
KUZMENKO MARINA

On Wed, Aug 15, 2018 at 3:12 PM, Andrew Gunsch <gun...@google.com> wrote:
> And also set security definitions in Open API doc as following (I added gae_default_service_account because first attempt was to use https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/endpoints/getting-started/clients/service_to_service_gae_default as I am usind service default account of Client GAE app to authentication, but it was also 401 error and documentation saying about google id token https://cloud.google.com/endpoints/docs/openapi/service-account-authentication so I switched to use google id token for authentication) 

I think we might need a big warning on the OpenAPI docs that says "nothing in here applies to Endpoints Frameworks" :) Since you have an Endpoints Frameworks app, the API annotations are the only part that matters here in terms of authentication.

That said, I'm not seeing much that's obviously wrong. If you're willing to privately send me your project ID / URL you've deployed this app on, we can try making auth'd requests directly to it and look at the logs.

On Tue, Aug 14, 2018 at 7:44 PM <aoinami.1...@gmail.com> wrote:
Thank you, Andrew! 

Changes only includes my default service account mail: CLIENT...@appspot.gserviceaccount.com and API server HOST = SERVER_PRJ_ID.appspot.com

SERVICE_ACCOUNT_EMAIL = "CLIENT...@appspot.gserviceaccount.com"
audiences={'serviceAccount': 'https://www.googleapis.com/oauth2/v4/token'})


And also set security definitions in Open API doc as following (I added gae_default_service_account because first attempt was to use https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/endpoints/getting-started/clients/service_to_service_gae_default as I am usind service default account of Client GAE app to authentication, but it was also 401 error and documentation saying about google id token https://cloud.google.com/endpoints/docs/openapi/service-account-authentication so I switched to use google id token for authentication) 
..
  "securityDefinitions": {
    "api_key": {
      "in": "query",
      "name": "key",
      "type": "apiKey"
    },
    "google_id_token": {
      "authorizationUrl": "",
      "flow": "implicit",
      "type": "oauth2",
      "x-google-issuer": "CLIENT...@appspot.gserviceaccount.com",
      "x-google-jwks_uri": "www.googleapis.com/oauth2/v4/token",
      "x-google-audiences": "www.googleapis.com/oauth2/v4/token"
    },
    "google_id_token-c0b0c9d9": {
      "authorizationUrl": "",
      "flow": "implicit",
      "type": "oauth2",
      "x-google-audiences": "www.googleapis.com/oauth2/v4/token",
      "x-google-issuer": "https://accounts.google.com",
      "x-google-jwks_uri": "www.googleapis.com/oauth2/v4/token"
    },
    "gae_default_service_account": {
     "authorizationUrl" : "",
     "flow": "implicit",
     "type": "oauth2",
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/google-cloud-endpoints/CAGFyOiGHa8akSRch6kiG-az8ARgjjHgLCa2uFO9%3D1KmX6Ucpcw%40mail.gmail.com.

Marina Lanyugina

unread,
Aug 16, 2018, 8:58:16 PM8/16/18
to D. T., Andrew Gunsch, Google Cloud Endpoints
Yes, Daniel, actually I realized that I generated echov1openapi.json only once at the beginning with @endpoints.api(
name='echo', version='v1') 
After class decorated with 'ServiceAccount' issuer, I didn't re-generated. Thank you for pointing me out to my miss. 

I tried to generated again with decoration, but now unfortunately encounters this error:
python-docs-samples/appengine/standard/endpoints-frameworks-v2/echo/lib/endpoints/openapi_generator.py", line 779, in __security_descriptor
    raise TypeError('Missing issuer {}'.format(issuer))
TypeError: Missing issuer google_id_token
I googled and found this answer 
https://stackoverflow.com/questions/51487510/missing-issuer-google-id-token-when-generating-openapi-doc-for-cloud-endpoints
Error is the same "Missing issuer google_id_token" even if I pass a dict as audiences: 
@endpoints.api(
	name='echo', version='v1',
	issuers={'ServiceAccount': endpoints.Issuer(
        'api-ml...@appspot.gserviceaccount.com',
        'https://www.googleapis.com/robot/v1/metadata/x509/api-ml...@appspot.gserviceaccount.com')},
	audiences={'ServiceAccount': ['https://apitest-ml-server.appspot.com']}
)
does it mean that only google id token could be used to authenticate calls to endpoints in std environment? in my understanding in case of flexible env 
ESP does auth part instead of framework lib and yaml is not generated from parsing API class? 
Thanks,
Marina

Sincerely Yours,
KUZMENKO MARINA

On Fri, Aug 17, 2018 at 5:40 AM, Daniel Tang <ta...@google.com> wrote:
Pardon my confusion, but if you're trying to use Google ID tokens with service accounts, why does your @api annotation use a service account issuer?

Daniel Tang | Software Engineer | ta...@google.com | Google LLC



On Thu, Aug 16, 2018 at 10:23 AM Marina Lanyugina <aoinami.1...@gmail.com> wrote:
Thanks Andrew!

"I think we might need a big warning on the OpenAPI docs that says "nothing in here applies to Endpoints Frameworks" :) " yes, I think I started to mix  OpenAPI and Endpoints docs :)
So, does this mean that frameworks v2 library will generate appropriate Open API docs and there will be no need to add some additional sections manually?
my URL of client making call to API is https://api-ml-213516.appspot.com/
API backend GAE Std URL is https://apitest-ml-server.appspot.com

Thank you 
Marina

Sincerely Yours,
KUZMENKO MARINA

On Wed, Aug 15, 2018 at 3:12 PM, Andrew Gunsch <gun...@google.com> wrote:
> And also set security definitions in Open API doc as following (I added gae_default_service_account because first attempt was to use https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/endpoints/getting-started/clients/service_to_service_gae_default as I am usind service default account of Client GAE app to authentication, but it was also 401 error and documentation saying about google id token https://cloud.google.com/endpoints/docs/openapi/service-account-authentication so I switched to use google id token for authentication) 

I think we might need a big warning on the OpenAPI docs that says "nothing in here applies to Endpoints Frameworks" :) Since you have an Endpoints Frameworks app, the API annotations are the only part that matters here in terms of authentication.

That said, I'm not seeing much that's obviously wrong. If you're willing to privately send me your project ID / URL you've deployed this app on, we can try making auth'd requests directly to it and look at the logs.

On Tue, Aug 14, 2018 at 7:44 PM <aoinami.1...@gmail.com> wrote:
Thank you, Andrew! 

Changes only includes my default service account mail: CLIENT_PRJ_ID@appspot.gserviceaccount.com and API server HOST = SERVER_PRJ_ID.appspot.com

audiences={'serviceAccount': 'https://www.googleapis.com/oauth2/v4/token'})


And also set security definitions in Open API doc as following (I added gae_default_service_account because first attempt was to use https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/endpoints/getting-started/clients/service_to_service_gae_default as I am usind service default account of Client GAE app to authentication, but it was also 401 error and documentation saying about google id token https://cloud.google.com/endpoints/docs/openapi/service-account-authentication so I switched to use google id token for authentication) 
..
  "securityDefinitions": {
    "api_key": {
      "in": "query",
      "name": "key",
      "type": "apiKey"
    },
    "google_id_token": {
      "authorizationUrl": "",
      "flow": "implicit",
      "type": "oauth2",
      "x-google-issuer": "CLIENT_PRJ_ID@appspot.gserviceaccount.com",
      "x-google-jwks_uri": "www.googleapis.com/oauth2/v4/token",
      "x-google-audiences": "www.googleapis.com/oauth2/v4/token"
    },
    "google_id_token-c0b0c9d9": {
      "authorizationUrl": "",
      "flow": "implicit",
      "type": "oauth2",
      "x-google-audiences": "www.googleapis.com/oauth2/v4/token",
      "x-google-issuer": "https://accounts.google.com",
      "x-google-jwks_uri": "www.googleapis.com/oauth2/v4/token"
    },
    "gae_default_service_account": {
     "authorizationUrl" : "",
     "flow": "implicit",
     "type": "oauth2",
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

Andrew Gunsch

unread,
Aug 17, 2018, 1:59:14 PM8/17/18
to aoinami.1...@gmail.com, D. T., google-clou...@googlegroups.com, Rose Davidson
On Thu, Aug 16, 2018 at 5:58 PM Marina Lanyugina <aoinami.1...@gmail.com> wrote:
Yes, Daniel, actually I realized that I generated echov1openapi.json only once at the beginning with @endpoints.api(
name='echo', version='v1') 
After class decorated with 'ServiceAccount' issuer, I didn't re-generated. Thank you for pointing me out to my miss. 

I tried to generated again with decoration, but now unfortunately encounters this error:
python-docs-samples/appengine/standard/endpoints-frameworks-v2/echo/lib/endpoints/openapi_generator.py", line 779, in __security_descriptor
    raise TypeError('Missing issuer {}'.format(issuer))
TypeError: Missing issuer google_id_token
I googled and found this answer 
https://stackoverflow.com/questions/51487510/missing-issuer-google-id-token-when-generating-openapi-doc-for-cloud-endpoints
Error is the same "Missing issuer google_id_token" even if I pass a dict as audiences: 
@endpoints.api(
	name='echo', version='v1',
	issuers={'ServiceAccount': endpoints.Issuer(
        'api-ml...@appspot.gserviceaccount.com',
        'https://www.googleapis.com/robot/v1/metadata/x509/api-ml...@appspot.gserviceaccount.com')},
	audiences={'ServiceAccount': ['https://apitest-ml-server.appspot.com']}
)
does it mean that only google id token could be used to authenticate calls to endpoints in std environment?
Not quite --- the same auth mechanisms (e.g. Google ID Token) work for both Standard and Flex. You just configure the server differently for each, but the client should be the same.

+rhd for any other suggestions here on debugging this.
in my understanding in case of flexible env 
ESP does auth part instead of framework lib and yaml is not generated from parsing API class? 
That's right --- In Flex, ESP handles auth based on the OpenAPI specification you upload. On Standard/Frameworks, the generated YAML is mostly just so we can generate the correct analytics/dashboards in the Cloud Console.
 
Thanks,
Marina

Sincerely Yours,
KUZMENKO MARINA


Sincerely Yours,
KUZMENKO MARINA

Thank you, Andrew! 

Changes only includes my default service account mail: CLIENT...@appspot.gserviceaccount.com and API server HOST = SERVER_PRJ_ID.appspot.com

SERVICE_ACCOUNT_EMAIL = "CLIENT...@appspot.gserviceaccount.com"
audiences={'serviceAccount': 'https://www.googleapis.com/oauth2/v4/token'})


And also set security definitions in Open API doc as following (I added gae_default_service_account because first attempt was to use https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/endpoints/getting-started/clients/service_to_service_gae_default as I am usind service default account of Client GAE app to authentication, but it was also 401 error and documentation saying about google id token https://cloud.google.com/endpoints/docs/openapi/service-account-authentication so I switched to use google id token for authentication) 
..
  "securityDefinitions": {
    "api_key": {
      "in": "query",
      "name": "key",
      "type": "apiKey"
    },
    "google_id_token": {
      "authorizationUrl": "",
      "flow": "implicit",
      "type": "oauth2",
      "x-google-issuer": "CLIENT...@appspot.gserviceaccount.com",
      "x-google-jwks_uri": "www.googleapis.com/oauth2/v4/token",
      "x-google-audiences": "www.googleapis.com/oauth2/v4/token"
    },
    "google_id_token-c0b0c9d9": {
      "authorizationUrl": "",
      "flow": "implicit",
      "type": "oauth2",
      "x-google-audiences": "www.googleapis.com/oauth2/v4/token",
      "x-google-issuer": "https://accounts.google.com",
      "x-google-jwks_uri": "www.googleapis.com/oauth2/v4/token"
    },
    "gae_default_service_account": {
     "authorizationUrl" : "",
     "flow": "implicit",
     "type": "oauth2",
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endp...@googlegroups.com.

Rose Davidson

unread,
Aug 21, 2018, 7:15:36 PM8/21/18
to Andrew Gunsch, aoinami.1...@gmail.com, D. T., Google Cloud Endpoints
It's possible to pass either a dict or a list (or tuple) as the audiences value. Passing a list/tuple is treated by the openapi generation code as the same thing as passing a dict with the key 'google_id_token'.

That is, audiences=['foo', 'bar'] is treated as audiences={'google_id_token': ['foo', 'bar']} when it comes to generating the openapi spec. Every key in the audiences dict must correspond to a key in the issuers dict.

However, the framework does not currently allow using a dict for audiences to actually work for Google ID token authentication. That is, the dict must be present in order to generate the openapi yaml, but it must be absent when actually running the app. I recognize this is not ideal and I'm looking for the best way to fix it.


Marina Lanyugina

unread,
Aug 21, 2018, 11:18:07 PM8/21/18
to Rose Davidson, Andrew Gunsch, D. T., Google Cloud Endpoints
Thank you very much for detailed clarifications! It really helps! and I could not figure it out from the documentation...

On Wed, Aug 22, 2018 at 8:15 AM, Rose Davidson <r...@google.com> wrote:
It's possible to pass either a dict or a list (or tuple) as the audiences value. Passing a list/tuple is treated by the openapi generation code as the same thing as passing a dict with the key 'google_id_token'.

That is, audiences=['foo', 'bar'] is treated as audiences={'google_id_token': ['foo', 'bar']} when it comes to generating the openapi spec. Every key in the audiences dict must correspond to a key in the issuers dict.

However, the framework does not currently allow using a dict for audiences to actually work for Google ID token authentication. That is, the dict must be present in order to generate the openapi yaml, but it must be absent when actually running the app. I recognize this is not ideal and I'm looking for the best way to fix it.


On Fri, Aug 17, 2018 at 10:59 AM Andrew Gunsch <gun...@google.com> wrote:
On Thu, Aug 16, 2018 at 5:58 PM Marina Lanyugina <aoinami.1...@gmail.com> wrote:
Yes, Daniel, actually I realized that I generated echov1openapi.json only once at the beginning with @endpoints.api(
name='echo', version='v1') 
After class decorated with 'ServiceAccount' issuer, I didn't re-generated. Thank you for pointing me out to my miss. 

I tried to generated again with decoration, but now unfortunately encounters this error:
python-docs-samples/appengine/standard/endpoints-frameworks-v2/echo/lib/endpoints/openapi_generator.py", line 779, in __security_descriptor
    raise TypeError('Missing issuer {}'.format(issuer))
TypeError: Missing issuer google_id_token
I googled and found this answer 
https://stackoverflow.com/questions/51487510/missing-issuer-google-id-token-when-generating-openapi-doc-for-cloud-endpoints
Error is the same "Missing issuer google_id_token" even if I pass a dict as audiences: 
@endpoints.api(
	name='echo', version='v1',
	issuers={'ServiceAccount': endpoints.Issuer(
        'api-ml-213516@appspot.gserviceaccount.com',
        'https://www.googleapis.com/robot/v1/metadata/x509/api-ml-213516@appspot.gserviceaccount.com')},
	audiences={'ServiceAccount': ['https://apitest-ml-server.appspot.com']}
)
Thanks,
Marina

Sincerely Yours,
KUZMENKO MARINA


Sincerely Yours,
KUZMENKO MARINA

Thank you, Andrew! 

Changes only includes my default service account mail: CLIENT_PRJ_ID@appspot.gserviceaccount.com and API server HOST = SERVER_PRJ_ID.appspot.com

audiences={'serviceAccount': 'https://www.googleapis.com/oauth2/v4/token'})


And also set security definitions in Open API doc as following (I added gae_default_service_account because first attempt was to use https://github.com/GoogleCloudPlatform/python-docs-samples/tree/master/endpoints/getting-started/clients/service_to_service_gae_default as I am usind service default account of Client GAE app to authentication, but it was also 401 error and documentation saying about google id token https://cloud.google.com/endpoints/docs/openapi/service-account-authentication so I switched to use google id token for authentication) 
..
  "securityDefinitions": {
    "api_key": {
      "in": "query",
      "name": "key",
      "type": "apiKey"
    },
    "google_id_token": {
      "authorizationUrl": "",
      "flow": "implicit",
      "type": "oauth2",
      "x-google-issuer": "CLIENT_PRJ_ID@appspot.gserviceaccount.com",
      "x-google-jwks_uri": "www.googleapis.com/oauth2/v4/token",
      "x-google-audiences": "www.googleapis.com/oauth2/v4/token"
    },
    "google_id_token-c0b0c9d9": {
      "authorizationUrl": "",
      "flow": "implicit",
      "type": "oauth2",
      "x-google-audiences": "www.googleapis.com/oauth2/v4/token",
      "x-google-issuer": "https://accounts.google.com",
      "x-google-jwks_uri": "www.googleapis.com/oauth2/v4/token"
    },
    "gae_default_service_account": {
     "authorizationUrl" : "",
     "flow": "implicit",
     "type": "oauth2",
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Google Cloud Endpoints" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-cloud-endpoints+unsub...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages