---
title: "Walkthrough: Creating a login page"
slug: "walkthrough--creating-a-login-page"
abstract: "Learn how to create a form page that enables logging in and out."
---
# Walkthrough: Creating a login page

This topic describes how to create a form page that enables visitors to log in and out on an extranet. This walkthrough is part two of the [Prefilling forms series](https://doc.sitecore.com/xp/en/developers/105/sitecore-experience-manager/prefilling-forms-walkthrough-series.html "Prefilling forms walkthrough series"). To execute the steps of this walkthrough, you must first complete the [Walkthrough: Creating a register page](https://doc.sitecore.com/xp/en/developers/105/sitecore-experience-manager/walkthrough--creating-a-register-page.html "Walkthrough: Creating a register page").

This walkthrough describes how to

- Create a login and logout submit action class
- Create a login action editor control
- Create the login submit action item
- Create the logout submit action item
- Create a login form
- Create a logout form
- Add the form to a webpage

<details>
<summary><h2>Create a login and logout submit action class</h2></summary>

To create the login and logout submit action class:

1. In your Visual Studio Project, go to `SubmitActions` folder. Create a folder named `LoginUser`.
2. In the `LoginUser` folder, create a `LoginUserData` class:

    ```csharp
    public class LoginUserData
     {
     public Guid UserNameFieldId { get; set; }
     public Guid PasswordFieldId { get; set; }
     }
    ```

3. Create a `LoginUser`class:

    ```csharp
    public class LoginUser : SubmitActionBase<LoginUserData>
     {
     public LoginUser(ISubmitActionData submitActionData) : base(submitActionData)
     {
     }

     protected override bool Execute(LoginUserData data, FormSubmitContext formSubmitContext)
     {
     Assert.ArgumentNotNull(data, nameof(data));
     Assert.ArgumentNotNull(formSubmitContext, nameof(formSubmitContext));

     var fields = GetFormFields(data, formSubmitContext);

     Assert.IsNotNull(fields, nameof(fields));

     if (UsernameOrPasswordFieldIsNull(fields))
     {
     return AbortForm(formSubmitContext);
     }

     var values = fields.GetFieldValues();

     if (UsernameOrPasswordValueIsNull(values))
     {
     return AbortForm(formSubmitContext);
     }

     var user = Login(values.Username, values.Password);

     if (user == null)
     {

     return AbortForm(formSubmitContext);
     }

     return true;
     }

     protected virtual User Login(string userName, string password)
     {
     var accountName = string.Empty;
     var domain = Context.Domain;
     if (domain != null)
     {
     accountName = domain.GetFullName(userName);
     }

     var result = AuthenticationManager.Login(accountName, password);
     if (!result)
     {
     return null;
     }

     var user = AuthenticationManager.GetActiveUser();
     return user;
     }

     private LoginUserFormFields GetFormFields(LoginUserData data, FormSubmitContext formSubmitContext)
     {
     Assert.ArgumentNotNull(data, nameof(data));
     Assert.ArgumentNotNull(formSubmitContext, nameof(formSubmitContext));

     return new LoginUserFormFields
     {
     Username = FieldHelper.GetFieldById(data.UserNameFieldId, formSubmitContext.Fields),
     Password = FieldHelper.GetFieldById(data.PasswordFieldId, formSubmitContext.Fields)
     };
     }

     private bool UsernameOrPasswordFieldIsNull(LoginUserFormFields field)
     {
     Assert.ArgumentNotNull(field, nameof(field));
     return field.Username == null || field.Password == null;
     }

     private bool UsernameOrPasswordValueIsNull(LoginUserFieldValues values)
     {
     Assert.ArgumentNotNull(values, nameof(values));
     return string.IsNullOrEmpty(values.Username) || string.IsNullOrEmpty(values.Password);
     }

     private bool AbortForm(FormSubmitContext formSubmitContext)
     {
     formSubmitContext.Abort();
     return false;
     }

     internal class LoginUserFormFields
     {
     public IViewModel Username { get; set; }
     public IViewModel Password { get; set; }

     public LoginUserFieldValues GetFieldValues()
     {
     return new LoginUserFieldValues
     {
     Username = FieldHelper.GetValue(Username),
     Password = FieldHelper.GetValue(Password)
     };
     }
     }

     internal class LoginUserFieldValues
     {
     public string Username { get; set; }
     public string Password { get; set; }
     }
     }
    ```

4. Go to the `SubmitActions` folder and add a folder named `LogoutUser`. In that folder, create the `LogoutUser` class:

    ```csharp
    public class LogoutUser : SubmitActionBase<string>
     {
     public LogoutUser(ISubmitActionData submitActionData) : base(submitActionData)
     {
     }

     protected override bool Execute(string data, FormSubmitContext formSubmitContext)
     {
     Assert.ArgumentNotNull(formSubmitContext, nameof(formSubmitContext));

     Logout();
     return true;
     }

     protected override bool TryParse(string value, out string target)
     {
     target = string.Empty;
     return true;
     }

     protected virtual void Logout()
     {
     AuthenticationManager.GetActiveUser();
     AuthenticationManager.Logout();
     }
     }
    ```

</details>

<details>
<summary><h2>Create a login action editor control</h2></summary>

The next step is to create a `LoginUser` action editor to map the form fields to the`LoginUserData` class.

> [!note]
> To complete this task, you must have the Sitecore Rocks Visual Studio plugin. The plugin is compatible with Visual Studio 2019 or earlier.

To create the `LoginUser` action editor control:

1. Create the JavaScript file for the action editor. In Visual Studio, navigate to the scripts folder and create a JavaScript file named `LoginUser.js`.
2. Copy the following script to the file:

    ```csharp
    (function (speak) {
    	    var parentApp = window.parent.Sitecore.Speak.app.findApplication('EditActionSubAppRenderer'),
    	        designBoardApp = window.parent.Sitecore.Speak.app.findComponent('FormDesignBoard');

    	    var getFields = function () {
    	        var fields = designBoardApp.getFieldsData();

    	        return _.reduce(fields,
    	            function (memo, item) {
    	                if (item && item.model && item.model.hasOwnProperty("value")) {
    	                    memo.push({
    	                        itemId: item.itemId,
    	                        name: item.model.name
    	                    });
    	                }
    	                return memo;
    	            },
    	            [
    	                {
    	                    itemId: '',
    	                    name: ''
    	                }
    	            ],
    	            this);
    	    };

    	    speak.pageCode(["underscore"],
    	        function (_) {
    	            return {
    	                initialized: function () {
    	                    this.on({
    	                        "loaded": this.loadDone
    	                    },
    	                        this);

    	                    this.Fields = getFields();

    	                    this.MapLoginUserForm.children.forEach(function (control) {
    	                        if (control.deps && control.deps.indexOf("bclSelection") !== -1) {
    	                            control.IsSelectionRequired = false;
    	                        }
    	                    });

    	                    if (parentApp) {
    	                        parentApp.loadDone(this, this.HeaderTitle.Text, this.HeaderSubtitle.Text);
    	                        parentApp.setSelectability(this, true);
    	                    }
    	                },

    	                setDynamicData: function (propKey) {
    	                    var componentName = this.MapLoginUserForm.bindingConfigObject[propKey].split(".")[0];
    	                    var component = this.MapLoginUserForm[componentName];

    	                    var items = this.Fields.slice(0);

    	                    if (this.Parameters[propKey] &&
    	                        !_.findWhere(items, { itemId: this.Parameters[propKey] })) {
    	                        var currentField = {
    	                            itemId: this.Parameters[propKey],
    	                            name: this.Parameters[propKey] +
    	                                " - " +
    	                                (this.ValueNotInListText.Text || "value not in the selection list")
    	                        };

    	                        items.splice(1, 0, currentField);

    	                        component.DynamicData = items;
    	                        $(component.el).find('option').eq(1).css("font-style", "italic");
    	                    } else {
    	                        component.DynamicData = items;
    	                    }
    	                },

    	                loadDone: function (parameters) {
    	                    this.Parameters = parameters || {};
    	                    _.keys(this.MapLoginUserForm.bindingConfigObject).forEach(this.setDynamicData.bind(this));
    	                    this.MapLoginUserForm.BindingTarget = this.Parameters;
    	                },

    	                getData: function () {
    	                    var formData = this.MapLoginUserForm.getFormData(),
    	                        keys = _.keys(formData);

    	                    keys.forEach(function (propKey) {
    	                        if (formData[propKey] == null || formData[propKey].length === 0) {
    	                            if (this.Parameters.hasOwnProperty(propKey)) {
    	                                delete this.Parameters[propKey];
    	                            }
    	                        } else {
    	                            this.Parameters[propKey] = formData[propKey];
    	                        }
    	                    }.bind(this));

    	                    return this.Parameters;
    	                }
    	            };
    	        });
    	})(Sitecore.Speak);
    ```

3. Deploy `LoginUser.js` to your website folder at: `YourInstance/Website/sitecore/shell/client/Applications/FormsBuilder/Layouts/Action`.
4. In Sitecore Rocks, expand the core database and go to: `/sitecore/shell/client/Applications/FormsBuilder/Layouts/Actions`.
5. Click **Add**, and click **New item**.
6. In the **Add New Item** dialog box, search for and click the `Speak-BasePage` template, enter the name: *LoginUser*.
7. Update the layout of this item to `/sitecore/client/Speak/Layouts/Layouts/Speak-FlexLayout` and add the following renderings:
    - PageCode
    - HeaderTitle
    - HeaderSubtitle
    - ValueNotinListText
    - MainBorder
    - MapLoginUserForm
8. Open the properties window of the **PageCode** rendering and update the `PageCodeScriptFileName` to: `/sitecore/shell/client/Applications/FormsBuilder/Layouts/Actions/LoginUser.js`
9. Add the parameters based on the templates for the renderings that you have added:

    | Item | Template |
    | --- | --- |
    | Stylesheet | Page-Stylesheet-File |
    | HeaderTitle | Text Parameters |
    | HeaderSubtitle | Text Parameters |
    | MapLoginUserForm | Folder |
    | UserName | FormDropList Parameters |
    | Password | FormDropList Parameters |
    | ValueNotInListText | Text Parameters |

    ![Add parameters](<https://doc.sitecore.com/api/markdown-image/xp/en/developers/105/sitecore-experience-manager/images/IS%20USED%20image2.png>)

10. Update their fields with the following values:

    | Parameter | Field:Values |
    | --- | --- |
    | `Stylesheet` | Stylesheet: `/sitecore/shell/client/Applications/FormsBuilder/Layouts/Actions/Actions.css` |
    | `HeaderTitle` | **IsVisible**: deselect<br><br>**Text**: *Map the fields in the form to the user profile details*. |
    | `HeaderSubtitle` | **IsVisible**: deselected<br><br>**Text**: *Map the fields in the form to the user profile details.* |
    | `UserName` | **ValueFieldName**: itemId<br><br>**DisplayFieldName**: name<br><br>**Form Label**: Username<br><br>**BindingConfiguration**: userNameFieldId / SelectedValue |
    | `Password` | **ValueFieldName**: itemId<br><br>**DisplayFieldName**: name<br><br>**Form Label**: Password<br><br>**BindingConfiguration**: passwordFieldId / SelectedValue |
    | `ValueNotInListText` | **IsVisible**: deselected<br><br>**Text**: *Value not in the selection list* |

</details>

<details>
<summary><h2>Create the login submit action item</h2></summary>

To create the login submit action item:

1. In the Content Editor, go to */system/Settings/Forms/Submit Actions*, insert a `Submit Action` item, and name it *Login User*.
2. Update the fields with the following values:

    | Field | Value |
    | --- | --- |
    | Model Type | ValueProviderSample.SubmitActions.LoginUser |
    | Error Message | Login failed! |
    | Editor | LoginUser |

</details>

<details>
<summary><h2>Create the logout submit action item</h2></summary>

To create the logout submit action item:

1. Insert a submit action item to the `Submit Actions` folder and name it *Logout User*.
2. Update the fields with the following values:

    | Field | Value |
    | --- | --- |
    | **Model Type** | ValueProviderSample.SubmitActions.LogoutUser |
    | **Error Message** | Logout failed! |

    > [!note]
    > Do not forget to save the items.

</details>

<details>
<summary><h2>Create a login form</h2></summary>

To create the login form:

1. Open the Sitecore Forms application from the Sitecore Launchpad.
2. Create a form and add the following sections:

    | Section name | Css class |
    | --- | --- |
    | LoginSection | `form-group col-md-`6 |
    | SubmitSection | `form-group col-md-12` |

3. Add the following fields:

    | Type | Label | Field name | Section |
    | --- | --- | --- | --- |
    | Single-line text | Username | Username | LoginSection |
    | Password | Password | Password | LoginSection |
    | Submit button | Login | Login | SubmitSection |

4. Add the **Login User** submit action to the Login button. Map the form fields accordingly. Then click **OK**.

    ![The login form](<https://doc.sitecore.com/api/markdown-image/xp/en/developers/105/sitecore-experience-manager/images/IS%20USED%20image9.png>)

5. Save the form and name it *Login Form*.

</details>

<details>
<summary><h2>Create a logout form</h2></summary>

To create a logout form:

1. Create a blank form.
2. From the **Form Elements** pane, drag the submit button to the page.
3. Edit the submit button properties with the following values:
    - **Label**: Logout
    - **Field name**: Submit Button
    - **CSS class**: btn btn-link
4. In the **Submit actions** section, add the **Logout User** submit action.
5. Save the form with name *Logout Form*.

</details>

<details>
<summary><h2>Add the form to a webpage</h2></summary>

With the Sitecore Forms application, you can easily create a new form or use a template. You can insert your form in a webpage in both the Content Editor and the Experience Editor. First, you must replace the default sample layout with the MVC layout and then you can insert your form in a webpage.

To add a form to a webpage:

1. Navigate to *sitecore/Content/Home*, and insert a Sample Item. Name it *Login*.
2. Change the `Login` item's default layout to MVC Layout (the MVC layout you created in the [previous walkthrough](https://doc.sitecore.com/xp/en/developers/105/sitecore-experience-manager/walkthrough--creating-a-register-page.html "Walkthrough: Creating a register page").
3. Remove all the sample controls and add the MVC form renderings. Add it to the main placeholder.
4. Edit the MVC form rendering you just added, and update its **Data Source** to *Login Form*.
5. Save and publish the items.

You can now view your login page. Go the [next walkthrough](https://doc.sitecore.com/xp/en/developers/105/sitecore-experience-manager/walkthrough--setting-up-a-value-provider-for-prefilling-forms.html "Walkthrough: Setting up a value provider for prefilling forms") to learn how to set up a value provider.

![The finished login form](<https://doc.sitecore.com/api/markdown-image/xp/en/developers/105/sitecore-experience-manager/images/IS%20USED%20image10.png>)

</details>