firebase auth with apigee


I am trying to authenticate with firebase.
However I have tried the answers to the inner cases but I have not been successful.
How can I receive the token generated by each user and validate, and then follow the process of generating an oauth2 with apigee to achieve api consumption.

 

2 1 471
1 REPLY 1


@nthrohe wrote:

I have tried the answers to the inner cases but I have not been successful.


Hmm, I'm sorry you're having trouble. I've travelled that journey of discovery as well. There are lots of different pieces. It does not help that Firebase does so many things. And also with the (kind of) recent re-architecture of the Firebase SDK, many of the older examples are no longer relevant. But it's hard to tell because the examples don't specifically say which version of the Firebase SDK they depend on.  😕


@nthrohe wrote:

How can I receive the token generated by each user and validate, and then follow the process of generating an oauth2 with apigee to achieve api consumption.


 

ok, let me restate what I think you want to do, in my own words. It sounds like you want to:

  1. use "Firebase Auth" aka "Firebase Authentication" to authenticate a user. 
  2. Get the ID token from that authentication, and then use it to ... generate an OAuth2 access token within Apigee.
  3. Use the OAuth2 token for API invocation. 

Is that about right?  This is a very reasonable thing to want to do.  And these three parts are quite distinct.  

Have you got the first part set up? I have a webapp that uses firebase SDK 10.7.1. It allows signin with email+password, or with a Google ID.  The signin code looks like this: 

import { initializeApp } from "firebase/app";
import {
  getAuth,
  signOut,
  signInWithEmailAndPassword,
  signInWithPopup,
  GoogleAuthProvider
} from "firebase/auth";

const fbapp = initializeApp(identityPlatformConfig);
const fbauth = getAuth(fbapp);
const GoogleIdProvider = (() => {
    const provider = new GoogleAuthProvider();
    provider.setCustomParameters({
      prompt: "select_account"
    });
    return provider;
  })();

function onClickSignin(event) {
  event.preventDefault();
  // either email/pw, or "signin with Google ID"
  const signin_option = $sel(`#sel-api-idp`).value;

  let p = null;
  if ( signin_option == "Google") {
    p = signInWithPopup(fbauth, GoogleIdProvider);
  } else {
    const email = document.getElementById("inputEmail").value.trim();
    const password = document.getElementById("inputPassword").value.trim();
    if (email && password) {
      p = signInWithEmailAndPassword(fbauth, email, password);
    }
  }
  if (p) {
    p = p
      .then((result) => {
        // result.user holds the ID Token, this is a JWT
      })
      .catch((error) => {
        console.log("error logging in: " + error.message);
      });
  }
  return false;
}

And the third step - use the Apigee-generated Access token to invoke APIs.... basically that's the use of OAuthV2/VerifyAccessToken.  there are numerous examples of doing that. here's one I put together some time ago.  So I suppose that 3rd part of the problem won't be hard to solve.  

So the only remaining part is the middle part - exchange the Firebase-generated ID token for an Apigee-generated access token.  

The OAuth v2.0 specification, IETF RFC 6749, describes a number of different "grant types" for issuing tokens, and the Apigee builtin policies support all of the grant types specified in that document.  grant types like: password, authorization code, implicit, or client credentials.  But, OAuthV2 is a framework, and it specifically allows "other grant types" that are not in the specification. What you are describing is similar to the password grant, but it uses a Firebase-generated ID token in place of a password.  This should be easy!

I reviewed how to use the password grant in this screencast.  You want to do something similar to that, except, rather than configuring Apigee to accept and then validate a username+password as a user credential, you want to configure Apigee to validate the ID token as a user credential.  ok how would that work? 

The ID token issued by Firebase auth is a JWT, signed with RS256, and it can be validated by "any party", any system that has access to the public key used by firebase.  Helpfully, Firebase publishes the list of public keys as a JWKS. The URL is https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com , and I beliebe this applies whether you are using Firebase Auth directly, or If you are using "Google cloud IDentity Platform", which is the enterprise offering for Firebase Auth. 

 Apigee has a builtin policy for verifying JWT, it is called VerifyJWT.  To verify a firebase-auth-generated ID token, you can configure that policy like this: 

<VerifyJWT name='VerifyJWT-Firebase-Id-Token'>
  <Algorithm>RS256</Algorithm>
  <Source>request.formparam.assertion</Source>
  <IgnoreUnresolvedVariables>false</IgnoreUnresolvedVariables>
  <PublicKey>
    <JWKS uri="https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com"/>
  </PublicKey>
  <Issuer>https://securetoken.google.com/your-project-id</Issuer>
  <Audience>your-project-id</Audience>
</VerifyJWT>

This assumes the inbound token is passed as a formparam named "assertion".   

OK, after verifying the ID token, then you just need to generate an access token.  

I put together an example that shows how to exchange Firebase ID tokens for Apigee access tokens. Find it here