İçeriğe geç
wedevit

August 19, 2026 · 10 min read · software

İlhan Buğra Aslan

Should you build authentication yourself or use an identity provider?


Short answer: unless identity is your product, use something that already exists, but be clear about which "already exists" you mean. On one side sit hosted identity services billed by monthly active users (Auth0, Clerk, Amazon Cognito, Microsoft Entra External ID). On the other sit open-source identity servers you run yourself (Keycloak, Zitadel, Ory, Authentik, FusionAuth). A third option keeps login inside your application through a library. When a team says "let's just build it," they almost always mean that third option, which is not writing cryptography from scratch but owning the flows around a mature library. That is where the real decision lives. Checking a password is easy. Carrying account recovery, session revocation, MFA enrollment and the enterprise SSO request that arrives three years from now is not.

Login is a subsystem, not a screen

The fastest way to see the actual scope is to open OWASP's verification standard. ASVS 5.0, released on 30 May 2025, holds roughly 350 requirements across 17 chapters, and four of those chapters describe what we casually call "login": V6 Authentication, V7 Session Management, V9 Self-contained Tokens, V10 OAuth and OIDC. V6 alone carries 50 requirements in eight sections, and the section titles map the work: password security, general authentication security, authentication factor lifecycle and recovery, multi-factor requirements, out-of-band mechanisms, cryptographic mechanisms, and authentication with an identity provider.

Even the password half is busier than it looks. NIST SP 800-63B Revision 4, published in August 2025, sets firm rules: a password used as the only authentication factor must be at least 15 characters, one used inside a multi-factor flow may drop to 8, verifiers should accept at least 64 characters, composition rules requiring mixed character types must not be imposed, the chosen password must be compared against a blocklist of common and breached values, and periodic rotation must not be required. A change is forced only when there is evidence of compromise. ASVS ties the same thinking to levels: at level 1 you check against at least the top 3000 passwords that match your own policy, and at level 2 against a set of breached passwords.

On storage, the OWASP password storage guidance puts Argon2id first with a minimum of 19 MiB of memory, 2 iterations and 1 degree of parallelism, and offers 46 MiB with 1 iteration for teams who would rather spend memory than CPU time. If you are on bcrypt, use a work factor of at least 10 and remember the 72-byte input limit, because anything longer is silently truncated. Those three paragraphs explain why "we'll write the login screen in two days" never fits in two days.

Where each of the three options runs out

A hosted service gets you to a first release fastest. Social login, MFA, email verification, password reset and an admin console arrive ready, and your job shrinks to making the app an OpenID Connect client. The cost shows up in two places: the bill grows with your user count, and your price starts at whichever tier holds the feature you need.

A self-hosted identity server is the middle path. Keycloak was donated to the CNCF in April 2023 and sits at incubating status, Apache-2.0 licensed and backed by Red Hat. On the protocol side it does the same job as the hosted options, all the data stays with you, and nothing is metered per user. In exchange you operate one more component: version upgrades, backup and restore, high availability, certificate renewal, theme and flow customization. Reasonable for a team with devops capacity, usually a bad trade on a single-developer project.

The library option keeps the user table in your database and the flows in your code. Auth.js, Better Auth, Spring Security and Devise all take on the cryptography and session handling. For a single application with a single client and no enterprise SSO on the horizon, this is the lowest-friction answer. Its limit arrives with the second application, a mobile client or service-to-service authorization, at which point you notice you do not actually have an authorization server.

What you sign up to own when you build

Verifying a password is the easy line item. The rest of the list looks like this: registration and email verification, single-use reset links that expire, error messages that do not reveal whether an account exists, rate limiting plus a lockout policy that does not let an attacker lock your customers out on purpose, revoking sessions on every device after a password change, MFA enrollment and recovery codes, a screen where a user can see and end active sessions, and an audit trail for the admin impersonation feature someone will inevitably request.

The weakest point in that list is rarely the password. It is recovery. ASVS gives V6.4 its own section for a reason: how the initial credential is generated, how a reset is verified and how administrative intervention is bounded are each separate requirements. The two failures we see most often are reset links that never expire or can be replayed, and a recovery flow that quietly bypasses MFA on an account where MFA is enabled. In a system like that, the second factor is decoration.

The part of the invoice you don't see on the pricing page

The pricing page shows you cost per user. It rarely shows the line items that decide the outcome. Enterprise SSO, meaning SAML or OIDC federation with a customer's own directory, is the most expensive add-on in this category, and most vendors either charge per connection or reserve it for the top tier. Audit log retention windows, which MFA methods live in which tier, separately metered machine-to-machine tokens, management API rate limits and the right to serve login pages on your own domain hide in the same place.

Assume prices move in both directions. Auth0 raised its free tier from 7,500 to 25,000 monthly active users in 2024, while other vendors restructured tiers over the same period. So build the comparison on your three-year user projection and on the tier that holds the features you need, not on today's headcount. Comparing an annual subscription against developer time is fair, as long as you compare against maintenance rather than initial setup: identity infrastructure keeps living after it ships.

Buying transfers the work, not the risk

Using an identity provider shrinks your attack surface. It does not zero it. Okta's October 2023 support-system breach is the textbook case: the first disclosure described 134 affected customers, about one percent of its base, and a later update revealed that the attacker had downloaded the names and email addresses of all 18,400 users of that support system. Once you depend on a provider, the quality of their incident response becomes part of yours.

