DAILY NEWS

Stay Ahead, Stay Informed – Every Day

Advertisement
Part 2 Building an Authentication System from Scratch – Backend Setup


User Registration & Secure Password Hashing with bcrypt

In the previous article, we built the backend foundation by setting up Express.js, PostgreSQL, environment variables, and a clean layered architecture.

With the backend ready, it’s time to implement the first authentication feature—User Registration.

Although registration appears straightforward, it involves much more than simply storing user details in a database. A secure registration system must validate user input, prevent duplicate accounts, protect passwords, and ensure that sensitive information is never exposed.

In this article, we’ll build the complete registration workflow while following security best practices.

The registration process follows a layered architecture, where each layer has a single responsibility.

Client


Routes


Controller


Service


Repository


PostgreSQL

Enter fullscreen mode

Exit fullscreen mode

The overall workflow is:

The client submits the registration form.
The controller receives the request.
The service validates the data.
The repository checks whether the email already exists.
The password is securely hashed using bcrypt.
The user is stored in PostgreSQL.
A success response is returned to the client.

Instead of placing all the registration logic inside the controller, I divided the implementation into three layers.

Controller

Responsible only for:

Receiving the HTTP request
Calling the service layer
Returning the HTTP response

The controller should never contain business logic or database queries.

Service

The service contains the application’s business logic.

For registration, it is responsible for:

Validating the request
Checking whether the email already exists
Hashing the password
Calling the repository to save the user

This layer acts as the brain of the application.

Repository

The repository communicates directly with PostgreSQL.

Its responsibilities include:

Checking if a user already exists
Creating a new user
Executing SQL queries

Keeping SQL isolated inside repositories makes the application easier to maintain and test.

The controller receives the registration request and forwards the data to the service layer.

// Register Controller Screenshot Here

Enter fullscreen mode

Exit fullscreen mode

The controller itself performs very little work.

Its responsibility is simply to:

Extract the request body
Call the service
Return either a success or an error response

This keeps controllers lightweight and easy to understand.

The service contains the actual registration workflow.

// Register Service Screenshot Here

Enter fullscreen mode

Exit fullscreen mode

The registration service performs the following steps:

Check whether the email already exists.
Generate a secure password hash.
Create the user in PostgreSQL.
Return the newly created user.

Because all business rules live inside the service layer, future changes become much easier.

For example, adding email verification later would require changes only inside the service, without affecting controllers or repositories.

The repository is responsible only for database communication.

// Repository Screenshot Here

Enter fullscreen mode

Exit fullscreen mode

Typical repository functions include:

findByEmail()
createUser()

Keeping SQL queries isolated improves readability and keeps the service layer database-agnostic.

One of the biggest mistakes an application can make is storing passwords in plain text.

Imagine a database leak.

If passwords are stored as plain text, every user’s credentials become immediately visible.

Instead, passwords should always be transformed into a secure one-way hash before being stored.

This is exactly why we use bcrypt.

bcrypt is one of the most trusted password hashing libraries available for Node.js.

Unlike encryption, hashing is a one-way operation.

This means:

The original password cannot be recovered.
Even the application itself cannot view the user’s password.
Only password verification is possible.

When a user registers, bcrypt performs several operations internally.

Password


Generate Random Salt


Password + Salt


Multiple Hashing Rounds


Store Hash in Database

Enter fullscreen mode

Exit fullscreen mode

Each password receives its own randomly generated salt before hashing.

Because of this:

Two users with the same password will have completely different hashes.
Rainbow table attacks become ineffective.
Brute-force attacks become significantly slower due to bcrypt’s configurable cost factor.

During login, the user enters their password as plain text.

bcrypt then:

Reads the stored hash.
Extracts the embedded salt.
Hashes the entered password using the same salt.
Compares the generated hash with the stored hash.

If both hashes match, the user is successfully authenticated.

const isMatch = await bcrypt.compare(
enteredPassword,
storedHash
);

Enter fullscreen mode

Exit fullscreen mode

One of bcrypt’s biggest advantages is that developers never need to manually manage salts or compare hashes—the library handles the entire verification process securely.

Using bcrypt provides several important security advantages.

✅ Passwords are never stored in plain text.

✅ Every password uses a unique random salt.

✅ Identical passwords generate different hashes.

