Open fool opened 4 years ago
i have not seen this implemented a lot in other services. there are several pitfalls here.
for one, the backend should be able to upgrade the hashing method to provide more security without the frontend being affected by that (breaking change otherwise)
also, the reason we store passwords hashed in a DB is so that a DB leak will not allow the attacker to use the credentials. if we allowed login using hashes, leaked DBs could be used for login. I don't think it's considered good practice to do hashing in the browser for login. therefore the proposed method is not necessarily more secure.
The customer stated several reason for wanting this feature:
I think the suggestion is to hash both on the client side and again on the server side.
Sending a client side hash of the password does not provide additional security when intercepted since one could simply use the intercepted hash for login (doesn't really need the original password).
It does help if the same password is used for other services, and those services don't use the same hash function, so the hash will only be valid for gotrue
.
Another reason I've seen clients use this method is for preventing password managers from saving passwords, but not sure this is valid for this library.
On a side note, a simple workaround would be to hash the password before calling any of those methods.
a diffferent context - but related I'm running some node code - I have a valid apple session from a mobile client I want to setup some node code on ec2 server to host this https://github.com/johndpope/Sign-in-with-Apple-for-supabase
I want to find matching users on system and give a jwt back. If I can instantiate a user by id - it would be preferable - but all this code in repo seems specific to client side browser stuff. I have db access to auth.users via postgres node. This is all server side - admin credentials.
apple gives me this
const jwtClaims = { iss: 'https://appleid.apple.com',
aud: 'app.test.ios',
exp: 1579483805,
iat: 1579483205,
sub: '000317.c7d501c4f43c4a40ac3f79e122336fcf.0952',
at_hash: 'G413OYB2Ai7UY5GtiuG68A',
email: 'da6evzzywz@privaterelay.appleid.com',
email_verified: 'true',
is_private_email: 'true',
auth_time: 1579483204 }
I find matching email email: 'da6evzzywz@privaterelay.appleid.com',
const res = await db.query('SELECT id,email,encrypted_password FROM auth.users WHERE email = $1', ["test@test.com"]);
console.log("ok:",res.rows[0]);
if (res.rows.length == 0){
return null;
}
auth
.login(res.rows[0].email, res.rows[0].encrypted_password, true)
.then(response => {
console.log("response:",response);
return response;
})
user.jwt() // would work - how can I instantiate an appropriate user? how can I give back a valid JWT? (I'm also wanting to create the user - but that's a separate problem)
UPDATE it doesn't look like anyone ever created the access_token via javascript I could convert apple code https://github.com/netlify/gotrue/blob/master/api/token.go#L166
func generateAccessToken(user *models.User, expiresIn time.Duration, secret string) (string, error) {
claims := &GoTrueClaims{
StandardClaims: jwt.StandardClaims{
Subject: user.ID.String(),
Audience: user.Aud,
ExpiresAt: time.Now().Add(expiresIn).Unix(),
},
Email: user.Email,
AppMetaData: user.AppMetaData,
UserMetaData: user.UserMetaData,
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte(secret))
}
tokenString, terr = generateAccessToken(user, time.Second*time.Duration(config.JWT.Exp), config.JWT.Secret)
UPDATE I ported over the code - though not entirely tested.... https://github.com/johndpope/Sign-in-with-Apple-for-supabase/blob/master/server.js#L172
UPDATE 2 - I can create a user with admin - but now I want to issue a corresponding jwt. Is there a way?
const { data: newUser, error } = await supabase.auth.admin.createUser({
email: jwtClaims.email,
email_confirm: true, // missing provide / identities guff
user_metadata:jwtClaims
})
console.log("newUser:", newUser);
console.log("jwt:", newUser.jwt());
andledPromiseRejectionWarning: TypeError: newUser.jwt is not a function
at returnExistingSupabaseJWTorCreateAccount (/Users/johndpope/Documents/gitWorkspace/Sign-in-with-Apple-for-node/server.js:189:31)
at processTicksAndRejections (internal/process/task_queues.js:95:5)
(Use `node --trace-warnings ...` to show where the warning was created)
// create an access token
let claims = {
"StandardClaims": {
"sub": newUser.id,
"aud": "",
"exp": Math.floor(Date.now() / 1000),
},
"Email": newUser.Email,
"AppMetaData": newUser.AppMetaData,
"UserMetaData": newUser.UserMetaData,
}
console.log("✅ claims:", claims);
const jwt = sign(claims, config.supabase.jwtSecret);
All methods that can use a password, essentially require it to be sent in plaintext (yes, over https, but still not encoded in any way):
It would be great if there were some more secure method of passing this password around during user creation/login/update