Skip to content

Rhetos/AspNetFormsAuth

Repository files navigation

AspNetFormsAuth

AspNetFormsAuth is a plugin package for Rhetos development platform. It provides an implementation of ASP.NET Core Identity authentication to Rhetos applications, with recommended security best practices such as password salting and hashing.

This is a backward-compatibility plugin for Rhetos applications that are migrated from ASP.NET to ASP.NET Core on .NET 5 (Rhetos v5). It provides the same authentication web API and database storage of users. Since Rhetos v5, there is technically no need for such plugins: Authentication is managed by ASP.NET Core, so Rhetos does not need to handle user authentication.

For documentation on older versions of this plugin, see previous release branch Readme.md.

Table of contents:

  1. Features
    1. Authentication
    2. Common administration activities
    3. Forgot password
  2. Authentication service API
    1. Login
    2. Logout
    3. SetPassword
    4. ChangeMyPassword
    5. UnlockUser
    6. GeneratePasswordResetToken
    7. SendPasswordResetToken
    8. ResetPassword
  3. Installation and configuration
    1. Hosting web app on IIS
    2. Set up HTTPS
  4. Configuration
    1. Admin user password
    2. Permissions and claims
    3. Maximum failed password attempts
    4. Password strength policy
  5. Sharing the authentication across web applications
  6. Session timeout
  7. Implementing SendPasswordResetToken
    1. Custom implementation
  8. Troubleshooting
  9. How to contribute
    1. Building and testing the source code

Features

Authentication

Common administration activities

  • To create a new user, insert the record in the Common.Principal entity.
  • To configure the user's permissions, enter the data in Common.PrincipalHasRole or Common.PrincipalPermission.
  • To set the user's password, the administrator may use SetPassword or GeneratePasswordResetToken web service methods (see below). The user will later use ResetPassword with the password reset token, or ChangeMyPassword when logged-in.

Forgot password

There are two recommended ways of implementing forgot password functionality with AspNetFormsAuth:

  • Option 1: An administrator (or a web application with administrator privileges) may call GeneratePasswordResetToken web method to get the user's password reset token. The administrator or the web application should then send the token to the user on its own.

  • Option 2: An end user that is not logged-in (or a web application with no special privileges) may call SendPasswordResetToken web method. The Rhetos sever will generate the password reset token and send it to the user. In order to use this method, an implementation of sending the token (by SMS or email, e.g.) should be provided by an additional plugin (see Implementing SendPasswordResetToken).

Authentication service API

The JSON service is available at URI <base URL>/Resources/AspNetFormsAuth/Authentication, with the following methods.

Login

  • Interface: (string UserName, string Password, bool PersistCookie) -> bool
  • Example of the request data: {"UserName":"myusername","Password":"mypassword","PersistCookie":false}.
  • The method does not require user authentication.
  • On successful log in, the server response will contain the standard authentication cookie. The client browser will automatically use the cookie for following requests.
  • Response data is boolean true if the login is successful, false if the login and password does not match, or an error message (string) with HTTP error code 4* or 5* in case of any other error.

Logout

  • No request data is needed, assuming standard authentication cookie is automatically provided. Response is empty.

SetPassword

Sets or resets the given user's password.

  • Interface: (string UserName, string Password, bool IgnorePasswordStrengthPolicy) -> void
  • Requires SetPassword security claim. If IgnorePasswordStrengthPolicy property is set, IgnorePasswordStrengthPolicy security claim is required.
  • Response data is empty if the command is successful, an error message (string) with HTTP error code 400 if the password does not match the password strength policy, or an error message with HTTP error code 4* or 5* in case of any other error.

ChangeMyPassword

Changes the current user's password.

  • Interface: (string OldPassword, string NewPassword) -> bool
  • Response data is boolean true if the login is successful, false if the login and password does not match, an error message (string) with HTTP error code 400 if the password does not match the password strength policy, or an error message with HTTP error code 4* or 5* in case of any other error.

UnlockUser

Reset the number of failed login attempts.

  • Interface: (string UserName) -> void
  • Response is empty.
  • Requires UnlockUser security claim.

GeneratePasswordResetToken

Generates a password reset token.

  • Interface: (string UserName) -> string
  • This method is typically called by an administrator or a web application with administrator privileges in order to create a user account without initial password and let a user choose it, or to implement forgot-password functionality.
  • To implement forgot-password functionality without using administrator privileges in web application, use SendPasswordResetToken method instead (see Forgot password).
  • Requires GeneratePasswordResetToken security claim.
  • To configure the token expiration time, set the DataProtectionTokenProviderOptions.TokenLifespan property inside the Startup.ConfigureServices method of your web application.

SendPasswordResetToken

Generates a password reset token and sends it to the user.

  • Interface: (string UserName, Dictionary<string, string> AdditionalClientInfo) -> void
  • When using this method there is no need to directly call GeneratePasswordResetToken method (see Forgot password).
  • The method does not require user authentication.
  • NOTE: AspNetFormsAuth package does not contain any implementation of sending the token (by SMS or email, e.g.). The implementation must be provided by an additional plugin. For example:
  • To configure the token expiration time, set the DataProtectionTokenProviderOptions.TokenLifespan property inside the Startup.ConfigureServices method of your web application.

