In Chapter 5, Creating Applications Using AngularJS, Entity Framework, and ASP.NET Web API, we created the ASP.NET Web API. However, anybody can access our web API if they know the URL. In this section, we will secure our web API. In order to use the ASP.NET Web API, the user must have permission to access the requested data. To implement security in the ASP.NET Web API, we created a table in the Northwind database.
You need to follow these steps to create a table:
CREATE TABLE [dbo].[Members] ( [Id] INT IDENTITY (1, 1) NOT NULL, [Email] NVARCHAR (200) NOT NULL, [Password] NVARCHAR (100) NOT NULL, [CreatedOn] DATETIME NOT NULL, [LastLogedIn] DATETIME NULL, CONSTRAINT [pk_members] PRIMARY KEY CLUSTERED ([Email] ASC, [Password] ASC));
MemberController
and click on Add.[AllowAnonymous]
attribute to the MemberController
and as a result, all the controllers must be declared with the [Authorize]
attribute.System.Web.Security
; create two action methods: login
and RegisterNewMember
, as shown in the following code. In the login
action method, if the member exists in the database table member, we will store the credentials in the form of cookies using FormsAuthentication.SetAuthCookie(email, true)
:[HttpGet] public IHttpActionResult Login(string email, string password) { _db.Configuration.ProxyCreationEnabled = false; var member = _db.Members.FirstOrDefault(m => m.Email == email && m.Password == password); if (member == null) { return NotFound(); } else { FormsAuthentication.SetAuthCookie(email, true); FormsAuthentication.RedirectFromLoginPage(email, false); member.LastLogedIn = DateTime.Now; _db.SaveChanges(); return Ok(); } } [HttpPost] public void RegisterNewMember(Member data) { var member = new Member(); member.Email = data.Email; member.Password = data.Password; member.CreatedOn = DateTime.Now; _db.Members.Add(member); _db.SaveChanges(); }
ctrlMember
that contains three functions: login
, RegisterMember
, and logout
, as shown here:app.controller('ctrlMember', function ($scope, myOperations) { $scope.userAuthentication = 'Fail'; <---------------- AUTHENTICATE USER -------------------- > $scope.login = function (Member) { $('#retrievingDataModal').modal('show'), var error = ''; if ($('#txtEmail').val() == '') { error += 'Email is required, '; } if ($('#txtPassword').val() == '') { error += 'Password is required'; } if ($('#txtEmail').val() != '' && $('#txtPassword').val() != '') { myOperations.Read('/api/Member/Login', { email: Member.Email, password: Member.Password }).success(function (data) { $scope.userAuthentication = 'Pass'; $scope.userEmail = $('#txtEmail').val(); $('#divLayoutMenu').show(); $('#txtEmail').val(''), $('#txtPassword').val(''), $('#retrievingDataModal').modal('hide'), }).error(function (response) { $scope.userAuthentication = 'Fail'; $('#divLayoutMenu').hide(); $('#messageModal').find('#messageModalHeading').empty(); $('#messageModal').find('#messageModalText').empty(); $('#messageModal').find('#messageModalHeading').append('Infromation'), $('#messageModal').find('#messageModalText').text('Check your credentials and try again. If you are not a register user please register first'), $('#messageModal').modal('show'), $('#retrievingDataModal').modal('hide'), }); } else { $('#messageModal').find('#messageModalHeading').empty(); $('#messageModal').find('#messageModalText').empty(); $('#messageModal').find('#messageModalHeading').append('Error'), $('#messageModal').find('#messageModalText').text(error); $('#messageModal').modal('show'), } } <! ----------------- REGISTER NEW MEMEBER ---------------> $scope.RegisterMember = function (NewMember) { var error = ''; if ($('#txtEmail').val() == '') { error += 'Email is required, '; } if ($('#txtPassword').val() == '') { error += 'Password is required'; } if ($('#txtEmail').val() != '' && error == '') { var filter = /^([w-.]+)@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.)|(([w-]+.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(]?)$/; //EMAIL VALIDATION if (filter.test($('#txtEmail').val())) { Operations.Create('/api/Member/RegisterNewMember', NewMember).success(function () { $('#messageModal').modal('hide'), }).error(function () { }); } else { $('#messageModal').find('#messageModalHeading').empty(); $('#messageModal').find('#messageModalText').empty(); $('#messageModal').find('#messageModalHeading').append('Error'), $('#messageModal').find('#messageModalText'). text('Invalid email !!!'), $('#messageModal').modal('show'), } } else { $('#messageModal').find('#messageModalHeading').empty(); $('#messageModal').find('#messageModalText').empty(); $('#messageModal').find('#messageModalHeading').append('Error'), $('#messageModal').find('#messageModalText').text(error); $('#messageModal').modal('show'), } } <! ----------------- LOGOUT -----------------------> $scope.logout = function () { $scope.userAuthentication = 'Fail'; $('.myPage').hide(); $('#Home').show(); $('#divLayoutMenu').hide(); } });
In the client-side code, we need to create a login page which implements the ctrlMember
AngularJS controller.
As you will notice in the very first line of the ctrlMember
controller is $scope.userAuthentication = 'Fail'
. In the beginning, the authentication is Fail
. If the authentication is a success, Pass
is returned by the ASP.NET Web API controller. In the AngularJS ctrlMember
controller, we will change the value of $scope.userAuthentication = 'Pass'
. All the other AngularJS controllers will depend on whether the userAuthentication
value is pass or fail.
web.config
file of the ASP.NET web API:<authentication mode="Forms"></authentication>