I have this scenario where users are expected to fill up an alternative email address and use that to authenticate user but I don’t know how or if there is an existing API that can be used to do that. I would like to know it.
You probably need to design a custom auth:
Notice that here i’m using GraphQL API for internal calls, i’m also using Typescript
// Custom Email Auth module
export const CustomEmailAuth = {
async validateAuthData(authData: CustomAuthEmailInput) {
//authData.id is email, need to keep this name for Parse Server auth engine
if (authData.id && authData.password) {
// Auth data should be already set on the user
const { users } = await client.findUsersByCustomAuth({ email: authData.id })
if (users.edges?.length === 1 && users.edges[0] && users.edges[0].node) {
const user = users.edges[0].node
// Additional safety check
if (
user.authData?.customEmail?.id === authData.id &&
user.authData?.customEmail?.password &&
user.authData.customEmail.password ===
SHA512(authData.password).toString()
) {
return
}
}
}
// Always throw by default for security purpose
throw new Error('Invalid authData')
},
async validateAppId() {
return true
},
}
// On the Parse Server Config
auth: {
customEmail: {
module: CustomEmailAuth,
},
},
# The query used to find the user
query findUsersByCustomAuth($email: Any!) {
users(where: { authData: { equalTo: { key: "customEmail.id", value: $email } } }, first: 2) {
edges {
node {
id
username
authData {
customEmail {
id
password
}
}
}
}
}
}
Sorry I should have stated my tools first and made clear of the statement of what I’m trying to do. I’m not familiar with GraphQL, I only used, NodeJS Server and JS-SDK.
Let’s say, A user signed up with email and password. The username is what the user inputted as their email. Aside from it was personal info, and then alternativeEmail
field as part of _User
class name.
The next time, that user logged in, he decided to use his alternative email address to authenticate.
How will I be able to do that?
Based on your solution, I need to setup a custom authentication (though I need to study custom auth first), and in the client, I need to provide an AuthProvider and use linkWith
?
Yes custom auth + linkWith, parse server donnot support alternative emails for auth
Upon looking at UsersRoute of PS, I just saw how they handle querying for email, username, and password comparison using crypto. I’ll try to mimic haw they did it.
You can use this simple cloud code:
Parse.Cloud.define("loginWithAlternativeEmail", async (request) => {
var alternativeEmail = request.params.email;
var pass = request.params.pass;
if(!alternativeEmail||!pass){
throw "error";
}
var userQuery = new Parse.Query(Parse.User);
userQuery.equalTo("alternativeEmail",alternativeEmail);
userQuery.limit(1);
var result = await userQuery.find();
if(result.length<1){
throw "loginError";
}
var tempUser = result[0];
var user = await Parse.User.logIn(tempUser.get("username"),pass);
return user.getSessionToken();
});
Then use become method in javascript using sessionToken that cloud code returned.
Parse.User.become(token);
Yes more affordable solution ! Thanks @uzaysan
Thanks to both of you. @uzaysan I was wondering, is there any security risk like checking the number of attempts and so on?
I don’t think failed attemps would be security risk. Parse server itself comes with unlimited login try by default. But if you wanna restrict login after x times fail You can use accountLockout
policy. More information of parse parameters can be found here
Is there a way to pull that from parse server so that I will be able to re-use that kind of logic?
I didn’t understand what you said. English is not my native language. Can you explain a little simple?
So do I
I want to know if there is a way to re-use the logic of account policy from parse server instead of creating your own account policy?
So I guess you are talking about the code I posted above. It doesn’t change parse server account policy. It uses it. So normal account login/register should be work fine. Its just cloud code. It doesn’t change parse server behaviour.
Oh I see. Thanks a lot.