ResetPassword

Allows a user to set the initial password or reset the forgotten password, using the token he received previously.

  • Interface: (string userName, string PasswordResetToken, string NewPassword) -> bool
  • See GeneratePasswordResetToken method for PasswordResetToken.
  • The method does not require user authentication.
  • Response data is boolean true if the password change is successful, false if the token is invalid or expired, or an error message (string) with HTTP error code 4* or 5* in case of any other error.

Installation and configuration

  1. Add "Rhetos.AspNetFormsAuth" NuGet package, available at the NuGet.org on-line gallery.

  2. Modify lines in Startup.cs, method ConfigureServices to:

    services.AddRhetos(ConfigureRhetosHostBuilder)
        .AddAspNetFormsAuth();
  3. Add the following lines to Startup.cs, method Configure. Check if some are already there to avoid duplicates. The ordering is important.

    app.UseRhetosAspNetFormsAuth();
    app.UseAuthentication();
    app.UseAuthorization();
  4. Make sure that you don't have this lines in Startup.cs, method Configure:

    services.AddAuthentication(...

Additional remarks:

  • If you want to show authentication APIs in Swagger, add this line in Startup.cs, method Configure:

    app.UseSwaggerUI(c =>
    {
      c.SwaggerEndpoint("/swagger/rhetos/swagger.json", "Rhetos REST API");
    });

Hosting web app on IIS

If you need to host a Rhetos web app with forms authentication on IIS:

  1. You could publish your application by use the feature Publish project in Visual Studio or you also use dotnet cli to publish it instead.
  2. Install latest .NET Core module for IIS.
  3. Create your web application on IIS.
    • Start IIS Manager -> Select the web application -> Open "Authentication" feature, make sure you set this: enable Anonymous Authentication, disable Windows Authentication, Forms Authentication and every other.

Set up HTTPS

HTTPS (or any other) secure transport protocol should always be enforced when using forms authentication. This is necessary because in forms authentication the user's password must be submitted from the client securely. At least the services inside /Resources/AspNetFormsAuth path must use HTTPS.

To enable HTTPS, see Configuring HTTPS in ASP.NET Core and Enforce HTTPS in ASP.NET Core.

Configuration

Admin user password

Note: When deploying the AspNetFormsAuth packages, it will automatically create the admin user account and SecurityAdministrator role, add the account to the role and give it necessary permissions (claims) for all authentication service methods.

After deployment:

  • Run the Rhetos utility AdminSetup.exe in the app's bin folder, to initialize the admin user's password. Run it with command-line argument AdminSetup.exe <your app startup dll>, it will prompt to enter the new admin password.

If needed, AdminSetup can be automated in a script with command-line arguments AdminSetup.exe <your app startup dll> --password <your password> --no-pause

Permissions and claims

All claims related to the authentication service have resource=AspNetFormsAuth.AuthenticationService. Admin user has all the necessary permissions (claims) for all authentication service methods.

Maximum failed password attempts

Password attempt limits and lockout time can be customized in the IdentityOptions.LockoutOptions

Password strength policy

Use entity (database table) Common.AspNetFormsAuthPasswordStrength to configure the password strength policy with one or more regular expressions.

  • A new password must pass all rules entered in the table.
  • RuleDescription is used as an error message to the user if the new password breaks the policy.
  • When administrator executes SetPassword method, the property IgnorePasswordStrengthPolicy may be used to avoid the policy.

Examples:

RegularExpression RuleDescription
.{6,} The password length must be at least six characters.
\d The password must contain at least one digit.
(\d.*){3,} The password must contain at least three digits.
[A-Z] The password must contain at least one uppercase letter.
[a-z] The password must contain at least one lowercase letter.
\W The password must contain at least one special character (not a letter or a digit).

Sharing the authentication across web applications

Sharing the authentication cookie is useful when using separate web applications for web pages and application services, or when using multiple servers for load balancing. In these scenarios, sharing the forms authentication cookie between the sites will allow a single-point login for the user on any of the sites and seamless use of that cookie on the other sites.

You could check official document of Microsoft here Share authentication cookies among ASP.NET apps.

Sharing the authentication with ASP.NET MVC (.NET Framework)

  • In case you have ASP.NET MVC "frontend" apps shared security with Rhetos app, that uses Katana, please see this chapter Share authentication cookies between ASP.NET 4.x and ASP.NET Core apps. This is the example code how to do it:

    // Rhetos app (.NET Core) config
    services.AddRhetos(ConfigureRhetosHostBuilder)
       .AddAspNetFormsAuth();
    
    ...
    
    services.PostConfigureAll<CookieAuthenticationOptions>(options =>
    {
        options.Cookie.Name = ".AspNet.SharedCookie";
        options.Cookie.SameSite = SameSiteMode.Lax;
        options.Cookie.Path = "/";
        options.Cookie.HttpOnly = true;
        options.Cookie.IsEssential = true;
        options.ExpireTimeSpan = TimeSpan.FromMinutes(120);
        options.CookieManager = new ChunkingCookieManager();
        options.TicketDataFormat = new SecureDataFormat<AuthenticationTicket>(
            new TicketSerializer(),
            DataProtectionProvider.Create(
                new DirectoryInfo("C:\\keyring"),
                (builder) => { builder.SetApplicationName("iis-app-name"); }
            ).CreateProtector(
                "Microsoft.AspNetCore.Authentication.Cookies." +
                "CookieAuthenticationMiddleware",
                "Cookies.Application",
                "v2"
            )
        );
    });
    // ASP.NET MVC (.NET Framework) config
    app.UseCookieAuthentication(new CookieAuthenticationOptions()
    {
        AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
        CookieName = ".AspNet.SharedCookie",
        SlidingExpiration = true,
        ExpireTimeSpan = TimeSpan.FromMinutes(120),
        LoginPath = PathString.FromUriComponent("/Account/Login"),
        LogoutPath = PathString.FromUriComponent("/Account/LogOff"),
        CookieManager = new ChunkingCookieManager(),
        TicketDataFormat = new AspNetTicketDataFormat(
            new DataProtectorShim(
                DataProtectionProvider.Create(
                    new DirectoryInfo("C:\\keyring"),
                    (builder) => { builder.SetApplicationName("iis-app-name"); }
                ).CreateProtector(
                    "Microsoft.AspNetCore.Authentication.Cookies." +
                    "CookieAuthenticationMiddleware",
                    "Cookies.Application",
                    "v2"
                )
            )
        )
    });

Session timeout

Configure the ASP.NET Identity authentication ticket timeout with CookieAuthenticationOptions.ExpireTimeSpan. The default value is 14 days.

Implementing SendPasswordResetToken

In order to use SendPasswordResetToken web method (see also Forgot password), an additional plugin must be provided that sends the token to the user (by SMS or email, e.g.).

Custom implementation

In order to implement a custom method of sending the token to the user (by SMS or email, e.g.), create a Rhetos plugin package with a class that implements the Rhetos.AspNetFormsAuth.ISendPasswordResetToken interface from Rhetos.AspNetFormsAuth.Interfaces.dll. The class must use Export attribute to register the plugin implementation. For example, you could check the code here:

[Export(typeof(ISendPasswordResetToken))]
public class EmailSender : ISendPasswordResetToken
{
    ...
}

The AdditionalClientInfo parameter of web service method /SendPasswordResetToken will be provided to the implementation function. The parameter may contain answers to security questions, preferred method of communication or any similar user provided information required by the ISendPasswordResetToken implementation.

The implementation class may throw a Rhetos.UserException or a Rhetos.ClientException to provide an error message to the client, but use it with caution, or better avoid it: The SendPasswordResetToken web service method allows anonymous access, so providing any error information to the client might be a security issue.

Any other exception (Rhetos.FrameworkException, e.g.) will only be logged on the server, but no error will be sent to the client.

Troubleshooting

Issue: Deployment results with error message "DslSyntaxException: Concept with same key is described twice with different values."
Solution: Please check if you have deployed both SimpleWindowsAuth package and AspNetFormsAuth package at the same time. Only one of the packages can be added to a Rhetos app. Read the installation instructions above for more information on the issue.

Issue: Web service responds with error message "The Role Manager feature has not been enabled."
Solution: The error occurs when the necessary modifications of Web.config file are not done. Please check that you have followed the installation instructions above.

Issue: I have accidentally deleted the admin user, SecurityAdministrator role, or some of its permissions. How can I get it back?
Solution: Execute AdminSetup.exe again. It will regenerate the default administration settings. See Admin user password.

Other: In case of a server error, additional information on the error may be found in the Rhetos app's log file (RhetosServer.log for Rhetos v1-v4). If needed, more verbose logging of the authentication service may be switched on by enabling Trace level logger AspNetFormsAuth.AuthenticationService. For example, in Rhetos v1-v4 add <logger name="AspNetFormsAuth.AuthenticationService" minLevel="Trace" writeTo="TraceLog" /> in Rhetos application's web.config, then the trace log will be written to RhetosServerTrace.log.

How to contribute

Contributions are very welcome. The easiest way is to fork this repo, and then make a pull request from your fork. The first time you make a pull request, you may be asked to sign a Contributor Agreement. For more info see How to Contribute on Rhetos wiki.

Building and testing the source code

  • Note: This package is already available at the NuGet.org online gallery. You don't need to build it from source in order to use it in your application.
  • To build the package from source, run Clean.bat, Build.bat and Test.bat.
  • For the test script to work, you need to create an empty database and a settings file test\Rhetos.AspNetFormsAuth.TestApp\rhetos-app.local.settings.json with the database connection string (configuration key "ConnectionStrings:RhetosConnectionString").
  • The build output is a NuGet package in the "Install" subfolder.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages