I can not quite understand how do users with different rights, here are the rules:
{"rules":
{"authentication":
{"users":
{"$uid": {
".read": "auth.uid == $uid || root.child('authentication').child('users').child('auth.uid').child('isAdmin').val() == true",
".write": "newData.parent().parent().parent().child('authentication').child('users').child('auth.uid').child('isAdmin').val() == true",
".indexOn": [
"email"
]
}
}
}
}
}
user: link screen user
Realtime Database:
{
"users" : {
"-KVVe4Ncd5Qnm5r37zVp" : {
"email" : "admin#gmail.com",
"isAdmin" : true,
"name" : "admin"
},
"-KVVeADyh07mBXBFImtq" : {
"email" : "djvang92#gmail.com",
"isAdmin" : true,
"name" : "Ivan"
}
}
}
Firebase script:
// Initialize Firebase
const config = {
apiKey: "AIzaSyAfeEpMopsPWnowiv1uEWYINgk6V_ohvG4",
authDomain: "spalah-1358.firebaseapp.com",
databaseURL: "https://spalah-1358.firebaseio.com",
storageBucket: "spalah-1358.appspot.com",
messagingSenderId: "300000265085"
}
firebase.initializeApp(config)
export const db = firebase.database();
export const auth = firebase.auth()
console.log(auth);
// var provider = new firebase.auth.GoogleAuthProvider();
// var provider = new firebase.auth.FacebookAuthProvider();
// var provider = new firebase.auth.TwitterAuthProvider();
// var provider = new firebase.auth.GithubAuthProvider();
export default {
// User object will let us check authentication status
user: {
authenticated: false,
data: null,
message: ''
},
login(context, creds, redirect) {
console.log('Login...');
let self = this;
let email = creds.email;
let password = creds.password;
let promise = auth.signInWithEmailAndPassword(email, password);
console.log(email, password);
// Redirect to a specified route
if(redirect) {
// context.$router.go(redirect)
// console.log(context.$router);
}
promise
.then(user => {
self.user.authenticated = true
self.user.message = false
})
.catch(e => {
self.user.message = e.message
console.log(e);
})
},
signup(context, creds, redirect) {
console.log('Sign Up...');
let email = creds.email
let password = creds.password
let promise = auth.createUserWithEmailAndPassword(email, password);
promise
.then(user => {
console.log(user);
self.user.message = false
})
.catch(e => {
self.user.message = e.message
console.log(e);
})
},
logout() {
let self = this
auth.signOut().then(function() {
// Sign-out successful.
console.log('Log-out successful');
self.user.authenticated = false
}, function(error) {
// An error happened.
console.log('Log-out error');
});
},
provider(context, creds, redirect) {
let provider = new firebase.auth.GoogleAuthProvider()
auth.signInWithPopup(provider).then(function(result) {
// Accounts successfully linked.
var credential = result.credential;
var user = result.user;
// ...
console.log(credential);
console.log(user.photoURL);
}).catch(function(error) {
// Handle Errors here.
// ...
console.log(error);
});
},
checkAuth() {
let self = this
auth.onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
console.log('Connect:', user);
self.user.authenticated = true
self.user.data = user
} else {
// No user is signed in.
console.log('No connect:');
self.user.authenticated = false
self.user.data = null
}
});
}
}
I can not understand how to test it in Javascript...
(I make application to vue.js)
Thank you!
I'm a bit late to the party here but may as well answer this for anyone looking.
The current method for assigning roles to users with Firebase is to use custom claims. To do this you mint your own JWTs and add in the custom claims at this point. You can use Firebase Functions to do this or you could do this on your own server.
You can see the documentation here.
Related
Wanting to display error messages when a person has trouble going through the authentication process (wrong password etc). I have a pinia store which has the actions for login etc below.
async loginUser(email, password) {
this.loadingUser = true;
try {
const { user } = await signInWithEmailAndPassword(
auth,
email,
password
);
this.userData = { email: user.email, uid: user.uid };
router.push("/");
} catch (error) {
console.log(error);
this.userData = {};
} finally {
this.loadingUser = false;
}
},
and my login script form component code below.
const email = ref("");
const password = ref("");
const handleSubmit = () => {
if (!email.value || password.value.length < 8) {
alert("Enter");
}
userStore.loginUser(email.value, password.value);
};
how can i display any authentication error on the page to the user? Much appreciated.
I'm trying to make a basic login/signup system with firebase. So far I've been able to fix all the other bugs. The program first creates a user with Firebase Authentication then puts the user data in the Firebase Database. I've managed to get the Authentication working but the database part just makes firebase spit out, "firebase is not defined".
Here's the code:
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.13.0/firebase-app.js";
import { getAuth, createUserWithEmailAndPassword } from "https://www.gstatic.com/firebasejs/9.13.0/firebase-auth.js";
import { getDatabase } from "https://www.gstatic.com/firebasejs/9.13.0/firebase-database.js";
const firebaseConfig = {
apiKey: "AIzaSyCQjuF9A4Km_M7Eo5gnd1B6nmDRRYSle2c",
authDomain: "badge-world.firebaseapp.com",
projectId: "badge-world",
storageBucket: "badge-world.appspot.com",
messagingSenderId: "186421361260",
appId: "1:186421361260:web:852bcaa237f86a76b1f649"
};
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const database = getDatabase(app);
document.getElementById ("signup-button").addEventListener("click", register);
document.getElementById ("login-button").addEventListener("click", login);
function register() {
let email = document.getElementById('email').value
let password = document.getElementById('password').value
let username = document.getElementById('username').value
if (validate_email(email) == false || validate_password(password) == false) {
alert("Incorrect Fields. Remember password has to have more than 6 characters and there must be a valid email.")
}
if(validate_field(username) == false) {
alert("Username missing")
}
createUserWithEmailAndPassword(auth, email, password)
.then(function (){
var user = auth.currentUser
var rootRef = firebase.database().ref();
var user_data = {
email : email,
password : password,
username: username,
last_login : Date.now
}
rootRef.child('users/' + user.uid).set(user_data)
alert("User Created!")
})
.catch(function(error) {
var error_code = error.code
var error_message = error.message
alert(error_message)
})
}
function login() {
}
// Validate Functions
function validate_email(email) {
let expression = /^[^#]+#\w+(\.\w+)+\w$/
if (expression.test(email) == true) {
// Email is good
return true
} else {
// Email is not good
return false
}
}
function validate_password(password) {
// Firebase only accepts lengths greater than 6
if (password < 6) {
return false
} else {
return true
}
}
function validate_field(field) {
if (field == null) {
return false
}
if (field.length <= 0) {
return false
} else {
return true
}
}
and here's the database part that seems to be causing the issue:
.then(function (){
var user = auth.currentUser
var rootRef = firebase.database().ref();
var user_data = {
email : email,
password : password,
username: username,
last_login : Date.now
}
rootRef.child('users/' + user.uid).set(user_data)
alert("User Created!")
})
.catch(function(error) {
var error_code = error.code
var error_message = error.message
alert(error_message)
})
Any help is appreciated!
You are using Firebase Modular SDK that uses a functional syntax and not the firebase. namespaced one. The problem is this line:
var rootRef = firebase.database().ref();
There is a top level function ref() to get a DatabaseReference now. Try refactoring the code as shown below:
import { getDatabase, ref, set } from "https://www.gstatic.com/firebasejs/9.13.0/firebase-database.js";
// declared while initializing
const database = getDatabase(app)
set(ref(database, 'users/' + user.uid), user_data)
.then(() => {
console.log("data added")
})
.catch((e) => console.log(e))
The documentation has examples of both the syntaxes so make sure you are referring to modular tab.
I want to avoid using the loginPopup or loginRedirect and get authenticated directly. I am using the below code. I am try to achieve SSO by hosting my chatbot on sharepoint website. As i have already login to my sharepoint website I need to avoid login again.
Current functionality, When i click on the chatbot icon i am getting a pop-up window on the current site. i.e. sharepoint and i am login again, I need to avoid this.
For complete code click here
function onSignInClick() {
alert("Inside onSignInClick function");
let requestObj = {
scopes: ["user.read", 'openid', 'profile']
};
debugger;
clientApplication.loginPopup(requestObj)
.then(onSignin)
.catch(function (error) { console.log(error) });
}
function onSignin(idToken) {
let user = clientApplication.getAccount();
document.getElementById("userName").innerHTML = "Currently logged in as " + user.name;
let requestObj1 = {
scopes: ["user.read", 'openid', 'profile']
};
}
var clientApplication;
(function () {
var msalConfig = {
auth: {
clientId: '<client id>',
authority: 'https://login.microsoftonline.com/<directory id>'
},
cache: {
cacheLocation: 'localStorage',
storeAuthStateInCookie: false
}
};
if (!clientApplication) {
clientApplication = new Msal.UserAgentApplication(msalConfig);
//alert("Inside if clientApplication: " + JSON.parse(clientApplication));
}
}());
(async function main() {
// Add your BOT ID below
var BOT_ID = "<Bot-Id>";
var theURL = "https://powerva.microsoft.com/api/botmanagement/v1/directline/directlinetoken?botId=" + BOT_ID;
//alert("before userId async function: " + JSON.parse(clientApplication));
var userId = clientApplication.account?.accountIdentifier != null
? ("You-customized-prefix" + clientApplication.account.accountIdentifier).substr(0, 64)
: (Math.random().toString() + Date.now().toString()).substr(0, 64)
;
//debugger;
alert("after userId async function: " + JSON.parse(userId));
const { token } = await fetchJSON(theURL);
const directLine = window.WebChat.createDirectLine({ token });
const store = WebChat.createStore({}, ({ dispatch }) => next => action => {
const { type } = action;
if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'startConversation',
type: 'event',
value: { text: "hello" }
}
});
return next(action);
}
if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
const activity = action.payload.activity;
let resourceUri;
if (activity.from && activity.from.role === 'bot' && (resourceUri = getOAuthCardResourceUri(activity))) {
exchangeTokenAsync(resourceUri)
.then(function (token) {
if (token) {
directLine.postActivity({
type: 'invoke',
name: 'signin/tokenExchange',
value: {
id: activity.attachments[0].content.tokenExchangeResource.id,
connectionName: activity.attachments[0].content.connectionName,
token
},
"from": {
id: userId,
name: clientApplication.account.name,
role: "user"
}
}).subscribe(
id => {
if (id === 'retry') {
// bot was not able to handle the invoke, so display the oauthCard
return next(action);
}
// else: tokenexchange successful and we do not display the oauthCard
},
error => {
// an error occurred to display the oauthCard
return next(action);
}
);
return;
}
else
return next(action);
});
}
else
return next(action);
}
else
return next(action);
});
window.WebChat.renderWebChat(
{
directLine: directLine,
store,
userID: userId,
styleOptions
},
document.getElementById('webchat')
);
})()
.catch(err => console.error("An error occurred: " + err));
By your scenario to eliminate loginPopup or loginRedirect in autentication,I understood that you don't require user involvement to login. The possible solution for your scenario is to use Client credential flow.
Client Credential Flow does not require user login and can silently Sign-in with application permissions.
Please refer this code sample which can help.
I am Creating an expo app in which a user can login using Gmail.
I followed this firebase documentation to implement that functionality but whenever I click on login, it doesn't neither save the data in the database nor return any error.
This is my firebase function:
isUserEqual = (googleUser, firebaseUser)=> {
if (firebaseUser) {
var providerData = firebaseUser.providerData;
for (var i = 0; i < providerData.length; i++) {
if (providerData[i].providerId === firebase.auth.GoogleAuthProvider.PROVIDER_ID &&
providerData[i].uid === googleUser.getBasicProfile().getId()) {
// We don't need to reauth the Firebase connection.
return true;
}
}
}
return false;
}
onSignIn = (googleUser)=> {
console.log('Google Auth Response', googleUser);
// We need to register an Observer on Firebase Auth to make sure auth is initialized.
var unsubscribe = firebase
.auth()
.onAuthStateChanged(function(firebaseUser) {
unsubscribe();
// Check if we are already signed-in Firebase with the correct user.
if (!this.isUserEqual(googleUser, firebaseUser)) {
// Build Firebase credential with the Google ID token.
var credential = firebase.auth.GoogleAuthProvider.credential(
googleUser.idToken,
googleUser.accessToken
);
// Sign in with credential from the Google user.
firebase.auth()
.signInAndRetrieveDataWithCredential(credential)
.then(function(result) {
console.log('User signed in');
})
.catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// The email of the user's account used.
var email = error.email;
// The firebase.auth.AuthCredential type that was used.
var credential = error.credential;
// ...
});
} else {
console.log('User already signed-in Firebase.');
}
}.bind(this)
);
};
signInWithGoogleAsync = async() => {
try {
const result = await Expo.Google.logInAsync({
behavior: 'web',
androidClientId: '929952027781-5ao9pp7n5n0sj2n70i5tp7klfro88bgp.apps.googleusercontent.com',
iosClientId: '929952027781-7obs66o3kr59kdhp6ll0c9598ue3u8aa.apps.googleusercontent.com',
scopes: ['profile', 'email'],
});
if (result.type === 'success') {
this.onSignIn(result);
return result.accessToken;
} else {
return {cancelled: true};
}
} catch(e) {
return {error: true};
}
}
And this is my login button:
<TouchableOpacity style={styles.AuthOptionGmail} onPress={() => signInWithGoogleAsync()}>
<Ionicons color='#ffffff' style = {styles.BtnIcon} name="logo-google" size={25}/>
<Text style={{fontSize:16,color:'#ffffff', textAlign:'center'}}>Login with Gmail</Text>
</TouchableOpacity>
Can anyone tell me where I messed up please????
with Expo sdk 32 and above following worked for me , just install "expo-google-app-auth"
import * as Google from "expo-google-app-auth";
signInWithGoogleAsync = async () => {
console.log("signInWithGoogleAsync");
try {
//clientId
const { type, accessToken, user, idToken } = await Google.logInAsync({
behavior: "web",
androidClientId:
"your id",
iosClientId:
"your id",
scopes: ["profile", "email"]
});
if (type === "success") {
console.log("accessToken" + accessToken);
console.log("idToken" + idToken);
console.log(user);
return accessToken;
} else {
return { cancelled: true };
}
} catch (e) {
console.log(e);
return { error: true };
}
};
I'm running this code in my react app:
componentDidMount() {
modelInstance.addObserver(this);
modelInstance.getSignInStatus().then((user)=>{
this.setState({
userName: user !== false ? user.displayName : "Sign in",
logged_in: user !== false ? true : false
});
});
}
And here is modelInstance.getSignInStatus():
this.getSignInStatus = function () {
return new Promise((resolve, reject)=>{
firebase.auth().onAuthStateChanged(function(user){
if (user){
resolve(user);
}
else {
resolve(false);
}
});
});
}
What happens is that this.state.userName is set to null, meaning that user.displayName is null. Why is this?
state = {
username: "",
email: "",
passwordOne: "",
passwordTwo: "",
error: null
};
onSubmit = event => {
const {username, email, passwordOne} = this.state;
const {history} = this.props;
auth
.createUserWithEmailAndPassword(email, password);
.then(authUser => {
db.doCreateUser(authUser.uid, username, email).then(() => {
//you should clear your state fields here, for username / email etc
console.log(authUser);
//redirect user
history.push(routes.HOME);
});
})
.catch(error => {
this.setState({error});
});
event.preventDefault();
};
const auth = firebase.auth();
const db = firebase.database();
in order to acess doCreateUser
const doCreateUser = (id, username, email) =>
db.ref(`users/${id}`).set({
uid:id,
username,
email,
});
I would use setState for checking the auth status like so:
firebase.auth().onAuthStateChanged(function(user){
if (user){
this.setState({user});
}
}
Then you want the state of the displayName of the current user
componentDidMount() {
modelInstance.addObserver(this);
modelInstance.getSignInStatus().then((user)=>{
this.setState({
userName: this.state.user ? this.state.user.displayName : "Sign in",
logged_in: this.state.user ? true : false
});
});
}
Obviously there has to be a name in the displayName property, If not you would have to update it. Let me know how this turns out.