skip to Main Content

I have 2 apps deployed to Cloud Run, the first is Nginx serving up a React app and the other is a FastAPI API, with Identity Aware Proxy on both of the load balancers set up to check against Identity Platform.

We have an Authentication URL running gcr.io/gcip-iap/authui which I understand to be this bit of the iap-gcip-web-toolkit project.

I can generate a valid JWT to use on the backend LB with

signInWithEmailAndPassword(auth, "[email protected]", "SomePassword")
  .then((userCredential) => {
    const user = userCredential.user;
    user.getIdToken().then((token) => {
      console.log(token)
    })
  })

But that is side-stepping the fact I’m already authed and logging in again.

How can I get a user (so I can call getIdToken) given that I’m logged in already? (I see GCP_IAP_UID and __Host-GCP_IAP_AUTH_TOKEN_XXXXXXXXXX in my cookies and can load the JS/HTML for the React app)

2

Answers


  1. You don’t need to call signInWithEmailAndPassword again if you’re already authenticated. Firebase should automatically manage the session for you. You can check if the user is logged in by using auth.currentUser, and then call getIdToken() directly.

    const auth = getAuth();
    const user = auth.currentUser;
    
    if (user) {
      user.getIdToken().then((token) => {
        console.log(token); // Use this token for your backend requests
      });
    } else {
      console.log("User not authenticated");
    }
    

    If auth.currentUser is null, make sure Firebase is initialized correctly and check if the session is being persisted. Hope this works for you.

    Login or Signup to reply.
  2. It looks like you’re trying to authenticate a user for your FastAPI API running behind Identity Aware Proxy (IAP) without requiring a separate login step if the user is already authenticated through Identity Platform. To avoid duplicating authentication steps, you want to get the user’s identity (JWT) from the Identity Platform once they’ve logged in, without forcing them to sign in again using signInWithEmailAndPassword.

    Since you’re using Identity Aware Proxy (IAP), you should be able to retrieve the JWT for an authenticated user via the request headers sent to your FastAPI backend. Here’s how you can handle it:

    1. Retrieve JWT from IAP Headers:
      When a user successfully authenticates through Identity Aware Proxy, the IAP will include a x-goog-iap-jwt-assertion header in the requests forwarded to your backend service (FastAPI). This header contains a JWT that you can validate to identify the user.

    In your FastAPI app, you can extract and validate this JWT as follows:

    from fastapi import FastAPI, Request, HTTPException
    

    import google.auth.transport.requests
    from google.oauth2 import id_token

    app = FastAPI()

    Define the Cloud Run Audience

    CLOUD_RUN_AUDIENCE = "your-cloud-run-service-url"

    @app.get("/protected-route")
    async def protected_route(request: Request):
    # Extract the IAP JWT from the headers
    iap_jwt = request.headers.get("x-goog-iap-jwt-assertion")

    if not iap_jwt:
        raise HTTPException(status_code=401, detail="IAP JWT not found in headers")
    
    try:
        # Verify the IAP JWT and get the decoded claims
        request_adapter = google.auth.transport.requests.Request()
        decoded_claims = id_token.verify_oauth2_token(iap_jwt, request_adapter, CLOUD_RUN_AUDIENCE)
        
        # Extract user information from the decoded JWT
        user_email = decoded_claims["email"]
        user_id = decoded_claims["sub"]
    
        return {"message": "Authenticated", "user_email": user_email, "user_id": user_id}
    
    except ValueError as e:
        raise HTTPException(status_code=403, detail=f"Invalid IAP JWT: {str(e)}")
    

    from fastapi import FastAPI, Request, HTTPException
    import google.auth.transport.requests
    from google.oauth2 import id_token

    app = FastAPI()

    Define the Cloud Run Audience

    CLOUD_RUN_AUDIENCE = "your-cloud-run-service-url"

    @app.get("/protected-route")
    async def protected_route(request: Request):
    # Extract the IAP JWT from the headers
    iap_jwt = request.headers.get("x-goog-iap-jwt-assertion")

    if not iap_jwt:
        raise HTTPException(status_code=401, detail="IAP JWT not found in headers")
    
    try:
        # Verify the IAP JWT and get the decoded claims
        request_adapter = google.auth.transport.requests.Request()
        decoded_claims = id_token.verify_oauth2_token(iap_jwt, request_adapter, CLOUD_RUN_AUDIENCE)
        
        # Extract user information from the decoded JWT
        user_email = decoded_claims["email"]
        user_id = decoded_claims["sub"]
    
        return {"message": "Authenticated", "user_email": user_email, "user_id": user_id}
    
    except ValueError as e:
        raise HTTPException(status_code=403, detail=f"Invalid IAP JWT: {str(e)}")
    

    Key Steps:
    IAP JWT Header: The x-goog-iap-jwt-assertion header contains the JWT that proves the user’s identity. You can extract this header in FastAPI from the incoming request.

    Verify the JWT: Use Google’s id_token.verify_oauth2_token method to verify the JWT against your Cloud Run audience (the URL of your backend service). You can also use the google.auth.transport.requests.Request to create a request adapter that the verification process needs.

    Extract User Info: Once verified, the JWT payload contains user information such as email and user ID, which you can extract and use in your application.

    1. Ensure IAP Configuration:
      Your FastAPI API should be set up behind an IAP-protected Cloud Run service.
      IAP is configured to authenticate users with your Identity Platform.
      By following this approach, you avoid asking users to re-authenticate with signInWithEmailAndPassword and instead use the identity that IAP has already verified.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search