How to set up custom user authentication with Google Cloud Endpoints - google-cloud-endpoints

I am trying to understand how to use Cloud Endpoints with custom authentication. From the docs I understand that it starts from the securityDefinitions:
securityDefinitions:
your_custom_auth_id:
authorizationUrl: ""
flow: "implicit"
type: "oauth2"
# The value below should be unique
x-google-issuer: "issuer of the token"
x-google-jwks_uri: "url to the public key"
# Optional. Replace YOUR-CLIENT-ID with your client ID
x-google-audiences: "YOUR-CLIENT-ID"
This is how I understand the flow:
API consumer sends a request with a JWT token in the header
ESP validates this token using the authorizationUrl
The request is forwarded or ESP returns an error.
My questions:
Is the flow above correct?
How should the authorizationUrl be implemented. How does the request look, what response should be return in case of success or failure
What about this values?
x-google-issuer: "issuer of the token"
x-google-jwks_uri: "url to the public key"
x-google-audiences: "YOUR-CLIENT-ID"

Configuring Custom Authentication for Endpoints
To configure custom authentication for Endpoints (and according to the OpenAPI v2 spec), you need two pieces:
Define your custom authentication scheme in the securityDefinitions section of the spec
Apply your custom authentication scheme (defined in #1) to the entire api or to specific operations using the security field.
The Google Cloud Endpoints docs describe this here.
OpenAPI Spec's SecurityDefinitions
Some fields in the SecurityDefinitions section of the OpenAPI spec are for the API producer, and some are for the API consumer.
The following fields are for the API producer and tell Endpoints how to validate the access tokens that accompany API requests:
type: "oauth2"
x-google-issuer: "issuer of the token"
x-google-jwks_uri: "url to the public key"
x-google-audiences: "YOUR-CLIENT-ID"
These fields are specified by the API producer and tell the consumer how to get a valid access token:
authorizationUrl
flow
Re:Your Questions
Correct. Here is documentation on how the consumer should send the access token with the request
ESP validates the access token using the public keys specified in the x-google-jwks_uri property of the spec and ensures that the issuer of the token matches the issuer specified in the securityDefinition's x-google-issuer field.
Correct.
Regarding your questions, the authorizationUrl should be set up by the OAuth2 provider you are using. That url should allow the consumer to execute the implicit OAuth2 flow to get an access token. All you need to do is specify this

Related

Need help setting up Postman Collection Authorization with API Token and Credentials

I am learning to connect to one of our 3rd party's API, and the first step in doing so is to first get an access token to use for additional requests.
To get that access token, I send a POST request that includes an API key in the header, along with the username and password in the body (as JSON). And that successfully returns a token.
But how do I set up that up in a collection? In postman I have options of API token, Basic Auth, Oath2, etc. But I do not see how you set up and include both the API key and user/password.
I've tried different scenario's of just the API Key and Oath2 with credentials, but unsure how you set it up to include both.

Firebase Cloud Function HTTP Request Authorization

I have a scenario where I need to do a secure request a Firebase Cloud Function from an external server using a HTTP request. In order to request it I need to send a bearer JWT token on the authorization header. After sometime looking at the Google documents to Firebase/GCP I've found many different ways to authenticate using google different APIs, but I'm kinda lost on it.
I know that I need to use a service account in order to identify the machine that is calling instead a common human-user credentials. I also know that the service account provides a JSON file that contains secure information to identify that service account, like the private key. By looking different docs I found this one that explains how to generate and request a token. After following those steps, I'm facing a 403 status when I try to call the cloud function using the resulting token.
I doubled checked the roles my service account has and I do have the ones the docs have pointed me.
Does anyone knows or have any suggestions how to proceed to have cloud function authorized calls by a machine (not human) interaction.
Edit 1:
As requested here I'm posting my JWT generator code:
const {
private_key_id,
private_key,
client_email,
} = require('./serviceAccount.json');
const jwt = require('jsonwebtoken');
const payload = {
"kid": private_key_id,
"iss": client_email,
"sub": client_email,
"iat": 1611257400,
"exp": 1611260940,
"aud": "https://oauth2.googleapis.com/token",
"target_audience": "https://<project- region>.cloudfunctions.net/helloWorld"
};
const token = jwt.sign(payload, private_key, { algorithm: 'RS256', header: {"alg":"RS256","typ":"JWT"} });
console.log(token);
With the result token from above I'm sending a POST request to https://oauth2.googleapis.com/token where the token is sent as the assertion field on a form data.
After suggestions here I did some research and found this blog with instructions to generate a Identity token using my service account. So I ran:
# Load the service account identity
gcloud auth activate-service-account --key-file=key.json
# Generate an id token
gcloud auth print-identity-token
The resulting token gave me the same result a 403 - Forbidden error. The interesting part is that using my user credentials and using gcloud to generate an identity token I was able to request the Cloud function with a 200 result.
I'm thinking that I'm missing some sort of role/privilege/scope on my service account configuration.
Make sure that the service account has assigned the cloudfunctions.functions.invoke in order to guarantee that the Cloud Function can be triggered from an external server using an HTTP request.

What is the OpenID Connect access token for?

The OpenID Connect JWT token contains both an id_token and an access_token (Like "access_token": "SlAV32hkKG"). What is the access_token for?
ANSWER EXAMPLE
Just adding an example to complement the answers taken from this linked article
User Info Endpoint Request
GET /userinfo HTTP/1.1
Host: openid.c2id.com
Authorization: Bearer SlAV32hkKG
User Info Endpoint Response
HTTP/1.1 200 OK
Content-Type: application/json
{
"sub" : "alice",
"email" : "alice#wonderland.net",
"email_verified" : true,
"name" : "Alice Adams",
"picture" : "https://c2id.com/users/alice.jpg"
}
The answer to your question lies in the section 5.3 and 16.4 of the specification. The access token is used to access the userinfo endpoint which is a protected resource.
16.4. Access Token Disclosure
Access Tokens are credentials used to access Protected Resources, as defined in Section 1.4 of OAuth 2.0 [RFC6749]. Access Tokens represent an End-User's authorization and MUST NOT be exposed to unauthorized parties.
[...]
5.3. UserInfo Endpoint
The UserInfo Endpoint is an OAuth 2.0 Protected Resource that returns Claims about the authenticated End-User. To obtain the requested Claims about the End-User, the Client makes a request to the UserInfo Endpoint using an Access Token obtained through OpenID Connect Authentication. These Claims are normally represented by a JSON object that contains a collection of name and value pairs for the Claims.
tl;dr - Access token grants authorization to access a protected resource where the ID token is consumed by the client for authentication.
Access token
Being an extention to OAuth2.0, OpenID Connect keep tokens/prameters defined in OAuth2.0 specification. Access token is one such thing. As defined by the protocol, access token is used to access protected resources. It replaces user credentials, manually generated tokens or security keys which were used in good old days (ex:- Think about basic authentication).
Note the access token could be an opaque string. Which means it's nothing that could be consumed by the client which recieves it. But the authorization server knows what it is. For example, introspection endpoint (RFC7662) can be used to validate the validity of an access token. And access token can be a JWT too depending on the usage and implementation.
ID token
This is what OpenID Connect introduced to OAuth2.0. ID token is a JWT and it is consumed by client to authenticate the end user(the resource owner). By validating an ID token, client have the ability to authenticate. Due to this fact, one can argue it surves one time usage.
Also note that in some implementations, ID tokens are being used as bearer tokens. That mean, ID token used like an access token for authentication and authorization.

Gitkit token service API returns 403 "cannot be identified with a client project" error

I am currently trying to use the Google Identity Toolkit Token Service REST API (https://developers.google.com/identity/toolkit/reference/securetoken/rest/v1/token) to generate an access token which I can use in my backend server.
When I specifying "authorization_code" as "grant_type" and the gtoken cookie value after authentication as "code" in the POST request to https://securetoken.googleapis.com/v1/token, I get a 403 response with the following error message:
{
"error": {
"code": 403,
"message": "The request cannot be identified with a client project. Please pass a valid API key with the request.",
"status": "PERMISSION_DENIED"
}
}
I inspected the gtoken value via a JWT decoder and it looks to be correct in format. In particular I can see that aud is set to my application/client ID. The documentation doesn't say anything about specifying API key - usually I would expect that to be specified in the Authorization header. So I am not sure what I am missing here.
Any pointer to this matter would be appreciated.
An API key in the URL is required when calling Google Identity Toolkit APIs (including the Token Service API). However, I would suggest you take a look at the new version of the service - Firebase Authentication. The Firebase Auth SDK has build-in support of the Token Service API.

OpenIDConnect Response Type Confusion

I've spend the last few days reading through all the specs with regards to OAuth2 and OpenIDConnect and implementing a test client using Thinktecture Identity Server. I've also followed several pluralsight courses and I think understand the main gist of it. However i'm still extremely confused about the Response Types.
OpenIDConnect spec specifies that the Hybrid flow response types are a combination of "code", "id_token" and "token". I understand the "id_token" allows us to get access to basic id information initially.
I also understand code" refers to the authorization code and "token" refers to an access token and combining "code" with one or both of the other two triggers the flow but my understanding was that you swap an authorization code for an access token in the Authorization flow, while the Implicit flow supplies the Access Code implicitly?
Could someone clear up my confusion?
The following statements that you made are correct:
code refers to the Authorization Code
token refers to an Access Token or (access_token)
in the Authorization Code flow one switches the code for an access_token
But part of your confusion may originate from terminology mixup:
the term Authorization flow is not entirely correct; its official name is Authorization Code flow
the term Access Code does not exist
the Implicit flow does not have an Authorization Code (nor Access code) in fact there's no credential (or grant) involved at all that allows the Client to get tokens from the Token endpoint, hence it's name
As #juanifioren pointed out, Hybrid flows combine things:
the code id_token flow would get a code and id_token in the Authentication Response directly but you'd use the code to get an access_token from the Token endpoint
the code token flow would get a code and access_token in the Authentication Response directly but you'd use the code to get an id_token and possibly another access_token in the backend from the Token endpoint
the code id_token token flow would get a code, access_token and an id_token in the Authentication Response directly and you could use the code in the backend to get another access_token from the Token endpoint
Getting an access_token from the Token endpoint differs from getting it from the Authorization endpoint because the confidential clients authenticate themselves to the Token endpoint (and not to the Authorization endpoint). Hence the access_token for the confidential part of the client might have more permissions and or a longer life.
See also a short thread on the spec mailing list on this topic: http://lists.openid.net/pipermail/openid-specs-ab/Week-of-Mon-20150209/005229.html
To understand the possible relationships between Response Types and Grant Types see IdentityServer4\Constants.cs
public static readonly Dictionary<string, string> ResponseTypeToGrantTypeMapping = new Dictionary<string, string>
{
{ OidcConstants.ResponseTypes.Code, GrantType.AuthorizationCode },
{ OidcConstants.ResponseTypes.Token, GrantType.Implicit },
{ OidcConstants.ResponseTypes.IdToken, GrantType.Implicit },
{ OidcConstants.ResponseTypes.IdTokenToken, GrantType.Implicit },
{ OidcConstants.ResponseTypes.CodeIdToken, GrantType.Hybrid },
{ OidcConstants.ResponseTypes.CodeToken, GrantType.Hybrid },
{ OidcConstants.ResponseTypes.CodeIdTokenToken, GrantType.Hybrid }
};
Your thoughts about Authorization Code Flow and Implicit Flow are right.
But I think you are over-complicating the hybrid flow. When using hybrid you just simply can get both code and id_token.
After that, either you can grab code and exchange it for access token or just use the id_token (or access token) directly. Both approaches have their own flaws, especially in terms of security.
https://medium.com/#darutk/diagrams-of-all-the-openid-connect-flows-6968e3990660#9401
6. response_type=code token
When the value of response_type is code token, an authorization code
and an access token are issued from the authorization endpoint, and an
access token is issued from the token endpoint. In addition, if openid
is included in the scope request parameter, an ID token is issued from
the token endpoint, too.
Both the authorization endpoint and the token endpoint issue an access
token, but the contents of the access tokens are not always the same.
Regarding this, “3.3.3.8. Access Token” in OpenID Connect Core 1.0
says as follows:
If an Access Token is returned from both the Authorization Endpoint
and from the Token Endpoint, which is the case for the response_type
values code token and code id_token token, their values MAY be the
same or they MAY be different. Note that different Access Tokens might
be returned be due to the different security characteristics of the
two endpoints and the lifetimes and the access to resources granted by
them might also be different.

Resources