I want to add multiple users with pre define paswword to Firebase Authentication project
I know it can be done using Hash password but in my case i have the real password not the generated hash password
can i user firebase auth:import to upload using realpassword or are there any way to convert real password to hash password using my project hash parameters ??
for example
You can hash with SHA256 and import these users. Here is an example in Node.js using the Admin SDK:
import * as crypto from 'crypto';
const importOptions = {
hash: {
algorithm: 'SHA256',
rounds: 1,
},
};
// For every user, you generate the password hash and a salt.
const currentRawSalt = generateRandomSalt();
const computedPasswordHash = crypto.createHash('sha256').update(currentRawSalt + yourUserPlainPassword).digest();
importUserRecord = {
uid: yourUserUid,
email: youUserEmail,
passwordSalt: Buffer.from(currentRawSalt),
passwordHash: computedPasswordHash,
};
admin.auth().importUsers([importUserRecord], importOptions)
.then((result) => {
// Check result to confirm success.
});
There's no way to import with a plain text password. You will have to generate the password hash to import them. There are a lot of hashing options, all described in the documentation on importing users with the Admin SDK.
I did the below work around
I stored all users data in excel sheet
Then I loop in sheet data and called sign up method for each row
Related
I want to force a user to reenter its password on a security sensitive step in my app.
I want to use reauthenticateWithCredential but no documentation seems to fit my case using #nativescript/firebase-auth since EmailAuthProvider is always undefined.
This is a similar issue for react.
TypeError: Cannot read property 'credential' of undefined - React-redux-firebase, Firebase Auth
I found the proper sequence to retrieve the user and inject the credential object.
There was also a little catch where reauthenticateWithCredential is coming directly from the user.
import '#nativescript/firebase-auth';
import { EmailAuthProvider } from '#nativescript/firebase-auth';
const user = firebase().auth().currentUser;
const credential = EmailAuthProvider.credential(user.email, password);
try {
await user.reauthenticateWithCredential(credential);
//Good password
}catch(e){
//Wrong password
}
Hope it may be of help to anyone.
How can I generate a link to undo the email change in firebase cloud functions?
So when a user changes their email address, I want to generate a link to include in an automated email for them to click to undo this email change. Firebase sends an email when an email changes, but I want to be able to do that myself with my own code.
Currently, I can find that there are ways you can generate a link to change the user password, verify email, etc. However, I cannot find a method that I can use to generate a link to undo email change when the user changes their email.
When a user changes the email, you can store a document in Firestore containing their old email, a token and some metadata if you need to. That being said, you should update user's email from a Cloud function or your server using the Admin SDK only as there are no triggers on E-Mail change.
import jwt from "jsonwebtoken"
import {v4} from "uuid"
exports.changeEmail = functions.https.onCall(async (data, context) => {
const {newEmail} = data;
const {uid} = context.auth;
// change user's email
// send an email to verify new email is required
// generate a JWT
const token = jwt.sign({ uid, eventId: v4() }, 'jwt_signing_secret', { expiresIn: '24h' });
// add a document in Firestore containing details about this event
await admin.firestore().collection("emailChanges").doc(eventId).set({
uid, changedAt: Date.now()
})
const undoURL = `https://[YOUR_DOMAIN]/revert-email-change?token=${token}`
// E-Mail this URL to user
// Terminate this function
})
Replace [YOUR_DOMAIN] will the URL of your website. Once the user visits /revert-change-email email page of your website, call another function that verifies this token.
exports.revertEmailChange = functions.https.onCall((data, context) => {
// pass the token from frontend by checking URL params
const {token} = data
// Verify the token
const decoded = jwt.verify(token, 'jwt_signing_secret');
console.log(decoded)
const {uid, eventId} = decoded
// token is valid
// read the Firestore document using stateId and check old email
const snap = await admin.firestore().collection("emailChanges").doc(eventId).get()
if (!snap.exists) return {error: "Invalid Token"}
const {email} = snap.data()
// use updateUser() method to change email back
// delete that document from Firestore
return {data: "Email changed back successfully"}
});
You can change the lifespan of JWT token i.e. how long the URL should be valid. You can read more about JWT at jwt.io. The additional eventId token is just to prevent that JWT token so it cannot be reused.
When writing Cloud Functions for Firebase, one uses the Admin Node.js SDK.
AFAIK it is not possible, with this Admin SDK, to generate an email action link to undo an email change, as we can we can do, for example, for email verification with the generateEmailVerificationLink() method.
You will need to build your own mechanism yourself. You'll probably have to save somewhere (e.g. in Firestore) the previous email and expose an HTTP endpoint to trigger the action (HTTPS Cloud Function? Call to the Firestore REST API?). In any case you'll have to check the identity of the calling user (by either checking the Firebase ID token as a Bearer token in the Authorization header of the HTTP request or via a dedicated Firestore Security Rule).
There isn't enough details in your question to understand the exact flow of your complete use case (i.e. from the request to change email up to the action of undoing an effective change) and propose a sensible approach.
I’m working on a react native application that uses [Firebase Email Link (passwordless) Auth]((https://firebase.google.com/docs/auth/web/email-link-auth)
I have created a ‘users’ collection on the Firestore database.
In order to easily sync users profile data to the redux store,I decided to use react-redux-firebase
I have already configured the rrfConfig and followed every single steps as stated in the getting started documentation, but still remain some parts that unclear and not documented. It’ll be great to get someone’s help on any ideas on how to tackle this part:
1) How to log in users with firebase.login({params}) that are signed up with email link (passwordless) using the methods outlined in the auth section?
This the email/password example:
firebase.login({
email: 'test#test.com',
password: 'testest1'
})
Since the user does not have a password, or credential or accessToken after he signed up using email link firebase.auth().signInWithEmailLink(email, window.location.href) all we have is a uid and email:
firebase.login({
email: 'test#test.com',
// any ideas to add here?
})
2) Similarly, how to create users with createUser(credentials, profile) using [email link (passwordless)](https://firebase.google.com/docs/auth/web/email-link-auth
) auth?
const createNewUser = ({ email, password, username }) => {
firebase.createUser( // should password be replaced by url?
{ email, password },
{ username, email }
)
}
Thank you in advance for helping out with any ideas on how to tackle this
I'm following firebase/identity toolkit docs for a SAML identity provider. Upon successful login, the redirect result contains attributes derived from the provider:
provider = new firebase.auth.SAMLAuthProvider('saml.test-provider');
firebase.auth().signInWithRedirect(provider);
...
firebase.auth().getRedirectResult().then(function(result) {
if (result.credential) {
console.log(result.additionalUserInfo.profile) // Custom provider claims, e.g., {"provider-foo":"bar"}
}
}
From the docs, the same values are also available via
result.user.getIdTokenResult().idTokenResult.claims.firebase.sign_in_attributes
firebase.sign_in_attributes
These same attributes don't seem to be stored anywhere accessible in the firebase_admin SDK:
from firebase_admin import auth
user = auth.get_user(uid)
print(user.custom_claims) # => None ... *provider* claims aren't here
print(user.provider_data[0]) # => has `federatedId` and some others, but still no custom provider claims
Is there any way to get this info in the admin SDK? Any way to tell if it's even saved by Firebase? Do I need to capture it in firestore (and wouldn't that be risky since the user could fake claims coming from the provider?)
Thanks!
the additional SAML attributes are only persisted in the token claims accessible via:
result.user.getIdTokenResult().idTokenResult.claims.firebase.sign_in_attributes
They are not stored on the user record. Identity Platform/Firebase Auth does not persist additional user info in storage for privacy reasons.
However, you can always store the claims you need on the record via the Admin SDK.
You would send the ID token to your server, verify it, parse the claims you need and set them on the user record.
Here is sample via the Node.js Admin SDK.
app.post('/saveUserClaims', (req, res) => {
// Get the ID token passed.
const idToken = req.body.idToken;
admin.auth().verifyIdToken(idToken)
.then(function(decodedToken) {
const uid = decodedToken.uid;
// ...
const samlClaims = decodedToken.firebase.sign_in_attributes;
// You would filter the claims as there could be too many.
// You can also save these claims in your database, etc.
return admin.auth().setCustomUserClaims(uid, samlClaims)
.then(() => {
res.status(200).end();
});
}).catch(function(error) {
// Handle error
});
});
That said, in general there is no need to save these claims as they will always be available in the ID token and you can access them from your security rules or when you pass the ID token to your server for validation. This is a better way to do this as you don't run into synchronization issue where your DB is out of sync with the user's attributes.
In the simple case outlined below, the user will successfully import but I receive an INVALID_PASSWORD when I try to authenticate.
The salt and passwordHash where pulled from an LDAP user directory (apacheds) using the {SSHA} auth schema. When I run the following JS I receive the passwordHash I'm expecting:
var sha1Hex = require('sha1-hex');
var saltHex = Buffer.from("ktuF+dzYMQU=", 'base64').toString('hex');
var passwordHex = Buffer.from("demo", 'utf-8').toString('hex');
var hash = sha1Hex(Buffer.from(passwordHex + saltHex, 'hex'));
var hashBase64 = Buffer.from(hash, 'hex').toString('base64');
console.log(hashBase64);
firebase CLM import command:
firebase auth:import users.json --hash-algo=SHA1 --rounds=80
users.json file:
{
"users": [
{
"localId": "3c872eee-e86c-4b44-9840-bcebaac18f2c",
"email": "test#example.com",
"salt": "ktuF+dzYMQU=",
"passwordHash": "BuapoGGKIdfGprfMFjj3N9I7Ljg=",
"displayName": "Demo User",
}
]
}
Credentials that should work with imported user:
Username: test#example.com
Password: demo
Firebase web api login command (returns INVALID_PASSWORD):
firebase.auth().signInWithEmailAndPassword('test#example.com', demo);
I'm not confident about the --rounds=80 parameter, seems weird that needs to be specified at all when using sha1. I've also tried with --rounds=0.
After trying this out with Java MessageDigest SHA-1 to verify the password hash, one of our uber auth experts said that it looks like you're doing passwordHash = SHA1(plainPassword + salt)
However, the Firebase Auth system uses passwordHash = SHA1(salt + plainPassword).
So I think if you switch that around, it should produce better results.
You can configure the order of the password and hash.
The hash-input-order accept two values: SALT_FIRST or PASSWORD_FIRST.
In your case you want to do:
firebase auth:import users.json --hash-algo=SHA1 --rounds=80 --hash-input-order=PASSWORD_FIRST
For anyone like me that went hours finding a solution for this issue, please refer to this.
Basically, passwordHash should be in Base64 encoding from un-hex-ed SHA1 hash. And --rounds=1 works fine.