Authentication Flow
Introduction
Damsy ERP authenticates users with a classic session-based login: the user selects a company, submits credentials, the application validates against SQL Server via GetLoginUser, and on success populates ASP.NET session state before redirecting to the dashboard.
There is no JWT or OAuth flow for standard module access. The session keys written at login become the authorization context for all subsequent requests.
Purpose
This page documents the complete authentication sequence — from the login form through password encryption, stored procedure validation, session initialization, and redirect — so you can extend login behavior or debug sign-in failures safely.
When to Use
Use this reference when you:
- Debug "invalid username or password" issues
- Add fields returned from
GetLoginUserto session - Implement account lockout or password policy changes
- Trace why a user reaches dashboard but lacks module tiles
How It Works
Sequence diagram
Key components
| Component | Location | Role |
|---|---|---|
LoginController | DamsyERP.UI/Controllers/LoginController.cs | GET/POST login, session fill, redirect |
Login_DAL | DAL/Login_DAL.cs | Calls [dbo].[GetLoginUser] |
HashCryptography | UTILITIES | Encrypts password before SP call |
GetLoginUser | SQL Server | Validates credentials; returns user + module access |
Common.GetCompany | Shared helper | Populates company dropdown on login form |
LoginAttemptTracker | UI helper | Rate-limits failed attempts |
GET /Login/Index
- If
Session["CompID"]is already set → redirect to~/Dashboard/Index - Otherwise call
BuildLoginView():- Load companies via
Common.GetCompany - Insert placeholder "Select Company" (CompID = 0)
- Run
UpdateSoftwareVersion()(writesSession["Version"]) - Return
UserLoginview
- Load companies via
/Login/UserLogin redirects to /Login/Index for legacy bookmarks.
POST /Login/Index
- Anti-forgery:
[ValidateAntiForgeryToken]on POST - Lockout check:
LoginAttemptTracker.IsLockedOut— returns friendly message if too many failures - Set
Login_BO.User.IsActive = true Login_DAL.GetLoginUserwith Login ID, encrypted password, CompID- Load default payroll period via
PayrollReportService.GetStartForMonth - Load SMTP settings via
Login_DAL.MailConfigure→[dbo].[GetEmailConfigration] - Success criterion:
objuser.UserNameis not null or empty
Password handling
Inside Login_DAL.GetLoginUser:
HashCryptography encryptPassword = new HashCryptography();
objUser.Password = encryptPassword.Encrypt(objUser.Password);
// passed to SP as @userpassword
The stored procedure compares against the encrypted value stored in the database. Do not send plaintext passwords to SQL.
Session keys set on success
After successful authentication, Session.Clear() runs first, then:
| Session key | Source |
|---|---|
dtVerifyUser | Full BO.User object (includes module bool flags) |
UserName, UserID | Display name and UserAccountsID |
CompID, CompName | Selected company |
Role, RoleId | Role name and ID (note: RoleId casing) |
StartMonth, StartYear | Default payroll period |
BranchCode | User branch |
CDKEY, EFUSERNAME, EFPASSWORD | E-invoice credentials |
ZAPIPATH | Server location / ZAPI base |
GenerateIRNUri, CancelIrnUri, PrintIRNUri | IRN API endpoints |
PrintEWayBillDetailed, PrintEWayBillSummary, EWayBillDeliveryChallan | E-Way bill URLs |
SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PSWD | Mail configuration |
Redirect: return Redirect("~/Dashboard/Index");
Failure path
LoginAttemptTracker.RecordFailure- Reload company list
- Model error: "The user name or password provided is incorrect"
- Return
UserLoginview (does not reveal whether login ID or password failed)
Developer Notes
- FormsAuthentication.SignOut is called on logout, but day-to-day module gating uses session keys, not roles claims.
- Software version check: Login also updates
SoftwareVersionstable when app version exceeds DB version. - Module flags come from SP columns mapped in
Login_DAL(e.g.Zstock→User.ZSTOCK,AttendancePuncging→User.AttPunch). - Fine-grained menu permissions use
GetDataUserPermissionsseparately — not at login time for every menu item.
Access control uses dtVerifyUser boolean properties and per-menu permission SPs. There is no Session["ModuleAccess"] key in this application.
Examples
Minimal successful login (blank DB seed)
| Field | Value |
|---|---|
| Company | Damsy Technologies |
| Login ID | admin |
| Password | Admin@123 |
Checking authentication in a new controller action
if (string.IsNullOrEmpty(Convert.ToString(Session["CompID"])))
return RedirectToAction("UserLogin", "Login", new { Area = "" });
Reading module access after login
var user = Session["dtVerifyUser"] as User;
if (user?.Payroll == true) { /* show payroll features */ }
Related Pages
- Session Management — full session key reference
- Login — user-facing login walkthrough
- Dashboard — post-login home
- Data Access Layer — DAL patterns used by Login_DAL
Important Notes
Session.Clear() before populating keys on successful login reduces stale session data risk. Preserve this pattern if extending login.
Login POST must include a valid company (CompID >= 1). The BO validates [Range(1, Int32.MaxValue)] on Compid.
Common Mistakes
| Mistake | Symptom |
|---|---|
| Comparing plaintext password in SQL | Login always fails |
Using RoleID session key (wrong casing) | Null role in permission checks — use RoleId |
| Skipping CompID in SP call | User authenticates against wrong company |
| Expecting menu items without DB permissions seed | Login works; menus empty or pages unauthorized |
| Storing password in session | Not done by design — only user metadata and flags |
Next Steps
- Read Session Management for keys added later in the session lifecycle.
- Read Module Routing to navigate from dashboard into modules.