Authenticate user in stored procedure - sql-server

I am new to sql and I am not sure what's wrong with my stored procedure.
User inputs user name & password which are my input parameters and if it is correct then return 'Login Success', if UN is incorrect than return 'Incorrect UN' or if PW is incorrect than return 'Incorrect PW'. In the stored procedure I have an IF Else statement and it is only hitting the first IF statement not other.
Please have a look my stored procedure:
CREATE PROCEDURE [dbo].[AuthenticateUser]
#UserName varchar(15),
#Password varchar(15),
#Role varchar(25) OUTPUT
AS
SET NOCOUNT ON
BEGIN
DECLARE #UN VARCHAR(25)
DECLARE #PW VARCHAR(25)
SELECT #UN = UserName, #PW = Password FROM LogIn
IF (#UN != #UserName COLLATE SQL_Latin1_General_CP1_CS_AS)
BEGIN
SET #Role = 'Incorrect User Name'
END
ELSE
BEGIN
IF (#PW != #Password COLLATE SQL_Latin1_General_CP1_CS_AS)
BEGIN
SET #Role = 'Incorrect Password'
END
ELSE
BEGIN
SET #Role = 'Logged in Successfully'
END
END
SELECT #Role
END
Thank you for your help

You are doing this:
SELECT #UN = UserName, #PW = Password FROM LogIn
IF (#UN != #UserName COLLATE SQL_Latin1_General_CP1_CS_AS)
These comparisions #UN = UserName and #PW = Password should be made in the WHERE clause to help in proper filtering of rows.
Here is the code rewritten (you can change to using your own table name)
Drop Table TestLogin
GO
Create Table TestLogin
(
UserName VarChar (20),
Password VarChar(20)
)
Insert TestLogin Values ('One', 'Two')
GO
Drop PROCEDURE AuthenticateUser
GO
CREATE PROCEDURE AuthenticateUser
#UserName varchar(15),
#Password varchar(15),
#Role varchar(25) OUTPUT
AS
If ((SELECT Count (*) From TestLogin Where UserName COLLATE SQL_Latin1_General_CP1_CS_AS = #Username And Password COLLATE SQL_Latin1_General_CP1_CS_AS = #Password) = 0)
Begin
If ((SELECT Count (*) From TestLogin Where UserName COLLATE SQL_Latin1_General_CP1_CS_AS = #Username) = 0)
Begin
Select #Role = 'Incorrect User Name'
End
Else
Begin
Select #Role = 'Incorrect Password'
End
End
Else
Begin
Select #Role = 'Logged in Successfully'
End
GO
Declare #Role VarChar (100)
Exec AuthenticateUser 'One', 'Two', #Role Output
Print #Role
Exec AuthenticateUser 'One', 'TwoX', #Role Output
Print #Role
Exec AuthenticateUser 'OneX', 'Two', #Role Output
Print #Role
The three examples provided at the end show you how the procedure behaves when you give it a good login, or either parameter is incorrect.

Change it to a SELECT COUNT(1) FROM userLogin.... and then use ExecuteScalar() on the SqlDataReader object.
As a side note, it's not a good idea to store your passwords in the DB in plain text, but hash them instead, preferably with a salt value.

Try this instead:
Create PROCEDURE [dbo].[AuthenticateUser]
#UserName varchar(15),
#Password varchar(15),
#Role varchar(25) OUTPUT
AS
SET NOCOUNT ON
BEGIN
If Not Exists (Select 1 From LogIn Where UserName = #UserName) Set #Role = 'Incorrect UserName'
Else If Not Exists (Select 1 From LogIn Where Password = #Password) Set #Role = 'Incorrect Password'
Else Set #Role = 'Logged in Successfully'
Select #Role
END

Generally it is not good idea to give an attacker a cue "name is OK, now guess PWD". Plus, password should be at least case sensitive. For this purpose:
select #un=username from LogIn
where username=#username
and cast(password as varbinary(max)) = cast(#password as varbinary(max))
if #un is null
set #role = 'UN or PWD is incorrect'
else
set #role = 'Success'
If you want to give hints:
select #un=username from LogIn
where username=#username
if #un is null
set #role = 'UN not found'
else
begin
select #un=username from LogIn
where username=#username
and cast(password as varbinary(max)) = cast(#password as varbinary(max))
if #un is null
set #role = 'password incorrect'
else
set #role = 'Success'
end
P.S.: I hope username is unique in your table.

Related

Creating procedure to login with password hashed and salt, returning Incorrect password

Ok, so I am making an ASP.net website application that has a registration form that will take in details about the user and the password will be encrypted with a registration procedure that will hash and salt the password. Now the problem is that when creating a login procedure. The login procedure that I implemented is displaying "Incorrect password" on #responseMessage output when passing in the username and password. What could be the problem and how to fix this issue?
RestuarantProc - Registration Procedure
CREATE PROCEDURE [dbo].[RestuarantProc]
#FirstName NVARCHAR(50),
#LastName NVARCHAR(50),
#UserName NVARCHAR(50),
#Password NVARCHAR(50),
#Age INT,
#Email VARCHAR(100),
#responseMessage NVARCHAR(250) OUTPUT
AS
BEGIN
SET NOCOUNT ON
DECLARE #salt UNIQUEIDENTIFIER=NEWID()
BEGIN TRY
INSERT INTO RestuarantReg(FirstName, LastName, UserName, PasswordHash, PasswordSalt, Age, Email)
VALUES(#FirstName, #LastName, #UserName, HASHBYTES('SHA2_512', #Password+CAST(#salt AS NVARCHAR(36))),
#salt, #Age, #Email)
SET #responseMessage='Success'
END TRY
BEGIN CATCH
SET #responseMessage=ERROR_MESSAGE()
END CATCH
END
GO
DECLARE #responseMessage NVARCHAR(250)
EXEC dbo.RestuarantProc #FirstName = 'Bob', #LastName = 'Hudgins', #UserName = 'bobh123', #Password = 'password',
#Age = '23', #Email = 'bob#bob.com', #responseMessage = #responseMessage OUTPUT
SELECT * FROM RestuarantReg
RestuarantProcLogin - Login Procedure
CREATE PROCEDURE RestuarantProcLogin
#userName NVARCHAR(254),
#password NVARCHAR(50),
#responseMessage NVARCHAR(250)='' OUTPUT
AS
BEGIN
SET NOCOUNT ON
DECLARE #userID INT
IF EXISTS (SELECT TOP 1 Id FROM [dbo].[RestuarantReg] WHERE UserName=#userName)
BEGIN
SET #userID=(SELECT Id FROM [dbo].[RestuarantReg]
WHERE UserName=#userName AND
PasswordHash=HASHBYTES('SHA2_512', #password+CAST(PasswordSalt AS NVARCHAR(36))))
IF(#userID IS NULL)
SET #responseMessage='Incorrect password'
ELSE
SET #responseMessage='User successfully logged in'
END
ELSE
SET #responseMessage='Invalid login'
END
DECLARE #responseMessage nvarchar(250)
EXEC dbo.RestuarantProcLogin #userName = N'bobh123', #password = N'password', #responseMessage = #responseMessage OUTPUT
SELECT #responseMessage as N'#responseMessage'
Move the calculation of the hash into a function. Easy to do, easy to maintain, single point of definition. Problem solved if you keep the datastore for your vars the same as your table.

print error if there is a name already in the table

//My code should be something like this
CREATE PROCEDURE REGISTRATION
#USERNAME VARCHAR(20)
AS
BEGIN
BEGIN IF
SELECT USERNAME FROM USERS WHERE USERNAME = #USERNAME
PRINT 'USER ALREADY EXITS'
ELSE
IF #USERNAME = 'NULL'
PRINT 'Fill username'
end
end
Try This :
CREATE PROCEDURE REGISTRATION
#USERNAME VARCHAR(20)
AS
BEGIN
declare #count as int
select #count = COUNT(*) from USER where USERNAME =#USERNAME
if(#count > 0)
print 'USER ALREADY EXITS' -- Record Exists
else
print 'Fill username' -- NULL
end
use exists. Also, formatting gets overlooked and is important
CREATE PROCEDURE REGISTRATION
#USERNAME VARCHAR(20)=''
AS
BEGIN
IF exists(SELECT 1 FROM USERS WHERE USERNAME = #USERNAME)
begin
PRINT 'USER ALREADY EXITS'
end
ELSE
begin
PRINT 'Fill username'
end
end

What's wrong with this Registration stored procedure

I'm trying to make a Registration stored procedure and when I execute the code, I get this error. I've googled it but it's more specific message error was not able to find a solution. what can cause issue here? Thanks in advice!
Error:
Msg 156, Level 15, State 1, Procedure SP_Registration, Line 39 [Batch Start Line 9]
Incorrect syntax near the keyword 'SET'.
This is my stored procedure:
-- =============================================
-- Author: <Nika Kalatozi>
-- Create date: <04/07/2017>
-- Description: <Registration Stored Procedure>
-- =============================================
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[SP_Registration]
#Username NVARCHAR(25),
#Password NVARCHAR(30),
#Email NVARCHAR(35),
#Firstname NVARCHAR(25),
#Lastname NVARCHAR(25),
#Gender NVARCHAR(10),
#Birthdate DATE,
#PhoneNumber NVARCHAR(25),
#PersonalID NVARCHAR(11),
#Result VARCHAR(100) OUTPUT
AS
BEGIN
IF EXISTS(SELECT #Username FROM Users WHERE #Username = #Username)
BEGIN
SET #Result = 'The username you have entered is already in use.'
RETURN;
END
ELSE IF EXISTS(SELECT #Email FROM Users WHERE #Email = #Email)
BEGIN
SET #Result = 'The email you have entered is already in use.'
RETURN;
END
ELSE
BEGIN
INSERT INTO Users(Username, [Password], Email, Firstname, Lastname,
Gender, BirthDate, PhoneNumber, PersonalID)
SET #Result = 'You have been registered successfully.'
RETURN;
END
END
In code
INSERT INTO Users(
...
)
you should specify what to insert:
INSERT INTO Users(
...
) VALUES
(#Username, ...) -- specify values in brakets

SQL Server syntax error Msg:156, Level:15, State:1

I'm trying to alter the following stored procedure, but I am getting a syntax error when I try to alter the procedure.
Msg 156, Level 15, State 1
Incorrect syntax near the keyword 'ELSE'. (Line 24)
Initially, I was executing the InsLoginAttempts incorrectly, but I corrected that.
Microsoft language reference doesn't seem to be any help https://msdn.microsoft.com/en-us/library/ms182717.aspx
SET ANSI_NULLS ON
GO
SET ANSI_NULLS ON
GO
ALTER PROCEDURE dbo.LogInUser
(#UserID varchar(50),
#Password varchar(15)
)
AS
BEGIN
SET NOCOUNT ON
DECLARE #UserExists varchar(50)
SET #UserExists = (SELECT UserID FROM Users WHERE UserID = #UserID)
DECLARE #CheckPassword varchar(15)
SET #CheckPassword = (SELECT Password FROM Users WHERE UserID = #UserID)
BEGIN
IF #UserExists IS NOT NULL
BEGIN
IF #Password = #CheckPassword
SELECT 'True' AS LoggedIn;
EXEC InsLoginAttempts #SPUserID = #UserID, #SPPassword = #Password, #Comment = 'Success';
ELSE
SELECT 'False' AS LoggedIn;
EXEC InsLoginAttempts #SPUserID = #UserID, #SPPassword = #Password, #Comment = 'Failed password attempt';
END
ELSE
SELECT 'False' AS LoggedIn;
EXEC InsLoginAttempts #SPUserID = #UserID, #SPPassword = #Password, #Comment = 'Failed username and password attempt';
END
END
GO
It's obviously a syntax error, but where is it?
EDIT: Also, I don't know if it's worth noting or not, but I'm also using a client called SQLPro for SQL Server.
Your script are missing a BEGIN and END
SET ANSI_NULLS ON
GO
SET ANSI_NULLS ON
GO
ALTER PROCEDURE dbo.LogInUser(
#UserID varchar(50),
#Password varchar(15)
)
AS
BEGIN
SET NOCOUNT ON
DECLARE #UserExists varchar(50)
SET #UserExists = (SELECT UserID FROM Users WHERE UserID = #UserID)
DECLARE #CheckPassword varchar(15)
SET #CheckPassword = (SELECT Password FROM Users WHERE UserID = #UserID)
BEGIN
IF #UserExists IS NOT NULL
BEGIN
IF #Password = #CheckPassword
BEGIN
SELECT 'True' AS LoggedIn;
EXEC InsLoginAttempts #SPUserID = #UserID, #SPPassword = #Password, #Comment = 'Success';
END
ELSE
BEGIN
SELECT 'False' AS LoggedIn;
EXEC InsLoginAttempts #SPUserID = #UserID, #SPPassword = #Password, #Comment = 'Failed password attempt';
END
END
ELSE
BEGIN
SELECT 'False' AS LoggedIn;
EXEC InsLoginAttempts #SPUserID = #UserID, #SPPassword = #Password, #Comment = 'Failed username and password attempt';
END
GO

How to user previous resultset into next query in SQL Server

I want to generate access token if username and password will match in users table. But how can I use previous returned value to next insert query? I have marked missing value with ###I don't know###.
CREATE PROCEDURE [dbo].[GetAccessToken]
#userId varchar(50),
#password varchar(50)
AS
SELECT Id
FROM Users
WHERE UserId = #userId AND Password = #password
IF ##ROWCOUNT != 0
BEGIN
SET #token = NEWID();
INSERT INTO AccessTokens (Token, UserId)
VALUES(CONVERT(varchar(255), #token), ###I Don't Know###)
END
RETURN 0
END
Please help me. Thanks, in advance.
Simply pass the #userId as your second parameter for INSERT
INSERT INTO AccessTokens (Token, UserId)
VALUES(CONVERT(varchar(255), #token), #userId)
Try this:
CREATE PROCEDURE [dbo].[GetAccessToken]
#userId varchar(50),
#password varchar(50)
AS
DECLARE #ID INT
SELECT #ID = Id
FROM Users
WHERE UserId = #userId AND Password = #password
IF (#ID IS NOT NULL )
BEGIN
SET #token = NEWID();
INSERT INTO AccessTokens (Token, UserId)
VALUES(CONVERT(varchar(255), #token), #ID)
RETURN 0
END
Use option with INSERT .. SELECT .. pattern
CREATE PROCEDURE [dbo].[GetAccessToken]
#userId varchar(50),
#password varchar(50)
AS
BEGIN
INSERT INTO AccessTokens (Token, UserId)
SELECT CONVERT(varchar(255), NEWID()), Id
FROM Users
WHERE UserId = #userId AND Password = #password
END

Resources