Goal
Register and login with username and password via custom token functionality in Firebase (instead of using email and password). Please note that I am new to javascript and making APIs in python.
My attempt
Code is provided below. I run a flask server with python main.py
that provides a custom token. Then app.js
should receive the token and signInWithCustomToken
. But the console in index.html
shows POST http://localhost:5000/get_custom_token 401 (UNAUTHORIZED)
. What am I missing/doing incorrectly?
Example code
Python backend
import hashlib
from flask import Flask, request, jsonify
from flask_cors import CORS
import firebase_admin
from firebase_admin import credentials, auth
app = Flask(__name__)
CORS(app) # Enable CORS for all routes
def initialize_firebase_admin():
# Path to your service account key file
cred = credentials.Certificate('myJSONfile.json')
firebase_admin.initialize_app(cred)
initialize_firebase_admin()
# Mock database
user_db = {}
# Functions
def hash_password(password):
return hashlib.sha256(password.encode()).hexdigest()
def register_user(username, password):
if username in user_db:
raise ValueError("Username already exists")
hashed_password = hash_password(password)
user_db[username] = hashed_password
print(f"User {username} registered successfully")
def authenticate_user(username, password):
hashed_password = hash_password(password)
stored_password = user_db.get(username)
if stored_password and stored_password == hashed_password:
return True
return False
def generate_custom_token(uid):
custom_token = auth.create_custom_token(uid)
return custom_token
# App
@app.route('/get_custom_token', methods=['POST'])
def get_custom_token():
data = request.json
username = data.get('username')
password = data.get('password')
print(f"Received login attempt for user: {username}")
if authenticate_user(username, password):
uid = username # Use username as uid
token = generate_custom_token(uid)
print(f"Generated custom token for user: {username}")
return jsonify({'token': token})
else:
print("Authentication failed for user: ", username)
return jsonify({'error': 'Authentication failed'}), 401
@app.route('/register', methods=['POST'])
def register():
data = request.json
username = data.get('username')
password = data.get('password')
try:
register_user(username, password)
print(f"User {username} registered successfully")
return jsonify({'message': 'User registered successfully'})
except ValueError as e:
print(e)
return jsonify({'error': str(e)}), 400
if __name__ == "__main__":
app.run(debug=True)
app.js
// Web app's Firebase configuration
const firebaseConfig = {
apiKey: "",
authDomain: "",
databaseURL: "",
projectId: "",
storageBucket: "",
messagingSenderId: "",
appId: "",
measurementId: ""
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
async function getCustomToken(username, password) {
const response = await fetch('http://localhost:5000/get_custom_token', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ username, password })
});
if (response.ok) {
const data = await response.json();
return data.token;
} else {
const error = await response.json();
throw new Error(error.error);
}
}
async function signInWithCustomToken(customToken) {
try {
const userCredential = await firebase.auth().signInWithCustomToken(customToken);
console.log("User signed in: ", userCredential.user);
// You can now use the authenticated user information
} catch (error) {
console.error("Error signing in: ", error.code, error.message);
}
}
async function authenticate(username, password) {
try {
const customToken = await getCustomToken(username, password);
await signInWithCustomToken(customToken);
} catch (error) {
console.error("Authentication failed: ", error.message);
}
}
// Example usage
const username = "user1";
const password = "password123";
authenticate(username, password);
index.html
<!DOCTYPE html>
<html>
<head>
<title>Firebase Authentication</title>
<script src="https://www.gstatic.com/firebasejs/9.0.0/firebase-app-compat.js"></script>
<script src="https://www.gstatic.com/firebasejs/9.0.0/firebase-auth-compat.js"></script>
</head>
<body>
<h1>Firebase Custom Authentication</h1>
<script src="app.js"></script>
</body>
</html>