Availability deserves a concrete question too: what happens when the provider goes down? Do existing sessions survive, do only new logins stop, or does the whole application close? Answer that before signing, and write the answer into your observability and error budget math. There is a supply-chain angle as well, since the provider's browser SDK executes on your pages, which is the identity-side version of the dependency argument in our post on software supply chain security.

Exit cost: password hashes do not travel

The most expensive part of an identity decision is reversing it. Amazon Cognito does not let you export password hashes or MFA secrets from a user pool. Moving to another provider therefore means either emailing a reset to every user or running a lazy migration: on a user's first login, the new system verifies the password against the old one, and if it matches, hashes and stores it locally, migrating that user in place. The pattern works, but it means operating two systems side by side for months, and users who never log in still need a reset in the end.

A subtler dependency is the provider's user identifier spreading through your database. If you used the sub claim from the token as a foreign key across your tables, switching providers means remapping references in dozens of places. The cheap insurance: mint your own identifier in your own users table, keep the provider's identifier as one field on that row, and hang every other relationship off yours. Keep the code you write inside the provider's rules engine thin for the same reason, whether that is Auth0 actions or a Keycloak authenticator, because business logic that lands there does not travel.

Couple to the standard, not to the vendor

Portability comes from where you draw the boundary, not from which logo you pick. If your application talks to the provider only over OpenID Connect, switching is a configuration exercise. If it has spread into proprietary APIs, proprietary token shapes and proprietary session behavior, switching becomes a project.

On the protocol side, RFC 9700 (BCP 240), published in January 2025, defines today's baseline: public clients must use PKCE, authorization servers must support it, redirect URIs must be validated with exact string matching, the implicit grant should not be used, the resource owner password credentials grant must not be used, and refresh tokens for public clients must either be sender-constrained or rotated on every use. OAuth 2.1 is still an IETF draft that will fold RFC 8252, PKCE (RFC 7636), the browser-based apps draft and RFC 9700 into one document. The short test: if you cannot describe your login as "authorization code plus PKCE," you have invented a protocol and nobody has reviewed it.

Where the tokens live is a separate decision

The second question after picking a provider is where tokens sit. The IETF's browser-based apps draft points at one pattern as the most secure: a server-side backend for frontend acts as the confidential OAuth client, keeps access and refresh tokens on its own side, and hands the browser nothing but an HttpOnly session cookie. Because the browser never sees a token, XSS cannot exfiltrate one.

If you already run Next.js, Nuxt or any framework with a server runtime, that pattern costs you no extra infrastructure. For a pure client-side single-page app that has to hold tokens in browser memory, at minimum insist on short-lived access tokens and refresh token rotation. The endpoint-side controls that go with this are covered in our post on API security and the OWASP API Top 10.

Selling B2B forces the decision earlier

In products sold to companies, what accelerates this decision is a procurement checklist rather than architectural taste. Past a certain customer size you will be asked to support login through the customer's own directory (Entra ID, Google Workspace, Okta), to deactivate accounts automatically when an employee leaves, which means SCIM provisioning, to honor the customer's own MFA and session-timeout policy, and to support domain verification with just-in-time account creation on first login. All of it can be built. But managing a separate federation configuration per customer becomes permanent work for the team that built it.

The deeper design mistake usually sits in the data model: assuming a user belongs to exactly one organization. If you do not model a person who can hold accounts at two different customers, your first consulting-firm customer forces that change under pressure. We covered how the tenant boundary gets enforced in the data layer in our post on multi-tenant SaaS architecture. The identity-side rule is the matching one: derive the tenant from the token, never from the request body.

Criteria: which option, when

Take a hosted identity service when the team is small, you have more than one client (web, mobile, services), enterprise SSO is a near-term ask, and your projected user count keeps the bill sane for three years. Run an open-source identity server yourself when keeping data under your own control is a requirement rather than a preference, when user counts make per-MAU pricing painful, and when you have the capacity to operate it. Keep it in the application with a library when there is one app, one client, no federation on the roadmap, and a real need to shape the login flow yourself.

Two rules survive all three choices. Do not hand-roll password storage, token signing or session cookie generation; leave those to a library. And plan the second factor from the start, because MFA bolted on later almost always leaves a gap in the recovery flow. We compared the methods themselves in multi-factor authentication and passkeys.

Five things you can do this week

One: test your password reset link. If the same link works twice, or still works a day later, fix that before anything else. Two: change a password and confirm the session on your other device is gone; if it survives, you have no way to kill a stolen session. Three: on a test account with MFA enabled, run the recovery flow and watch whether it skips the second factor. Four: if you use a provider, write down which tier holds enterprise SSO, audit log retention and machine-to-machine tokens, then multiply by your three-year projection. Five: count how many tables in your database use the provider's user identifier as a foreign key; if the answer is not zero, you have just measured your exit cost.

None of those five makes the decision. They make its price visible. The expensive mistake in identity is rarely picking the wrong provider; it is drawing the boundary in the wrong place and finding out two years later that you cannot move. When you do sit down to choose, start from criteria rather than a diagram, the same framing we used for off-the-shelf versus custom software.


Need help with this topic?

get in touchall posts