Hash Passwords
Introduction
In this recipe, you'll learn how to securely hash passwords to protect user credentials in your application. Password hashing is an essential part of securing sensitive information before storing it in your database.
Before continuing, ensure you have:
- A local Hasura DDN project.
- A lambda connector added to your project.
- Familiarity with bcrypt for hashing passwords.
NB: Bcrypt is a common, well-tested library for password hashing in various languages, and it's widely supported across many systems.
Recipe
Step 1. Write the function
- TypeScript
- Python
- Go
npm install bcryptjs
import bcrypt from "bcryptjs";
export async function hashPassword(password: string): Promise<string> {
const salt = await bcrypt.genSalt(10);
const hashedPassword = await bcrypt.hash(password, salt);
// Add your own logic here to hit your Hasura endpoint and perform an insertion
return hashedPassword;
}
bcrypt==4.2.0
from hasura_ndc import start
from hasura_ndc.function_connector import FunctionConnector
import bcrypt
connector = FunctionConnector()
@connector.register_query
async def hash_password(password: str) -> str:
salt = bcrypt.gensalt()
hashedPassword = bcrypt.hashpw(password.encode("utf-8"), salt).decode("utf-8")
# Add your own logic here to hit your Hasura endpoint and perform an insertion
return hashedPassword
if __name__ == "__main__":
start(connector)
go get golang.org/x/crypto/bcrypt
go get golang.org/x/net/[email protected]
package functions
import (
"context"
"fmt"
"golang.org/x/crypto/bcrypt"
"hasura-ndc.dev/ndc-go/types"
)
// HashPasswordArguments defines the input arguments for the function
type HashPasswordArguments struct {
Password string `json:"password"`
}
// HashPasswordResult defines the output result for the function
type HashPasswordResult string
// FunctionHashPassword hashes a password string and returns it as a string result
func FunctionHashPassword(ctx context.Context, state *types.State, arguments *HashPasswordArguments) (*HashPasswordResult, error) {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(arguments.Password), bcrypt.DefaultCost)
if err != nil {
return nil, fmt.Errorf("failed to hash password: %v", err)
}
// Add your own logic here to hit your Hasura endpoint and perform an insertion
result := HashPasswordResult(string(hashedPassword))
return &result, nil
}
Step 2. Track your function
To add your function, generate the related metadata that will link together any functions in your lambda connector's source files and your API:
ddn connector introspect <connector_name>
Then, you can generate an hml
file for the function using the following command:
ddn command add <connector_name> "*"
Step 3. Test your function
Create a new build of your supergraph:
ddn supergraph build local
In your project's explorer, you should see the new function exposed as a type and you should be able to execute a mutation like this:
Wrapping up
In this guide, you learned how to enhance your API by securely hashing passwords before storing them in your database. Your API clients can invoke this mutation and you can handle all of the logic of hashing and inserting the new record directly from your API.
Learn more about lambda connectors
- TypeScript Node.js connector.
- Python connector.
- Go connector.