✅ Brute-force attacks become significantly slower.

✅ Rainbow table attacks are mitigated.

These features make bcrypt one of the industry standards for password protection.

Once the backend implementation was complete, I verified the registration API using Postman.

Request

POST /api/auth/register

Enter fullscreen mode

Exit fullscreen mode

{
“username”: “Sriya”,
“email”: “sriya@gmail.com”,
“password”: “Password123”
}

Enter fullscreen mode

Exit fullscreen mode

Response

{
“success”: true,
“user”: {
“id”: 1,
“username”: “Sriya”,
“email”: “sriya@gmail.com”
}
}

Enter fullscreen mode

Exit fullscreen mode

Notice that the response never includes the password or its hash.

Only non-sensitive user information is returned to the client.

Now that users can securely register and their passwords are safely stored, the next step is allowing them to authenticate.

In the next article, we’ll build the Login Flow, where we’ll:

Verify user credentials
Compare passwords using bcrypt
Generate JWT Access Tokens
Generate Refresh Tokens
Understand how JWT authentication works internally



Source link

You Can’t Govern the AI You Can’t See



AI governance starts with visibility: a policy, a budget, or a guardrail can only act on the AI traffic a team can actually see. This guide explains why so much AI use stays out of IT’s view, why that gap stops governance before it starts, and how the Bifrost AI gateway and Bifrost Edge close it by making endpoint AI both visible and governable.

Every AI governance control an organization owns, from budgets and access rules to guardrails and audit trails, can only act on the AI traffic it can actually see. That ability to see what AI is running and what it is sending, often called AI visibility, is the precondition for everything else. The trouble is that most AI used at work now runs on the endpoint, inside desktop apps, browser tabs, and coding agents that reach a model provider directly, so the activity never reaches the systems security teams watch. A request that leaves a laptop for a third-party model without crossing a monitored path is, for governance purposes, a request that did not happen. The gap is wide, as a 2025 Gartner survey of cybersecurity leaders found that 69 percent have evidence or suspicion that employees are using public generative AI at work, which is exactly the usage most teams cannot account for.

Why you can’t govern what you can’t see

Governance is a chain of steps, and visibility is the first link. To act on an AI request, a system has to see it, attach an identity and a policy to it, enforce limits on it, and record what happened. When the first step is missing, none of the steps after it can run, because a control that never observes a request has nothing to act on.

This plays out the same way across every control a security or platform team relies on. A data guardrail that never inspects a prompt cannot redact the secret inside it. A budget that never counts a call cannot cap spending on it. A policy that never sees a tool cannot decide whether the tool is allowed. The result is not weak governance but absent governance, applied with confidence to the fraction of AI traffic that happens to be visible while the rest moves untouched.

Where AI goes out of view

AI goes out of view wherever it runs close to the user and connects straight to a provider, which describes most of where it now runs. Four blind spots account for the bulk of it:

Desktop assistants such as the ChatGPT app or Claude Desktop, signed in with personal accounts the organization does not manage.
Browser AI, including in-page assistants and extensions that an employee turns on without review.
Coding agents such as Claude Code, Codex, and Cursor, which read source code and call external services from the developer’s machine.
MCP servers wired into those tools, which can read files, call APIs, and act on a user’s behalf with standing access.

The list of tools an IT team can name is routinely a fraction of what employees actually use, because every new app, browser feature, and MCP server is one more thing to find, and discovery has no natural endpoint. The tools no one tracks are not necessarily malicious; they are simply outside anyone’s view, which is what places them beyond the reach of any control. Gartner has predicted that by 2030, more than 40 percent of organizations will experience security or compliance incidents tied to the use of unauthorized AI, a direct consequence of governing only the share of activity a team can see.

Why traditional tools don’t close the gap

Traditional controls do not close the visibility gap because they were built to watch the network, while endpoint AI mostly avoids the network they watch. Network proxies and data loss prevention systems inspect what crosses the corporate perimeter, yet a large share of AI traffic leaves the device for a provider directly, over an encrypted connection that resembles ordinary web browsing and that often never passes through a corporate proxy at all.

Three gaps recur across these approaches:

