The Node.Cs server offer two types of authentication methods, all compatible with the standard implementation of Asp.NET MVC:
The configuration must be set on the node.config file into the Security section. The parameters are
<NodeCsConfiguration> <NodeCsSettings> <Security> <LoginPage>/Account/LogOn</LoginPage> <AuthenticationType>Form</AuthenticationType> <Realm>Node.Cs</Realm> </Security> ...
Other than this the GlobalNodeCs.cs must be modified to specify what service will verify the authentication data, and to add the GlobalAuthorize filter to handle all authorization requests.
This can be made inside the Application_Start method:
public void Application_Start() { ... GlobalVars.AuthenticationDataProvider = new EfAuthenticationDataProvider(() => new MusicStoreEntities()); GlobalVars.GlobalFilters.Add(new GlobalAuthorize()); ...
For this example we are using the EfAuthenticationDataProvider, a database dataprovider based on EntityFramework. Then we add the filter to the global filters.
Inside the NodeCsMusicStore sample all is written clearly but just to give an example with the Form authentication type
A specific "Authorize" attribute as in Asp.NET MVC should be added to the methods or controller needing to be secured. For the controller
[Authorize(Roles = "Administrator")] public class StoreManagerController : ControllerBase, IDisposable {
Or for the method
[Authorize] public IEnumerable<IResponse> Index() {
If not authorized the attribute will redirect to the LogOn page specified inside the settings and inside the controller properties, the property "User" will be set with the current user.
REMEMBER TO ADD THE GlobalAuthorize FILTER!!!
The process is simple, after verifyng that the ModelState has no errors (this check the attributes on the model class).
[HttpPost] public IEnumerable<IResponse> Register(RegisterModel model) { if (ModelState.IsValid) { var authProvider = GlobalVars.AuthenticationDataProvider; // Attempt to register the user AuthenticationCreateStatus createStatus; var user = authProvider.CreateUser(model.UserName, model.Password, model.Email, null, null, true, null, out createStatus); if (createStatus == AuthenticationCreateStatus.Success) { authProvider.AddUsersToRoles(new[] { user.UserName }, new[] { "Administrator" }); Authorize.FormSetAuthCookie(HttpContext, model.UserName, false); yield return RedirectToAction("Index", "Home"); } else { ModelState.AddModelError("", "Unable to create user"); } } // If we got this far, something failed, redisplay form yield return View(model); }
The procedure is more or less the same
[HttpPost] public IEnumerable<IResponse> LogOn(LogOnModel model, string returnUrl) { if (ModelState.IsValid) { var authProvider = GlobalVars.AuthenticationDataProvider; if (authProvider.IsUserAuthorized(model.UserName, model.Password)) { Authorize.FormSetAuthCookie(HttpContext, model.UserName, model.RememberMe); if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\")) { yield return Redirect(returnUrl); } else { yield return RedirectToAction("Index", "Home"); } } else { ModelState.AddModelError("", "The user name or password provided is incorrect."); } } // If we got this far, something failed, redisplay form yield return View(model); }
Simply execute the appropriate signout method for the authorization required
public IEnumerable<IResponse> LogOff() { Authorize.FormSignOut(HttpContext); yield return RedirectToAction("Index", "Home"); }
To have a custom provider for authorization, some interface must be implemented:
IUser, that represents the user. Note that the user MUST know what is its data provider to do the ChangePassword and SetRoles operations
public interface IUser { string UserName { get; } bool ChangePassword(string oldPassword, string newPassword); void SetRoles(params string[] roleNames); }
And the data provider itself. Note that there will be ONE AND ONLY ONE INSTANCE of this class so, be carefule adding instance variables cheking that the will be thread-safe!!
public interface IAuthenticationDataProvider { bool IsUserAuthorized(string user, string password); IUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out AuthenticationCreateStatus status); bool IsUserPresent(string userName); IUser GetUser(string userName, bool isOnLine); void AddUsersToRoles(string[] userNames, string[] roleNames); string[] GetUserRoles(string p); }