Logins, Users, and Roles in SQL Server: The Principle of Least Privilege

Written by

in

Logins, Users, and Roles in SQL Server: The Principle of Least Privilege

Two layers, frequently conflated by beginners — getting this right is the foundation of every other security decision, including the service-account grants your Chapter 12 capstone will require you to design and justify.

Least privilege, one keyring(hand out only the keys that fit)LOGINserver-level:can you connect?USERdatabase-level:what can you do here?app_service’s keyring — only what it needs:SELECTINSERT / UPDATEdb_ownerthe master key —opens everything. don’t.AuditLog tablerole GRANTs UPDATE…DENY UPDATE winsstill blocked, alwaysgrant exactly what’s needed —nothing wide, nothing “just in case”DENY always beats GRANT,no matter which rolehanded out the grant 📌

Login vs User

Login User
Scope Server-level — can you connect at all? Database-level — what can you do here?
Created with CREATE LOGIN CREATE USER ... FOR LOGIN

This two-layer split has a practical consequence worth internalizing: a login can exist on the server with no matching user in a given database (meaning it can authenticate but can’t touch that database’s objects at all), and conversely a database can be moved or restored to a different server where the matching login doesn’t exist yet — producing an “orphaned user,” a genuinely common real-world migration gotcha fixed with ALTER USER ... WITH LOGIN =.

Granting Access the Right Way

CREATE LOGIN app_service WITH PASSWORD = 'Str0ng!PasswordHere#2024';
CREATE USER app_service FOR LOGIN app_service;

CREATE ROLE app_read_write;
GRANT SELECT, INSERT, UPDATE ON SCHEMA::dbo TO app_read_write;
ALTER ROLE app_read_write ADD MEMBER app_service;

Granting permissions to a role, then adding users as members, is the pattern to default to over granting permissions to individual users directly. When ten application accounts all need the same access, you manage one role’s permission set instead of ten separate, potentially-drifting grants.

DENY Always Wins

DENY overrides GRANT, even from another role, regardless of role membership order

-- Even though app_read_write GRANTs UPDATE, an explicit DENY on the same table wins:
DENY UPDATE ON dbo.AuditLog TO app_read_write; -- audit logs should never be editable, even by the app

-- app_service, a member of app_read_write, now genuinely cannot UPDATE AuditLog,
-- despite the role's blanket GRANT UPDATE ON SCHEMA::dbo covering it

This makes DENY the right tool for a deliberate, hard exception to a broader grant — exactly the AuditLog scenario above, where “the app can write to most tables” needs one specific, unbreakable carve-out.

The Principle That Matters Most

An application’s service account should almost never be db_owner. Grant exactly the permissions the application actually needs — usually db_datareader + db_datawriter built-in roles, or narrower, custom roles scoped to specific tables. A compromised connection with db_owner can drop every table, read every row, and grant itself further permissions; the same compromise with a narrowly-scoped role can only do what that role permits.

Common mistake: Granting db_owner during development “just to get things working,” then never revisiting it before shipping. This is precisely the shortcut the Chapter 12 capstone’s security requirement is designed to catch — write out exactly which GRANTs a service account needs, and why, rather than reaching for the broadest role available.
Practice tip: Run the auditing query SELECT * FROM sys.database_role_members joined to sys.database_principals twice on the same login above, to see role membership from both directions. Getting comfortable inspecting existing grants, not just creating new ones, is what real least-privilege maintenance looks like.

Enjoyed this?

Subscribe to get every new SQL Server lesson as soon as it’s published, and share it with a developer who’d find it useful.

📡 Subscribe via RSS  | 
Share on X  | 
Share on LinkedIn  | 
Share on Facebook

Want the full structured course with quizzes, projects, and 10+ exercises per chapter? Check out SQL Server for Developers & DBAs, coming soon on this site.