Databutton app includes a basic setup for authentication. Here's how to set it up and allowing users to sign in with email/password and Google.
Authentication Wrapper with Databutton Apps
The AuthWrapper template is included in the "components" section of any new app by default.
Alternatively, one can create this wrapper just pasting the code below.
Typically the config keys and values has this format. Take note of the firebaseConfig as you will need it later. You can also find it under Project Overview in Firebase later.
Authentication Settings - Once the project is set up, navigate to the โAuthenticationโ section in the Firebase console side menu.
Configuring Sign-In Methods - In the Authentication panel, go to the โSign-in methodโ tab. Configure sign-in providersโโโEmail/Password, Google.
Adding Authorised Domains in Firebase
Detailed Steps
To ensure application securely manages where login attempts can originate from, follow these steps to add authorized domains to your Firebase project:
Click on โAuthenticationโ in the side menu.
Select the โSettingsโ tab.
Scroll down to the โAuthorized domainsโ section.
Click on the โAdd domainโ button.
Enter databutton.com and confirm by clicking "Add"
If your app is deployed with a custom domain, you must also authorize this domain to handle user logins.
For example, if your app URL is https://avra.databutton.app/demo-authentication, add avra.databutton.app as an authorized domain.
Repeat the process: Click โAdd domainโ, enter your custom domain like YOUR_USER_NAME.databutton.app, and then confirm by clicking "Add".
Configuring your Databutton app - The final step involves adding the Firebase project ID to the Databutton secrets. This project ID is essential for the backend operations of your app. This project ID is same as in the config file which we obtain earlierโ.
We can do a manual Entryโโโ
Navigate to the โConfigโ tab in the Databutton.
Manually add the project ID as a secret with the name FIREBASE_PROJECT_NAME.
Alternatively, we can ask the AI agent to that.
Example Prompt
I would need you to add my FIREBASE_PROJECT_NAME in the secrets. Can you help me doing that?
Implementing Firebase Authentication over the app
Protecting UI Pages
Now, once we have the firebase authentication set up done, we can start protecting our UI pages.
Example prompt -
I would like to add the component #AuthWrapper and protect my page.
Code snippet from the example app
Here's an example of using AuthWrapper. Further you can also make changes by adding "Logout" button as shown in the code snippet below.
Itโs important to secure our router calls as well. This helps prevent unauthorised access to the backend services.
Here's an example prompt to do thatโ-
Hey! I would like to protect this capability so that only authenticated users can use this. Can you do that for me?
Code snippet from the example app ( Comparing protected vs non protected capabilities )
Non-protected Capabilities
from fastapi import APIRouterfrom fastapi.responses import StreamingResponsefrom pydantic import BaseModelimport databutton as dbfrom openai import OpenAIrouter =APIRouter()classStartupIdeaRequest(BaseModel): startup_topic:strclassStartupIdeaResponse(BaseModel): startup_ideas: list[str]@router.post("/generate-startup-ideas", tags=["stream"])defgenerate_startup_ideas(body: StartupIdeaRequest): OPENAI_API_KEY = db.secrets.get("OPENAI_API_KEY") client =OpenAI(api_key=OPENAI_API_KEY) prompt = f"Generate 3 innovative startup ideas in the field of {body.startup_topic}, focusing on non-coder tech co-founders. Keep the ideas concise."
defidea_generator(): response = client.chat.completions.create( model="gpt-4-0125-preview", messages=[ {"role": "system", "content": "You are an assistant that generates startup ideas."}, {"role": "user", "content": prompt} ], stream=True )for chunk in response:if chunk.choices[0].delta.content:yield chunk.choices[0].delta.contentreturnStreamingResponse(idea_generator(), media_type="text/plain")
Protected Capabilities
from fastapi import APIRouterfrom fastapi.responses import StreamingResponsefrom pydantic import BaseModelimport databutton as dbfrom openai import OpenAIfrom databutton.experimental.auth.get_user import FirebaseUserfrom fastapi import Dependsrouter =APIRouter()classStartupIdeaRequest(BaseModel): startup_topic:strclassStartupIdeaResponse(BaseModel): startup_ideas: list[str]@router.post("/generate-startup-ideas", tags=["stream"])def generate_startup_ideas(body: StartupIdeaRequest, user: FirebaseUser = Depends(db.experimental.auth.get_firebase_user)):
OPENAI_API_KEY = db.secrets.get("OPENAI_API_KEY") client =OpenAI(api_key=OPENAI_API_KEY) prompt = f"Generate 3 innovative startup ideas in the field of {body.startup_topic}, focusing on non-coder tech co-founders. Keep the ideas concise."
defidea_generator(): response = client.chat.completions.create( model="gpt-4-0125-preview", messages=[ {"role": "system", "content": "You are an assistant that generates startup ideas."}, {"role": "user", "content": prompt} ], stream=True )for chunk in response:if chunk.choices[0].delta.content:yield chunk.choices[0].delta.contentreturnStreamingResponse(idea_generator(), media_type="text/plain")
Note the usage of defined arguments - def generate_startup_ideas(body: StartupIdeaRequest, user: FirebaseUser = Depends(db.experimental.auth.get_firebase_user))
Also, the usage of additional dependencies.
from databutton.experimental.auth.get_user import FirebaseUserfrom fastapi import Depends
Under the hood, Databutton takes care of all these.
Updating Component with the protected capability
Untill now we have implemented a layer of proetction over our capability. But we have not updated the component where this capability ( FastAPI endpoint) has been used. Therefore, in our case we have the enpoint used over the ChatInput UI component and thus we will ask the agent to make the necessary changes / updates. Here's how it can be prompted -
My #AI Chatbot is updated with aunthentication. Can you read and update the changes here as well.