Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

accept pre-hashed passwords #114

Open
fool opened this issue Jun 30, 2020 · 5 comments
Open

accept pre-hashed passwords #114

fool opened this issue Jun 30, 2020 · 5 comments
Labels
type: feature code contributing to the implementation of a feature and/or user facing functionality

Comments

@fool
Copy link

fool commented Jun 30, 2020

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

@fool fool added the type: feature code contributing to the implementation of a feature and/or user facing functionality label Jun 30, 2020
@fool
Copy link
Author

fool commented Jun 30, 2020

@mraerino
Copy link

mraerino commented Jul 1, 2020

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:

  • protect against corp firewalls intercepting HTTPS -> that's not something we can defeat against. a lot relies on HTTPS working. users in such a corp setting will have to be aware and mitigate another way
  • leaked logs -> we do audit our code to make sure this doesn't happen. our server logs never contain full payloads

@erezrokah
Copy link
Contributor

erezrokah commented Jul 1, 2020

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.

@erezrokah
Copy link
Contributor

On a side note, a simple workaround would be to hash the password before calling any of those methods.

@johndpope
Copy link

johndpope commented Nov 14, 2022

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);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: feature code contributing to the implementation of a feature and/or user facing functionality
Projects
None yet
Development

No branches or pull requests

4 participants