Avoiding Wix members confirmation emails or changing the sending address - wix

I am working with a client who runs a BtoB. We have set up Member Accounts and some member roles to secure sensible information to which they would have access once approved. However, we are running with an issue that is driving me completely crazy: as Wix’s default registration process rules, once someone signs up and we approve Member Access, an email is sent to their account with a token to confirm their email.
Even though we have an email integrated with Wix with our domain, both the confirmation emails and password reset (sent after a user clicks on “forgot my password”), are not being sent from that address, but from some stupid #site-members.com address.
sender address
My client’s clients all use business emails, and most of their servers are completely blocking these emails. Therefore, they are not being able to complete the registration process and never get to login.
After trying to talk to Wix’s support - which was a complete waste of time - I started scouting the internet and found a tutorial for sending Triggered Emails as confirmation emails. I tried it and it seems to work, however, even though the Triggered Email is set to be sent from my account, it adds a via something:
via ascendbywix
Aaaand.. Guess what! After doing some testing, these get blocked as well in many servers.
So, I don’t know what else to do! Can somebody please help me to either avoid sending confirmation emails at all, or to see if there is any other way to set the email address sending those using Corvid or the Wix dashboard?
Just in case you want to see the code, there are three parts to it:
REGISTRATION LIGHTBOX
import wixWindow from 'wix-window';
import wixData from 'wix-data';
import { doRegistration } from 'backend/register';
let registration;
$w.onReady(function () {
$w("#register").onClick((event) => {
console.log("Button was clicked");
$w("#errorMessage").collapse();
$w("#emailExists").collapse();
if ($w("#email").valid && $w("#password").valid && $w("#company").valid && $w("#name").valid) {
registerPerson();
console.log("Trying to register");
} else {
$w("#errorMessage").expand();
console.log("Missing Information");
}
})
});
function registerPerson () {
let email = $w("#email").value;
let password = $w("#password").value;
let name = $w("#name").value;
let company = $w("#company").value;
let toInsert = {
"name": name,
"company": company,
"email": email
};
wixData.insert("Members", toInsert)
.then( (results) => {
let item = results;
} )
.catch( (err) => {
let errorMsg = err;
} );
doRegistration(email, password, name)
.then((result) => {
wixWindow.openLightbox("confirmation");
let userId = result.user.id
.catch((err) => {
let errMsg = err;
console.log(err);
$w("#emailExists").expand();
} );
});
}
BACKEND REGISTER.JSW
export function doRegistration(email, password, name, company) {
// register the user
return wixUsers.register(email, password, {
"contactInfo": {
"name": name,
"company": company
}
})
.then((results) => {
wixUsers.emailUser('verifyRegistration', results.user.id, {
variables: {
approvalToken: results.approvalToken
}
});
return results
});
}
export function doApproval(token) {
// approve the user
return wixUsers.approveByToken(token)
// user is now active, but not logged in
// return the session token to log in the user client-side
.then((sessionToken) => {
return { sessionToken, "approved": true };
})
.catch((error) => {
return { "approved": false, "reason": error };
});
}
CONFIRMATION PAGE (where users will be redirected after confirming their email)
import wixLocation from 'wix-location';
import wixUsers from 'wix-users';
import {doApproval} from 'backend/register';
$w.onReady( () => {
// get the token from the URL
let token = wixLocation.query.token;
doApproval(token)
.then( (result) => {
if (result.approved){
// log the user in
wixUsers.applySessionToken(result.sessionToken);
console.log("Approved");
}
else {
console.log("Not approved!");
}
} );
} );

just create the SPF record in the DNS and include everything to it along with the WIX servers (ascendbywix.com ~all).

Related

How to distinguish connected users in WebSocket?

