I am currently using the Pyrebase wrapper to get information (such as their email and created date) of all users. I tried looking through the documentation and cross reference it to Pyrebase documentation however i don't seem to get what i'm looking for. Currently i have tried this:
import pyrebase
config={all required information, including path to service account .json file}
firebase=pyrebase.initialize_app(config)
db=firebase.database()
auth=firebase.auth()
extract_user = db.child('users').child('userId').get()
for x in extract_user.each():
print(x.val())
auth.get_account_info(user[x.val()])
However i still failed, i know im missing something but im not sure what.
Note: I saved the users userID in the database under userId. So i looped through each and every ID to be used in the 'get_account_info'
Any suggestions or ways i can get this to be done?
from firebase_admin import credentials
from firebase_admin import auth
cred = credentials.Certificate("./key.json")
initialize_app(cred, {'databaseURL' : "your database..."})
page = auth.list_users()
while page:
for user in page.users:
print("user: ", user.uid)
page = page.get_next_page()
Then, after you get user id that looks like "F5aQ0kAe41eV2beoasfhaksfjh2323alskjal" you can see the actual email by:
user = auth.get_user("F5aQ0kAe41eV2beoasfhaksfjh2323alskjal")
print("user email: ", user.email)
The db.child('users').child('userId').get() in your code reads users from the Realtime Database, where they'll only exist if your application added the there explicitly. Adding a user to Firebase Authentication does not automatically also add it to the Realtime Database.
While Pyrebase allows you to initialize it with a service account, it doesn't replicate all administrative functionality of the Firebase Admin SDKs. As far as I can see in Pyrebase's code, Pyrebase's does not implement a way to list users.
Consider using the Firebase Admin SDK, which has a built-in API to list users.
Related
I'm using Firebase authentication to manage my users accounts.
Now, I need to change the uid of the users, then I'm trying to delete the user and import it again with the same password using python.
I'm trying to follow the documentation. But I might be missing something.
So, in the Firebase authentication page, I'm going to menu (in the right upper corner) and getting the base64_signer_key and base64_salt_separator values.
And trying to use the code below to delete the user, import the user and update the other fields:
for user in auth.list_users().iterate_all():
if user.email == 'myname#yahoo.com':
newId = CPF(cpf()).rawValue
oldId = user.uid
print('User: {}'.format(user._data))
# Delete the user
auth.delete_user(oldId)
# Recreate the user
users = [
auth.ImportUserRecord(
uid=newId,
email=user.email,
password_hash=user.password_hash.encode('utf-8'),
password_salt=None
),
]
hash_alg = auth.UserImportHash.scrypt(
key=base64.b64decode(base64_signer_key),
salt_separator=base64.b64decode(base64_salt_separator),
rounds=8,
memory_cost=14
)
try:
result = auth.import_users(users, hash_alg=hash_alg)
print('Successfully imported {0} users. Failed to import {1} users.'.format(
result.success_count, result.failure_count))
for err in result.errors:
print('Failed to import {0} due to {1}'.format(users[err.index].uid, err.reason))
except Exception as e:
print(e)
# Update user
auth.update_user(
newId,
phone_number=user.phone_number,
email_verified=user.email_verified,
display_name=user.display_name,
disabled=user.disabled
)
I'm following this documentation https://firebase.google.com/docs/auth/admin/import-users#import_users_with_firebase_scrypt_hashed_passwords
I'm able to delete and recreate the user, but when I try to login with the same user/password I'm getting FirebaseInvalidPasswordError.
What should I do recreate the user with same password and be able to authenticate in the standard way ?
After many tests, maybe I've managed to find a working way to solve the problem.
First of all, if you have created a new service account private key, go to GCP console here https://console.cloud.google.com/iam-admin/iam?authuser=0&project=[your_firebase-proect-id] and make sure your service account have the "Firebase Authentication" admin rights
(note the service account)
(check permission)
This was my first problem since without that permission, the firebase admin SDK always returns an empty password_salt and the string "UkVEQUNURUQ=" for the password_hash (which translates to "REDACTED").
Once I got the correct password hash and salt for user, your code should looks like this
# Recreate the user
users = [
auth.ImportUserRecord(
uid=newId,
email=user.email,
password_hash=base64.urlsafe_b64decode(user.password_hash),
password_salt=base64.urlsafe_b64decode(user.password_salt)
),
]
Note the base64.urlsafe_b64decode part? I've tried to manually export my probject users with the firebase cli though
firebase auth:export --project [project-id] users.csv
and noticed a big difference: Python password hash was
utfZLdz4phgAnRIKRUOxxFTKmbUEenbV1CbkQC0o4iorXpx-BJsdwofjAQkb1mUAgs_sO49cBv_lT8QuCztRzA== while CSV password hash was utfZLdz4phgAnRIKRUOxxFTKmbUEenbV1CbkQC0o4iorXpx+BJsdwofjAQkb1mUAgs/sO49cBv/lT8QuCztRzA== (in python slashes are undercores)
Don't know if my approach would cover all cases, but exporting auth from the cli and comparing their hashes with the python ones could lead you to solve further cases.
When writing an Azure Function in Python, I would expect to be able to access the host and function keys from the environment. Is this possible? All the examples I've seen do it by calling a get request, which seems like a lot of code to access something that I've set through the website.
This question is very similar, but not language specific.
It sounds like you want to get the response of the Host API admin/host/keys of Azure Functions as below, so please refer to Azure Functions wiki page Key management API
Here is my sample code.
# App Credentials, to get it see the figures below
username = "<your username like `$xxxxx`>"
password = "<your password>"
functionapp_name = "<your function app name>"
api_url = f"https://{functionapp_name}.scm.azurewebsites.net/api"
site_url = f"https://{functionapp_name}.azurewebsites.net"
import base64
import requests
auth_info = f"{username}:{password}"
base64_auth = base64.b64encode(str.encode(auth_info)).decode()
print(base64_auth)
jwt_resp = requests.get(f"{api_url}/functions/admin/token", headers={"Authorization": f"Basic {base64_auth}"})
jwt = jwt_resp.text.replace("\"", "", -1)
print(jwt)
keys_resp = requests.get(f"{site_url}/admin/host/keys", headers={"Authorization": f"Bearer {jwt}"})
print(keys_resp.text)
It works and its result as below.
For getting the username and password of App Credentials, please see the figures below.
Fig 1. On Azure portal, open the Platform features tab of your Function App and click the Deployment Center link
Fig 2. Select the FTP option in the first step of SOURCE CONTROL and click the Dashboard button to copy the values of Username and Password, but just use the part of Username with $ prefix as username variable in my script. Ofcouse, you also can use them in tab User Credentials tab.
Also, you can refer to my answer for the similar SO thread Unable to access admin URL of Azure Functions using PowerShell, and my figures below come from that.
Update: For using Azure Function for Python in container, please refer to the figure below to get the deployment credentials.
I am building a Web App with Python and I would like to authenticate users.
The pyrebase package seems to be outdated and it generates dependency errors so I cannot use it.
I know that there is a function from the firebase-admin API that works like this:
from firebase import auth
email = example#example.com
user = auth.get_user_by_email(email)
But what if this user has a password? I would like to check if the both the email and the password are provided correctly. Thanks in advance.
The Firebase Admin SDK does not have the concept of a current user, so there's no API to "sign in" a user based on their credentials.
Since you're building a web app, the usual flow is to use the Firebase JavaScript SDK in your client-side code to sign the user in. If needed you can then send the ID token from the client to your Python code on the server, and perform user-based operations there.
Firebase Admin SDK doesn’t provide an API to validate and/or authenticate a user by their password.
However, Firebase provides the Firebase Auth REST API for this purpose. To use the REST API, you need to obtain your Web API Key from the Firebase console.
To Locate the Web API Key
Navigate to Project Settings from Firebase console, then find Web API Key on the General tab. The Web Api key is auto generated whenever you add app to your firebase project. You can also go to an app settings to find apiKey from firebaseConfig
Implement Authentication
Suppose you want to implement user sign in
def sign_in_with_email_and_password(email, password, return_secure_token=True):
payload = json.dumps({"email":email, "password":password, "return_secure_token":return_secure_token})
FIREBASE_WEB_API_KEY = 'the web API key here'
rest_api_url = "https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword"
r = requests.post(rest_api_url,
params={"key": FIREBASE_WEB_API_KEY},
data=payload)
return r.json()
References
https://betterprogramming.pub/user-management-with-firebase-and-python-749a7a87b2b6
https://firebase.google.com/docs/projects/api-keys
https://firebase.google.com/docs/reference/rest/auth
I am using DF with Python API and here is the code and I can't use the detect intent text.
If I use the second line I get the next error:
google.api_core.exceptions.PermissionDenied: 403 IAM permission 'dialogflow.sessions.detectIntent' on 'projects/newagent/agent' denied.
If I use the first one:
google.api_core.exceptions.InvalidArgument: 400 Resource name 'projects/newagent/agent/environments/draft/users//agent/sessions/5276b6d4-a0b6-4e91-84d3-16512d1f3299' does not match 'projects//agent/environments//users//sessions/'.
I have enabled billing on Google Cloud and the user has Owner privileges. What is going wrong?
def detect_intent_texts(project_id, session_id, texts, language_code):
session_client = dialogflow_v2.SessionsClient()
#----------------------------------------------------------Lines that I talk about in the question---------------------------------------------------------------------------------------------------
#session = session_client.session_path(project_id, session_id)
session = "projects/newagent/agent/environments/draft/users/<user id>/sessions/6344a857-9de5-406c-ba0f-c71b7b3ffdba"
#----------------------------------------------------------Lines that I talk about in the question---------------------------------------------------------------------------------------------------
for text in texts:
text_input = dialogflow_v2.types.TextInput(text=text, language_code=language_code)
query_input = dialogflow_v2.types.QueryInput(text=text_input)
response = session_client.detect_intent(session=session, query_input=query_input)
detect_intent_texts("newagent/agent/environments/draft/users/<User Number>",str(uuid.uuid4()),"Que tal?","es-ES")
The Session ID should have the format projects/<Project ID>/agent/sessions/<Session ID> (being <Project ID> the ID of the GCP project where your agent is located and <Session ID> the ID you use for your ongoing session), as can be seen in this documentation page.
In your code I see that you are calling the detect_intent_texts() function like:
project_id = "newagent/agent/environments/draft/users/<User Number>"
session_id = str(uuid.uuid4())
texts = "Que tal?"
language_code = "es-ES"
I see two main errors here:
The Project ID has the wrong format, it should be the ID of your GCP project, which usually has a format like my-first-project or similar, and slashes / are not supported, so you are using a wrong Project ID.
The text should be a Python list of strings, like ["hello"] and not just "hello".
Just as an example, the following minimal code provides the result below:
import dialogflow
def detect_intent_texts(project_id, session_id, texts, language_code):
session_client = dialogflow.SessionsClient()
session = session_client.session_path(project_id, session_id)
print('Session path: {}\n'.format(session))
for text in texts:
text_input = dialogflow.types.TextInput(text=text, language_code=language_code)
query_input = dialogflow.types.QueryInput(text=text_input)
response = session_client.detect_intent(session=session, query_input=query_input)
print('Fulfillment text: {}\n'.format(response.query_result.fulfillment_text))
detect_intent_texts("my-project","abcd",["hello"],"en-US")
Result:
user#my-project:~/dialogflow$ python detect_intent_minimal.py
Session path: projects/my-project/agent/sessions/abcd
Fulfillment text: Hi!
Therefore I suspect that changing the project_id to its correct value and the texts to a list should solve your issues.
EDIT:
I have been able to reproduce the issue that you are seeing with a 403 PermissionDenied message by using a Service Account without the required permissions.
In order to run intents in Dialogflow, you need to use a Service Account with one of the following roles:
Dialogflow API Admin and Dialogflow API Client can query for intents, and therefore, one of those is required in order to make the type of requests you are trying to do with your script.
I see you said that your user has owner privileges over the project. However, the issue may be that you are using a wrong service account. In order to set up authentication correctly, follow the steps detailed in the docs. In summary, you will have to create a Service Account with the right permissions, download its JSON key, and use it as an environment variable by running the command export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/key.json" wherever you are running the script.
When an identity calls a Google Cloud Platform API, Google Cloud Identity and Access Management(IAM) requires that the identity has the appropriate permissions to use the resource for which you have to create custom roles and then assign to service account. Then you will use that service account to call Google Cloud Platform API. Here you can search Dialogflow and see that DF is supported with custom roles only. That is why you have google.api_core.exceptions.PermissionDenied: 403 IAM permission 'dialogflow.sessions.detectIntent'. Do following steps:
Go to you project in Google Cloud Platform and then select roles as shown here:
Then click on Create Role, insert role name and related fields. Then click on Add Permissions and in the filter, search 'Service: Dialogflow'. Select the permissions you want and then click on create.
Then select this:
Click on Create Service Account and on Select Role option, type and search for the role you created on step 2 and save the account.
Do this: . A list of service account will show. Click on 'Create credentials' button.
Select the service account created in above steps and choose JSON. Then select Create. A JSON file be downloaded.
Add that file in your code as: os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'yourfilename.json'
Create an agent in Dialogflow console with google project for which you did all of the above steps. Enjoy :D
I have been able to login to Google spreadsheet with gdata python client.programmaticlogin function following the sample/spreadsheet in gdata downloaded pack.
Now I am not able to login to my enterprise gapps 'me#mycompany.com' do I have to pass any other arms? I tried with account type Hosted didn't work.
I tried creating oath2 key from gui, I have my client id and email id generated. Running the oauth sample in gdata asks for consumerkey and secret key. Can somebody advise on this please?
ok I got it solved with the below
import gdata.gauth
Client_id='xxx';
Client_secret='yyy'
Scope='https://spreadsheets.google.com/feeds/'
User_agent='myself'
token = gdata.gauth.OAuth2Token(client_id=Client_id,client_secret=Client_secret,scope=Scope,user_agent=User_agent)
print token.generate_authorize_url(redirect_uri='urn:ietf:wg:oauth:2.0:oob')
code = raw_input('What is the verification code? ').strip()
token.get_access_token(code)
print "Refresh token\n"
print token.refresh_token
print "Access Token\n"
print token.access_token
Take a look here for an example of how to use client login. Its part of a library I created in order to make working with Google Spreadsheet simple.