This is an example Apigee proxy that illustrates how to use Apigee to dispense tokens,
using an ID token generated by Firebase Auth, for the user credential. It will use the grant type of
urn:ietf:params:oauth:grant-type:jwt-bearer
.
The tokens dispensed here are opaque OAuth 2.0 access tokens.
This example has been tested with Apigee X.
This example is not an official Google product, nor is it part of an official Google product.
This material is Copyright 2024, Google LLC. and is licensed under the Apache 2.0 license. See the LICENSE file.
This code is open source but you don't need to compile it in order to use it.
-
modify the VerifyJWT-Firebase-Id-Token policy to replace
your-project-id
with your project ID, in two places. -
Install the apigeecli tool, if you don't have it.
curl -s https://raw.githubusercontent.com/apigee/apigeecli/master/downloadLatest.sh | bash export PATH=$PATH:$HOME/.apigeecli/bin
-
Import the proxy into any Apigee organization.
TOKEN=$(gcloud auth print-access-token) ORG=my-apigee-org ENV=my-apigee-env apigeecli apis create bundle -f apiproxy --name oauth2-firebase-id -o $ORG --token $TOKEN apigeecli apis deploy --wait --name oauth2-firebase-id --ovr --org $ORG --env $ENV --token $TOKEN
-
Create an API product. The API product normally wraps API proxies with metadata. For the purposes of this example, your API product need not contain any API proxies. This is because in this example, we do not actually verify the token in this example. We only issue the token.
PRODUCT_NAME=apigee-test-product apigeecli products create --name "${PRODUCT_NAME}" --displayname "${PRODUCT_NAME}" \ --envs "$ENV" --approval auto \ --org "$ORG" --token "$TOKEN"
-
Create a Developer within Apigee
DEVELOPER_EMAIL="example-developer@cymbalgroup.com" apigeecli developers create --user "${DEVELOPER_EMAIL}" --email "${DEVELOPER_EMAIL}" \ --first Example --last Developer \ --org "$ORG" --token "$TOKEN"
-
Create a Developer App within Apigee, which is associated to the new Developer, and with authorization to use the API product.
APP_NAME=example-app-1 apigeecli apps create --name "${APP_NAME}" --email "${DEVELOPER_EMAIL}" \ --prods "${PRODUCT_NAME}" --org "$ORG" --token "$TOKEN"
View and copy the consumerKey :
CLIENT_ID=value-from-consumerKey-in-the-output
-
Obtain your Firebase Auth ID token. (This step is left to you)
-
With that ID token, and the client ID you obtained in the setup step, invoke the access-token-dispensing proxy to generate and retrieve a token:
endpoint=https://endpoint-for-your-apigee-environment.io FIREBASE_ID_TOKEN=eyJhbGciOiJSUzI1N...full-token-here curl -i -X POST -H 'content-type: application/x-www-form-urlencoded' \ "$endpoint/oauth2-firebase-id/token" \ -d 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer' \ -d "client_id=$CLIENT_ID" \ -d "assertion=$FIREBASE_ID_TOKEN"
The response you see will look like this:
HTTP/2 200 token: access_token=b9g7tIQa2niYB9pYWALw6Rv6mhkW content-length: 321 date: Tue, 09 Jan 2024 18:25:42 GMT via: 1.1 google { "token_type": "Bearer", "access_token": "b9g7tIQa2niYB9pYWALw6Rv6mhkW", "expires_in": 1799, "issued_at": 1704824742674, "refresh_token": "IU89ziyPrwsRgqupAAGvPiXpo7hs2oi3", "authenticated_user": "dchiesa001@gmail.com", "auth_time": 1704824425, "refresh_token_expires_in": 86399, "refresh_count": "0" }
The access token is an opaque access token. You can then use it as a bearer token for invoking APIs managed within Apigee. That is not shown in this example.
This API proxy dispenses opaque OAuth access tokens, using the jwt-bearer grant type. Essentially,
- Apigee uses the Firebase-generated ID token to authenticate the user
- Apigee uses the client ID to authenticater or identify the client app
If both of those are successful, Apigee generates an access token. The access token includes a custom attribute, stored internally in the key-management database within Apigee, containing the email of the user that was originally authenticated by Firebase.
Later, when you use OAuthV2/VerifyAccessToken on that token, your proxy wil be able to see the value of that custom attribute, and identify the originally authenticated user.
The tokens issued by this API proxy are "opaque", and are not JWT. JWT is one possible format for tokens. An opaque token, just a random string, is another possible format. Apigee can generate and return JWT, that function in much the same way as the opaque oauth tokens shown here. This is not implemented in this example API Proxy.
-
get the ID of the developer:
apigeecli developers get --email "${DEVELOPER_EMAIL}" --org "$ORG" --token "$TOKEN" DEVELOPER_ID=...resulting developerId from above...
-
remove the developer app
apigeecli apps delete --id "${DEVELOPER_ID}" --name "${APP_NAME}" --org "$ORG" --token "$TOKEN"
-
remove the developer
apigeecli developers delete --email "${DEVELOPER_EMAIL}" --org "$ORG" --token "$TOKEN"
-
delete the example API product
apigeecli products delete --name "${PRODUCT_NAME}" --org "$ORG" --token "$TOKEN"
-
get the revision of the deployed API proxy:
apigeecli apis listdeploy --name "oauth2-firebase-id" --org "$ORG" --token "$TOKEN" REV=...revision-from-above...
Then undeploy it:
apigeecli apis undeploy --name "oauth2-firebase-id" --env "$ENV" --rev "$REV" --org "$ORG" --token "$TOKEN"
-
delete the API proxy:
apigeecli apis delete --name "oauth2-firebase-id" --org "$ORG" --token "$TOKEN"
Done.