I'm trying to create an event in express.js, where connected users will be sent to the client.
My goal is that in client side user can see who belongs that particular message sent from.
As it describes in docs and as I could also run in localhost, broadcasting messages works fine.
wss.on("connection", function connection(ws) {
ws.on("message", function message(data) {
wss.clients.forEach(function each(client) {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
});
});
So before sending messages to client, there should be another event where connected username should be sent, so that in client side can be defined who that particular message belongs.
My idea is to create users object which supposed to keep track of all connected users like here.
const users = {};
wss.on("connection", function connection(ws) {
ws.on("userName", function message(userName) {//this doesn't work
const user = {
name: userName,
id: uuid(), // some unique id, no idea if websocket has or not
};
users[id]= user
ws.send("user", user) // current user who belongs the message to
ws.send("users", users) // users to show connected users list
});
ws.on("message", function message(data) {
wss.clients.forEach(function each(client) {
if (client !== ws && client.readyState === WebSocket.OPEN) {
client.send(data);
}
});
});
});
user event doesn't work, it is just my idea but not sure if how to do it correctly.
Any help will be appreciated.

How to automatically login users after Email/Password authentication

I'm currently building a blog sample app, using NextJS, ApolloClient and MongoDB + MongoRealm. The NextJS skeleton was built after the framework's official page tutorial.
At the moment, new users can signup, by accessing a SignUp form which is routed at 'pages/signup'. After entering their credentials, they are redirected to the home page. Then, the freshly signed in users have to visit another page(the one associated with 'pages/login' root), which contains the login form, which is responsible with their email/password authentication.
Also, I've set up Realm to send a confirmation email at the user's email address. The email contains a link to a customized page from my NextJs app, which will handle their confirmation(users also have to be confirmed, after requesting a sign in)
The workflow should be established with this. However, I want to automatically login a user, after he/she just logged in(so that they won't need to sign in and also visit the log in page, when creating their accounts).
The problem I'm encountering is that my React component that handles the user confirmation, doesn't have access to the user instance's email and password. I need a way to login the user, without having access to his/her credentials.
Below, I will try to explain exactly why this access restriction happens in the first place. Although the entire '_app.js' is wrapped in some custom providers, I'll try to keep things as simple as possible, so I'll present only what is needed for this topic.
My signup.js file looks something like this:
import { useForm } from "react-hook-form";
// Used 'useForm' hook to simplify data extraction from the //input form
import { useAuth } from "members";
const SignUpForm = () => {
const router = useRouter();
const { handleSubmit, register } = useForm();
const { signup } = useAuth();
const signUpAndRedirect = (form) => {
signup(form.email, form.password);
router.push("/");
// after signing up, redirect client back to home
};
return (
{/*My form's 'email' and 'password' fields are only accessible in the SignUpForm component*/}
<div>
<form onSubmit={handleSubmit(signUpAndRedirect)}>
...
...
</form>
</div>
);
};
export default SignUpForm;
My login.js file is built after the same concept, the only difference being that 'signUpAndRedirect' is replaced with
'authenticateAndRedirect':
const authenticateAndRedirect = (form) => {
login(form.email, form.password);
router.push("/");
};
And here is my confirm.js file, which is responsible with extracting the token and tokenId from the confirmation URL. This component is normally only rendered when the client receives the email and clicks on the confirmation link(which basically has the form /confirm, where each token is a string and is added into the URL by Realm).
import Link from "next/link";
import { useEffect } from "react";
import { useRouter } from "next/router";
import { useAuth } from "members";
const Confirm = () => {
const router = useRouter();
const { confirm, login } = useAuth();
useEffect(() => {
const token = router.query.token;
const tokenId = router.query.tokenId;
if (token && tokenId) {
confirm(token, tokenId);
login(email, password); // !!! I don't have access to these
}
}, [router]);
//used useEffect() to assure the confirmation only happens once, after the component was rendered.
return (
<div>
<h2>
Thank you for confirming your email. Your profile was successfully
activated.
</h2>
<Link href="/">
<a>Go back to home</a>
</Link>
</div>
);
};
export default Confirm;
And finally, just a quick look into the signup, login and confirm methods that I have access to through my customized providers. I am quite positive that they work correctly:
const client = () => {
const { app, credentials } = useRealm();
const [currentUser, setCurrentUser] = useState(app.currentUser || false);
const [isAuthenticated, setIsAuthenticated] = useState(user ? true : false);
// Login and logout using email/password.
const login = async (email, password) => {
try {
const userCredentials = await credentials(email, password);
await app.logIn(userCredentials);
setCurrentUser(app.currentUser);
setIsAuthenticated(true);
} catch (e) {
throw e;
}
};
const logout = async () => {
try {
setUser(null);
// Sign out from Realm and Auth0.
await app.currentUser?.logOut();
// Update the user object.
setCurrentUser(app.currentUser);
setIsAuthenticated(false);
setUser(false);
} catch (e) {
throw e;
}
};
const signup = async (email, password) => {
try {
await app.emailPasswordAuth.registerUser(email, password);
// await app.emailPasswordAuth.resendConfirmation(email);
} catch (e) {
throw e;
}
};
const confirm = async (token, tokenId) => {
try {
await app.emailPasswordAuth.confirmUser(token, tokenId);
} catch (e) {
throw e;
}
};
return {
currentUser,
login,
logout,
signup,
confirm,
};
};
export default client;
The currentUser will basically represent the Realm.app.currentUser and will be provided to the _app by my providers.
So, the problem is that my Confirm component doesn't have access to the email and password fields.
I've tried to use the useContext hook, to pass data between sibling components, but quickly abandoned this approach, because I don't want to pass sensitive data throughout my NextJS pages(The only place where I should use the password is during the MongoDB POST request, since it gets encrypted by Realm Web).
Is there any way I could solve this issue? Maybe an entirely different approach?
Thank you very much in advance! Any help would be very much appreciated!
If you disable the user email confirmation, you could potentially call the login function when the register is finished like that :
registerAndLogin(email, password)
.then(() =>
loginAndRedirect(email, password)
.then(() => router.push('/')
.catch(err => throw err)
)
.catch(err => throw err)
I used your post to resolve an error I had, so thank you by the way.
Hope my answer works, I didn't had the time to test.

Web app that runs in Microsoft Teams (personal tab) doesn't always work on Desktop version

I have a Web app built in Vuejs and has SSO authentification using microsoftTeams.authentication.getAuthToken when running in Teams, or microsoftAuthLib when running in the browser.
Inside the company's network or when connected to the VPN everything works absolutely fine.
We recently opened it outside of the VPN and we created a public certificate for it. So when I disconnect the VPN, it works:
In any browser (outside of Teams).
Teams browser version.
Teams on Android/iPhone.
But it doesn't work on Teams Windows Desktop version, it fails with the following error:
Refused to display
'https://login.microsoftonline.com/.../oauth2/authorize?...' in a
frame because it set 'X-Frame-Options' to 'deny'.
Anybody has an idea what could be the issue? And why would it work on the company's VPN but not outside?And only on specific cases? I am lost, any help would be appreciated.
Thank you
*** EDIT / ADDED SSO REDIRECT CODE ***
import * as microsoftTeams from "#microsoft/teams-js";
import * as microsoftAuthLib from "msal";
import settings from './settings.js';
var msalConfig = {
auth: {
clientId: settings.sso.id,
authority: settings.sso.authority
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: true
}
};
var requestObj = {
scopes: settings.sso.scopes
};
var myMSALObj = new microsoftAuthLib.UserAgentApplication(msalConfig);
myMSALObj.handleRedirectCallback(authRedirectCallBack);
function authRedirectCallBack(error, response) {
if (error) {
console.log(error);
} else {
console.log("token type is:" + response.tokenType);
}
}
function loginRedirect(requestObj) {
let account = myMSALObj.getAccount();
if (!account) {
myMSALObj.loginRedirect(requestObj);
return false;
} else {
return true;
}
}
function acquireMsalToken() {
return new Promise(function (resolve) {
resolve(myMSALObj.acquireTokenSilent(requestObj).then(token => {
return token.accessToken;
}).catch(error => {
acquireMsalTokenRedirect(error);
}));
})
}
function acquireTeamsToken() {
return new Promise((resolve, reject) => {
microsoftTeams.authentication.getAuthToken({
successCallback: (result) => {
resolve(result);
},
failureCallback: (error) => {
reject(error);
}
});
});
}
function acquireMsalTokenRedirect(error) {
if (error.errorCode === "consent_required" ||
error.errorCode === "interaction_required" ||
error.errorCode === "login_required") {
myMSALObj.acquireTokenRedirect(requestObj);
}
}
var msal = {
autoSignIn: function () {
return loginRedirect(requestObj);
},
acquireToken: async function () {
if (settings.sso.inTeams) {
microsoftTeams.initialize();
microsoftTeams.enterFullscreen();
return acquireTeamsToken();
} else {
let signedIn = msal.autoSignIn();
if (signedIn) {
return acquireMsalToken();
}
}
}
}
export default msal
This error means that you are trying to redirect your tab's iframe to the AAD login flow which in turn is unable to silently generate an auth token for you and is attempting to show an interactive flow (e.g. sign in or consent):
Refused to display
'https://login.microsoftonline.com/.../oauth2/authorize?...' in a
frame because it set 'X-Frame-Options' to 'deny'.
To avoid this issue you need to try and acquire a token silently and if that fails use the microsoftTeams.authentication.authenticate API to open a popup window and conduct the AAD login flow there.
Replacing the acquireTeamsToken() function with the following resolved the issue.
function acquireTeamsToken() {
return new Promise((resolve, reject) => {
microsoftTeams.initialize(() => {
microsoftTeams.authentication.authenticate({
url: window.location.origin + "/ms-teams/auth-start",
width: 600,
height: 535,
successCallback: (result) => {
resolve(result);
},
failureCallback: (error) => {
reject(error);
}
});
});
});
}
I found this documentation very helpful on how to create the Authentication pop up and how to create a Callback window with the Token in it.
You might also want to cache the token and only create a popup when it expires.
This might be because you're using the auth popup option instead of the redirect option in whichever auth library you're using (hopefully MSAL 2.0). Teams is a little different because it's actually launching a popup for you when necessary, so although it sounds a bit strange, you actually want to use the redirect option, inside the popup that is launched. What might help is to look at the new SSO Sample app in the Teams PnP samples.
Go to: %APPDATA%\Microsoft\Teams
Open the file hooks.json (if it's not there, create it)
Add the following to it: {"enableSso": false, "enableSsoMac": false}
That's it, now Teams desktop has the same authentication workflow as the browser version. Have a nice day.

React-native : how to check if it's the user's first connection?

I 'm new to react-native and I would like to set up my first page of the app with
1- The user never logged in the app, I 'll present the app with some slides + go to signup page
2 -The user is already in => directly go to the user page
3 -The user is already in but the id is not correct
Can you guide me through it ?
For the first point I really don't know how to check if the user exist in my db
For the second and third points I thought I'd try :
onPressLogin(){
fetch('linktomyAPI',{
method: 'POST',
headers:{
'Content-Type' : 'application/json',
'Accept':'application/json'
},
body: JSON.stringify({
username:this.state.username,
password: this.state.password,
})
})
.then(response => response.json())
.then((responseData) =>{
if(responseData.error !== 1){ // verify the success case, as you didn't provide the success case i am using the error code
this.setState({ // its recommended you verify the json before setting it to state.
userdetail: responseData,
})
setTimeout(() => {
Actions.Authentication();
}, 2300);
AsyncStorage.setItem('username', this.state.username); // its setItem not saveitem.
} else {
console.log(responseData);
Alert.alert(JSON.stringify(responseData)); // Alerts doesn't allow arrays or JSONs, so stringify them to view in Alerts
}
}).catch((error) => {
// handle catch
console.log("error:"+JSON.stringify(error));
});
}
Do you think I can do this way, is that relevant?
Thanks for taking the time to answer me. I'm really new so I need help and explanations. Thanks !!! :)
you can use the UserInfo to do. firstly, you have saved the user info in memory use Session js and in the device local file use AsyncStore. you already do it use the AsyncStore.
firstly save the user info into Session,the Session structure is:{id:"dd333",name:"john"},
...
setTimeout(() => {
Actions.Authentication();
}, 2300);
Session.id = res.id;
Session.name = res.name;
AsyncStorage.setItem('userinfo', Json.stringfy(res));
then you can show diffent page and condition.
// in the component which you want compoentDidMount
componentDidMount() {
// here you can try to get it from AsyncStore if the Session is null.
// then hanle it as the followng
if(Session.id == ""){
//default it is "", it means the user does not login
} else if(Session.id != "222"){
// the user id is not correct
} else {
// here is the user login and id is correct
}
}

The sms code has expired. Please re-send the verification code to try again

Whenever I tried to login with phone number using react-native-firebase sdk, I recieve OTP code through sms and when I submit the recieved code, an error is there saying:"The sms code has expired. Please re-send the verification code to try again." And here point to be noted that an entry for respective phone number is writing in Users section of firebase even there is an error.
I am using following:
NodeJS: v8.11.1,
NPM: v5.6.0,
react-native: "^0.59.9",
react-native-firebase: "^5.5.3"
Some links I have already tried are:
1. https://github.com/invertase/react-native-firebase-
docs/blob/master/docs/auth/phone-auth.md
2. https://stackoverflow.com/questions/46522726/firebase-phone-
authentication-error-the-sms-code-has-expired
3. https://www.bountysource.com/issues/45308170-firebase-phone-
number-auth-integration
4. https://medium.com/#chrisbianca/getting-started-with-firebase-
authentication-on-react-native-a1ed3d2d6d91
5. https://invertase.io/oss/react-native-firebase/v6/auth/phone-
auth
In MobileRegistration.js:
navigateToOtpScreen() {
console.log("Phone number: ", "+91" + this.state.phoneNumber)
firebase.auth().signInWithPhoneNumber("+91" +
this.state.phoneNumber)
.then(confirmResult => {
this.setState({ confirmResult, message: 'Code has been sent!'})
this.props.navigation.navigate('EnterOtp', { 'confirmResult':
confirmResult})
})
.catch(error => {
alert(error.message);
this.setState({ message: `Sign In With Phone Number Error:
${error.message}` })
});
};
In EnterOtp.js:
componentDidMount() {
this.unsubscribe = firebase.auth().onAuthStateChanged((user) => {
alert(JSON.stringify(user));
if (user) {
this.setState({
user: user.toJSON()
});
} else {
// User has been signed out, reset the state
this.setState({
user: null,
message: '',
otp: '',
otp1: '',
otp2: '',
otp3: '',
otp4: '',
otp5: '',
otp6: ''
});
}
});
}
componentWillUnmount() {
if (this.unsubscribe) this.unsubscribe();
}
verifyOTP = async () => {
const {
confirmResult,
} = this.props.navigation.state.params;
let otp = this.state.otp + "" + this.state.otp1 + "" + this.state.otp2 + "" + this.state.otp3 + "" + this.state.otp4 + "" + this.state.otp5 + "" + this.state.otp6
if (confirmResult && otp.length) {
alert(otp);
confirmResult.confirm(otp).then((user) => {
AsyncStorage.setItem('accessToken', confirmResult._verificationId);
this.props.navigation.navigate('SetupCoverVideo');
this.setState({
message: 'Code Confirmed!'
});
})
.catch(error => {
alert(error.message) && this.setState({
message: `Code Confirm Error: ${error.message}`
})
});
}
}
Expected Result: Code should be verified and an entry should be in Users section of firebase and navigate to SetupCoverVideo.
Actual Result: Facing an error saying: "The sms code has expired. Please re-send the verification code to try again." And here point to be noted that an entry for respective phone number is writing in Users section of firebase even there is an error.
I am wondering for the solution. Anyone please assist me.
Apparently, some recent versions of Android are smart enough to receive the SMS verification code and use it to authenticate the user. This authentication happens in the background while the user still receives the verification code in an SMS. When the user tries to enter the verification code, he/she gets a message that the verification code expired, because Android has already used it (in the background) and has already logged in the user! To double-check that, check the Firebase Console. You should find that this new user has been added to the list of users.
To avoid receiving the verification code expiry message, we need to set up a listener for "authentication changes." As soon as Android logs in the user in the background, this listener should navigate the user away from the login screen, in which he/she was supposed to enter the verification code. The following demonstrates how this can be implemented. I would add the following code to the login screen.
Example code for use with functional components:
useEffect( () => {
firebase.auth().onAuthStateChanged( (user) => {
if (user) {
// Obviously, you can add more statements here,
// e.g. call an action creator if you use Redux.
// navigate the user away from the login screens:
props.navigation.navigate("PermissionsScreen");
}
else
{
// reset state if you need to
dispatch({ type: "reset_user" });
}
});
}, []);
Example code for use with class components:
// I did NOT test this version, because I use functional components.
componentDidMount() {
firebase.auth().onAuthStateChanged( (user) => {
if (user) {
// Obviously, you can add more statements here,
// e.g. call an action creator if you use Redux.
// navigate the user away from the login screens:
props.navigation.navigate("PermissionsScreen");
}
else
{
// reset state if you need to
this.setState({
user: null,
messageText: '',
codeInput: '',
phoneNo: '',
confirmResult: null,
});
}
});
};
You need to check for background authentication using:
conponentDidMount() {
firebase.auth().onAuthStateChanged((user) => {
if (user) {
// alert(JSON.stringify(user))
// Obviously, you can add more statements here,
// e.g. call an action creator if you use Redux.
// navigate the user away from the login screens:
}
});
}
Then you need to log out your user once you are done with it (I faced this issue of old user session already present while new user was coming to authenticate)
So, at the time of logging out use:
if (firebase.auth().currentUser)
firebase.auth().currentUser.delete();
And you are all set!