Network filtering and data loss prevention sit on the corporate network path, so requests sent straight from a device to a provider, including from machines off that network, never reach them.
Blocklists work from a known list of destinations, and new apps, browser features, and MCP servers appear faster than any list is updated.
SaaS and expense audits catch tools that bill the company, but they miss free tiers, personal accounts, and anything installed locally.

Each of these methods produces a partial list at a single moment, while the real usage is continuous and changes by the day. Closing the gap calls for visibility at the point where the AI actually runs, which is the endpoint itself.

How the Bifrost AI gateway and Bifrost Edge make AI visible and governable

Making AI governable takes two things in sequence: a place where AI traffic can be seen and governed, and a way to route the AI on every machine into that place. Bifrost, the open-source AI gateway built by Maxim AI, is that place, and Bifrost Edge is what brings the endpoint into it.

On the gateway, every request that passes through is recorded by built-in observability, which captures the prompt, the response, the model, the token counts, the cost, and the latency for each call, with no change to the application. The same gateway holds the virtual keys, budgets, and rate limits that tie usage to a person or project, along with the guardrail profiles that inspect prompts and responses. The limit, until now, has been reach: the gateway could see and govern only the traffic that something had already pointed at it.

Bifrost Edge closes that reach by routing all supported AI traffic on a machine through Bifrost rather than letting it go straight to the provider. The AI that used to leave the laptop unseen now appears in the same logs, under the same policies, as the rest of an organization’s AI. The division of labor is straightforward: Edge supplies the sight by inventorying endpoint AI and routing it through the gateway, and the gateway supplies the governance by recording, inspecting, and enforcing on the traffic it can now see. The gateway stays the single control plane, and Edge becomes its reach to the endpoint, so there is no separate visibility tool and no second policy model to maintain.

See what is running across the fleet

Visibility begins with knowing what is present. Bifrost Edge discovers the MCP servers configured in each app and the AI applications in use on every machine, then assembles a live view across the fleet of which assistants and which servers are running, on which apps, and on how many devices. New apps and servers surface as they appear rather than during a periodic audit, and each one can be allowed or denied from a single console, with the decision enforced on the device.

Govern and record the traffic you can now see

Once endpoint AI is visible, the same controls that protect gateway traffic apply to it. The guardrail profiles configured in Bifrost run before a prompt reaches a model and before a response returns, so secrets and personal data are caught or redacted before they leave the machine. Virtual keys and budgets tie each request to a person and a limit, while an administrative audit trail records who changed which policy and when, signed and retained for later review.

Roll it out and keep it current

Bifrost Edge deploys through the device management platforms an organization already runs, including Jamf, Microsoft Intune, Kandji, Omnissa Workspace ONE, and JumpCloud, across macOS, Windows, and Linux. Identity and keys come from the user’s single sign-on, so no secrets sit on the device, and central changes to policy and routing reach the fleet on their own once a machine is signed in.

Common questions about AI visibility

What is AI visibility?

AI visibility is the ability to see which AI tools, models, and services are in use across an organization, and to see the individual requests they send and receive. Without it, governance controls have nothing to act on, which is why visibility is treated as the first step rather than a report generated at the end.

How do you discover shadow AI?

Shadow AI is discovered by observing AI activity where it originates. Because most of it runs on endpoints, an agent on the device, such as Bifrost Edge, can inventory the apps and MCP servers in use and route their traffic through a gateway, which turns a guess about what employees might be using into a current list of what they actually use.

Can you get visibility without blocking AI?

Visibility does not have to mean blocking AI. Routing endpoint AI through the Bifrost gateway makes each request visible and subject to guardrails and budgets while the tools keep working normally, so an organization can approve and govern AI rather than ban it. Blocking remains available for tools a team decides to disallow, but that is a policy choice rather than a side effect of gaining visibility.

Visibility first, then governance

Shadow AI is, at its core, a visibility problem before it is a policy problem, because the strongest policy in the world cannot reach a request no one can see. The organizations that handle it well start by making endpoint AI visible, then apply the controls they already trust to the usage that visibility reveals.

Pairing the Bifrost AI gateway with Bifrost Edge gives security and platform teams both halves at once: the gateway records, inspects, and enforces, and Edge, currently in alpha, brings the AI on every machine into view so those controls have something to act on. Teams working through their own visibility gap can see how the combined approach fits together on the Bifrost Edge overview and register there for alpha access.



Source link