sidebar_position | sidebar_label | description | keywords | seoFrontMatterUpdated | |||||
---|---|---|---|---|---|---|---|---|---|
4 |
Hash Passwords |
Learn how to securely hash passwords and handle them within your API. |
|
false |
import GraphiQLIDE from "@site/src/components/GraphiQLIDE"; import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem";
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.
:::info Prerequisites
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.
:::
```sh title="In your connector's directory, install the bcrypt package:"
npm install bcryptjs
```
```typescript title="In your functions.ts file, add the following:"
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;
}
```
```plaintext title="In your requirements.txt, add the bcrypt package:"
bcrypt==4.2.0
```
```python title="In your functions.py file, add the following:"
from hasura_ndc import start
from hasura_ndc.function_connector import FunctionConnector
import bcrypt
connector = FunctionConnector()
@connector.register_mutation
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)
```
```sh title="Add the bcrypt package and its dependencies to your connector's go.mod:"
go get golang.org/x/crypto/bcrypt
go get golang.org/x/net/[email protected]
```
```go title="In a Go file inside your functions directory, add the following:"
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
// ProcedureHashPassword hashes a password string and returns it as a string result
func ProcedureHashPassword(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
}
```
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> "*"
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:
<GraphiQLIDE
query={mutation HashPassword { hashPassword(password: "Thisisthesecure1!") }
}
response={{ "data": { "hashPassword": "$2a$10$0kqTP3HNd72oz8Q/qEA2PeOf.sr8jth/zMuICGmZu1qMCfA5N/b/a" } }
}
/>
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.
- TypeScript Node.js connector.
- Python connector.
- Go connector.