Part One: Log in and Registration Screen in PowerApps

Anthony Emmanuel
11 min readAug 6, 2023

--

This is the first of a three-part series on how to create a user-friendly login and registration page in Power Apps. In this first part, we’ll cover the user registration process, which includes the following features:

Password validation:
Ensuring that passwords include uppercase, lowercase, numbers, and symbols.

Unique username and email address:
Making sure that each user has a distinct username and email.

Gmail account requirement:
Allowing only Gmail accounts for registration.

Email confirmation code:
Sending a code for email confirmation that expires after 5 minutes.

Password recovery:
Enabling users to recover their accounts if they forget their passwords.

When should a power app have a login screen?

A Powerapp login screen allows users to enter unique identifier information, usually a username and password before they can access an application. If that username and password validations are correct, then the app will open otherwise it will give a notification error. However, knowing that an Office 365 authentication is required to access the Power Apps portal, it's therefore important to understand why an additional login or registration screen might be useful.

Rejoice Stores is a shopping mall that plans to employ 15 sales personnel who would run different shifts to attend to customers. The management of Rejoice Stores has also decided to build their Purchase Order Application using power apps due to its several benefits. Unfortunately, the need to track activities on the purchase order app would mean that all 15 sales representatives would be provided with individual Office365 user accounts, excluding user accounts for other intended members of staff but this would lead to an increase in overhead cost. However, in a bid to reduce costs, there is an idea to provide all 15 sales representatives with a single Office 365 user account that they can use to access the purchase order and other necessary applications.

In meeting the requirement of Rejoice Stores, there is a need to ensure that the purchase order and every one of their applications must still be able to track every user and essential activity.

New users are required to register or sign up on the app by providing the required information. If this information passes the validation tests, the app navigates to another screen where users are required to confirm their registration using a code sent to their email address. This is to ensure that every user has a valid email for authentication and other activities.

Data Connections

  1. Create a SharePoint List named LoginDemo that stores users' records. Below are the columns to be created. All columns should be a single line of text.
Title //I used sharepoint's title column for the Users FullName
UserName
Password
EmailAddress

2. Add the Gmail connector to power apps.

Steps:

  1. Add two blank screens to the canvas and name the first screen the Home Screen. Paste the below codes in the onVisible and Fill properties of the Home Screen.
1. OnVisible
Set(gblShowErrorImage, false );
ClearCollect(
colMenuTable,
{
Name: "Log in",
Value: 1
},
{
Name: "Register",
Value: 2
},
{
Name: "Forgot Password",
Value: 3
}
);

2. Fill: ColorFade( RGBA(22, 255, 89, 1), 90%)

2. Add a horizontal container to the home screen and set its properties to the values below. This container should cover the entire width and height of the screen.

1. Justify: Center
2. Allign: Center
3. Width: Parent.Width
4. Height: Pparent.Height
5. Gap: 15
6. Fill: Transparent

3. Add two non-responsive containers into the vertical container created in Step 1 and set their properties to the values provided below.

1. Height: 720
2. Align in container: Set by container, Center
3. Flexible width: Off
4. Width: 650
5. All paddings: 0
6. Border radius: 8
7. Drop shadow: Bold

4. Add an HTML Control to the left-sided container and insert the code below into its text property. Set its Height and Width to desired values and add a desired image or background colour for the container background as shown in the image above.

"<div style= 'padding:15px;height:100px; width: "&Parent.Width &"px;  
text-align:center; font-size:4.5em; font-family: Trebuchet MS;
font-weight:900'>Application Registration Demo</div>"

5. Add a blank vertical gallery into the left-sided container as seen above and name it MenuGallery. Also, add a button control to the gallery template and adjust their X and Y properties to achieve a similar appearance to what is displayed above, then use the values provided below to set the other properties.

1. Gallery Items: colMenuTable//The Menu collection in the OnVisibile of the screen. 
//Also navigate away and back to the home screen to initialize the Menu collection

2. Gallery On-Select:
Switch(
ThisItem.Name,
"Log in",
UpdateContext({locPasswordError: false});
Set(
gblBlankEntry,
false
),
"Register",
UpdateContext({locUsernameError: false});
UpdateContext({locPasswordError: false});

)

3. Button Text: ThisItem.Name

4. Button Fill:
ColorFade(
Switch(
ThisItem.Name,
"Log in",
RGBA(
24,
156,
21,
1
),
"Register",
RGBA(
26,
26,
26,
0.6
),
"Forgot Password",
Color.OrangeRed
),
-10%
)

5. Button Border Color:
Switch(
ThisItem.Name,
"Log in",
Self.Fill,
"Register",
Color.White,
"Forgot Password",
Self.Fill
) //Or as desired
6. Button Onselect: Select(Parent)

6. Add a Timer control below the gallery. This would help us display the error icon. Note that the visible property of this control would later be turned off. Use the values provided below to set its property.

1. Duration: 3000
2. Start: gblShowErrorImage
3. OnTimerEnd: Set(gblShowErrorImage, false)

7. Add a vertical container to the right-hand side container that was created above in Step 3 and set its properties to the values below.

1. Direction: Vertical 
2. Justify: Start
3. Align: Center
4. Gap: 8
5. Width: Parent.Width
6. Height: Parent.Height
7. Visible: If(MenuGallery.Selected.Name = "Register", true, false)

8. Add an HTML control to the container created in step 7 using the values provided below for its properties.

1. HTML Text: "<div style= 'padding:5px;height:45px; width: "&Parent.Width &"px;  text-align:center; font-size:2em; font-family: Trebuchet MS; font-weight:900'>Register</div>"
2. Width: Parent.Width
3. Alight in container: Set by container, Center
4. Flexible Height: Off
5. Height: 70
6. Botton Padding: 0
7. Other paddings: 5

9. Add a text label to the container created in step 7. This label would help us indicate the titles of data to be collected. Use the values provided below to set their properties. If done correctly, the text label would appear in a similar position to the one in the image above.

1. Text: Full Name
2. Font: Open sans
3. Font Size: 11.5
4. Font Weight: Semi Bold
5. Width: 550
6. Align in container: Set by container, Center
7. Flexible height: Off
8. Height: 20
9. Left Padding: 0

10. Add a text input control and name it txtFullName. The same properties used in step 9 should also be used for this, except for Height which now equals 50 with a border radius of 5 and a left padding of 12.

11. Copy the text label and text input controls created in steps 9 and 10, and paste them into the container. Name them accordingly using what is displayed below.

Display of text controls with their labels

Below, you would find codes for each text control that allows them to indicate when there is an error. The codes should be placed in the border colour property of their respective text control. Also, since the variables that work with these codes are yet to be declared, they could be commented out until the variables are set.

12. Code for border colour of txtFullName

If(
gblBlankEntry And locPasswordError = false And IsBlank(txtFullName.Text),
Color.Red,
RGBA(
99,
139,
44,
1
)
)

13. Code for border colour of txtUsername

If(
gblBlankEntry And locPasswordError = false And IsBlank(txtUsername.Text),
Color.Red,
If(
locUsernameUsed,
Color.Red,
RGBA(
99,
139,
44,
1
)
)
)

14. Code for border colour of txtEmailAddress

If(
gblBlankEntry And locPasswordError = false || gblInvalidEmail || locEmailUsed,
Color.Red,
RGBA(
99,
139,
44,
1
)
)

15. Code for border colour of txtPassword

If(
locPasswordError,
Color.Red,
If(
locPasswordError = false And gblPasswordsDontMatch,
Color.Red,
RGBA(
99,
139,
44,
1
)
)
)

16. Code for border colour of txtConfirmPassword

If(
locPasswordError,
Color.Red,
If(
locPasswordError = false And gblPasswordsDontMatch,
Color.Red,
RGBA(
99,
139,
44,
1
)
)
)

Again, these codes can be commented out to avoid the distraction created by the errors.

17. To include the error icon/emoji as displayed below, add an HTML control under the previous text controls and input the code provided.

Display of the error icon
1. HTML Text:
If(
gblShowErrorImage,
"<div style= 'padding:5px;height:60px; width: " & Parent.Width & "px; text-align:center; font-size:4em; font-family: Trebuchet MS; font-weight:300'>☹️</div>",
""
)
2. Visible:
If(
gblShowErrorImage,
true,
false
)
3. Width: Parent.Width
4. Font size: 11
5. Height: 95

18. Then add a button control with the properties provided below.

1. DisplayMode: 
If(
Len(txtPassword.Text) < 14,
DisplayMode.Disabled,
If(
IsBlank(txtFullName.Text) ||
IsBlank(txtUsername.Text) ||
IsBlank(txtPassword.Text) ||
IsBlank(txtEmailAddress.Text) ||
IsBlank(txtConfirmPassword.Text),
DisplayMode.Disabled,
DisplayMode.Edit
)
)
2. Onselect Property:
Set(
gblTimeCodeWasSent,
Now()
);
Set(
gblNewUserEmail,
txtEmailAddress.Text
);
Set(
gblNewUserFullName,
txtFullName.Text
);
Set(
gblRegistrationCodeSent,
RandBetween(
111111,
999999
)
);
UpdateContext(
{
locUsernameUsed: !IsBlank(
LookUp(
LoginDemo,
UserName = txtUsername.Text
).UserName
)
}
);
UpdateContext(
{
locEmailUsed: !IsBlank(
LookUp(
LoginDemo,
EmailAddress = txtEmailAddress.Text
).EmailAddress
)
}
);
Set(
gblBlankEntry,
If(
IsBlank(txtFullName.Text) ||
IsBlank(txtUsername.Text) ||
IsBlank(txtPassword.Text) ||
IsBlank(txtConfirmPassword.Text) ||
IsBlank(txtEmailAddress.Text),
true,
false
)
);
Set(
gblPasswordsDontMatch,
If(
txtPassword.Text <> txtConfirmPassword.Text,
true,
false
)
);
Set (
gblInvalidEmail,
If(
IfError(
Gmail.SendEmailV2(
gblNewUserEmail, //checks if the email address is active
{
Subject: "",
Body: ""
}
),
true,
false
) || Right(
txtEmailAddress.Text,
10
) <> "@gmail.com", //confirms if its a gmail account
true,
false
)
);
ClearCollect(
colCheckNumbers,
ForAll(
Split(
txtPassword.Text, //splits the password and checks each character for numbers and then returns the available numbers as a collection
""
),
If(
IsMatch(
Value,
"[0-9]"
),
Value,
""
)
)
);
ClearCollect(
colCheckCapitalLetters,
ForAll(
Split(
txtPassword.Text, //splits the password and checks each character for capital letters and then returns the available capital letters as a collection
""
),
If(
IsMatch(
Value,
"[A-Z]"
),
Value,
""
)
)
);
ClearCollect(
colCheckSmallLetters,
ForAll(
Split(
txtPassword.Text,
""
),
If(
IsMatch(
Value,
"[a-z]" //splits the password and checks each character for small letters and then returns the available small letters as a collection
),
Value,
""
)
)
);

ClearCollect(
colCheckSymbol,
ForAll(
Split(
txtPassword.Text,
""
),
If(
IsMatch(
Value,
"[@,#,$,%,&,?,>,<]" //splits the password and checks each character for any of these symbols and then returns the available symbols as a collection
),
Value,
""
)
)
);
UpdateContext(
{
locPasswordError: (CountRows(
Filter(
colCheckNumbers,
Value
)
) = 0 || CountRows(
Filter(
colCheckCapitalLetters,
Value
)
) = 0 || CountRows(
Filter(
colCheckSmallLetters,
Value
)
) = 0 || CountRows(
Filter(
colCheckSymbol,
Value
)
) = 0)
}
);
If(
locPasswordError,
Notify(
"Password must be a combination of uppercase letters, lowercase letters, numbers and any of these symbols !@#$%^&*>?",
NotificationType.Error,
3000
);
Set(
gblShowErrorImage,
true
),
If(
gblPasswordsDontMatch,
Notify(
"Passwords do not match",
NotificationType.Error,
3000
);
Set(
gblShowErrorImage,
true
),
If(
gblInvalidEmail,
Notify(
"Invalid email address. Please use a valid gmail account",//locEmailUsed
NotificationType.Error,
3000
);
Set(
gblShowErrorImage,
true
),
If(
locEmailUsed,
Notify(
"Email address is not available. Please use another email address",//locEmailUsed
NotificationType.Error,
3000
);
Set(
gblShowErrorImage,
true
),
If(
gblBlankEntry,
Notify(
"All fields are required",
NotificationType.Error,
3000
);
Set(
gblShowErrorImage,
true
),
If(
locUsernameUsed,
Notify(
"Username not available. Try another one",
NotificationType.Error,
3000
);
Set(
gblShowErrorImage,
true
)

)
)
)
)
)
);
If(
locPasswordError || locUsernameUsed || gblInvalidEmail || locEmailUsed || gblPasswordsDontMatch,
false,
If(
gblBlankEntry,
false,
ClearCollect(
colNewUser,
{
Status: "colNewUserRecord",
Name: txtFullName.Text,
UserName: txtUsername.Text,
Email: txtEmailAddress.Text,
Password: txtConfirmPassword.Text
}
);
)
);
If(
locPasswordError = false And gblBlankEntry = false And locUsernameUsed = false And gblPasswordsDontMatch = false And gblInvalidEmail = false And locEmailUsed = false,
Gmail.SendEmailV2(
gblNewUserEmail,
{
Subject: "Complete Registration",
Body: "<div style='background-color: #f5f5f5; width: 650px; height: 400px; border: 2px solid black; padding-bottom: 30px; font-weight:600; color: #0c5c00'>
<div style='background-color: #638b2c ; height: 60px; text-align: center; color: #f5f5f5; font-weight: 900; padding: 15px;font-size:2em; font-family: Trebuchet MS'>
APPLICATION REGISTRATION
</div>
<div style='font-size:2em; font-family: Trebuchet MS; padding: 20px; background-color:#f5f5f5; color: #057f3f'><br> Hello " & gblNewUserFullName & ",<br><br> Please complete your account registration using the code below.
<div style='background-color: #f5f5f5; ; height: 60px; text-align: center; color: #057f3f; font-weight: 900; padding: 15px;font-size:2em; font-family: Trebuchet MS'>
" & gblRegistrationCodeSent & "
</div>
</div>
</div>",
Importance: "Normal"
}
);
Notify(
"You are one step away! Enter the code sent to your email to complete your registration",
NotificationType.Information,
4000
);
Navigate(
'Confirm Registration',
Transition.Push
);

);

19. Add a new screen and name it ‘Confirm Registration’ with a Fill value of ColorFade( RGBA(22, 255, 89, 1), 90%).

Registration confirmation screen

20. Add a vertical container to the new screen and use the values below to set its properties.

1. Direction: Vertical
2. Justify: Start
3. Align: Center
4. Gap: 8
5. Width: 600
6. Height: 700
7. Border radius: 8
8. Drop shadow: 8
9. X: Parent.Width/2 - Self.Width/2
10. Y: Parent.Height/2 - Self.Height/2

21. Add an HTML control for the header and paste the below code into its text property.

1. HTML Text:
"<div style= 'padding:5px;height:45px; width: "&Parent.Width &"px;
text-align:center; font-size:2em; font-family: Trebuchet MS;
font-weight:900'>Enter Code</div>"

2. Height: 75
3. Padding Bottom: 0
4. Other paddings: 5
5. Width: Parent.Width

22. Add a text input control where users would input the confirmation code sent to their email address. Name the input control txtRegistrationCode

1. Flexible width: Off
2. Width: 500
3. Align: By the container, Center
4. Height: 50

//Other propeties can be experimented with

23. The space between the txtRegistrationCode and the Confirm button is just an empty label used to separate the controls. A label or HTML control can be used to achieve this.

24. Add a Button control as seen in the confirm screen image above. The align and width properties are the same as the input text control in step 22. The code for the Onselect property is provided below.

Set(
CodeExpired,
If(
DateDiff(
gblTimeCodeWasSent,
Now(),
TimeUnit.Minutes
) > 5,
true,
false
)
);
Set(
CodeError,
If(
Value(txtRegistrationCode.Text) <> gblRegistrationCodeSent,
true,
false
)
);
If(
CodeExpired,
false;
Notify(
"Code has expired. Click resend for another code",
NotificationType.Error,
4000
),
If(
CodeError,
false;
Notify(
"Incorrect code. Try again",
NotificationType.Error,
4000
),
If(
CodeExpired = false And CodeError = false,
ForAll(
colNewUser,
Patch(
LoginDemo,
Defaults(LoginDemo),
{
Title: Name,
UserName: UserName,
EmailAddress: Email,
Password: Password
}
)
);
Navigate(
'Home Screen',
ScreenTransition.Fade
);
Reset(txtRegistrationCode)
);
Notify(
"Registration successful. Please login",
NotificationType.Information,
3000
)
)
);
Reset(txtFullName);
Reset(txtUsername);
Reset(txtEmailAddress);
Reset(txtPassword);
Reset(txtConfirmPassword);

25. Add another button to resend the registration code. Below is the code for the Onselect property.

Set(
gblTimeCodeWasSent,
Now()
);
Set(
gblRegistrationCodeSent,
RandBetween(
111111,
999999
)
);
Gmail.SendEmailV2(
gblNewUserEmail,
{
Subject: "Complete Registration",
Body: "<div style='background-color: #f5f5f5; width: 650px; height: 400px; border: 2px solid black; padding-bottom: 30px; font-weight:600; color: #0c5c00'>
<div style='background-color: #638b2c ; height: 60px; text-align: center; color: #f5f5f5; font-weight: 900; padding: 15px;font-size:2em; font-family: Trebuchet MS'>
APPLICATION REGISTRATION
</div>
<div style='font-size:2em; font-family: Trebuchet MS; padding: 20px; background-color:#f5f5f5; color: #057f3f'><br> Hello " & gblNewUserFullName & ",<br><br> Please complete your account registration using the code below.
<div style='background-color: #f5f5f5; ; height: 60px; text-align: center; color: #057f3f; font-weight: 900; padding: 15px;font-size:2em; font-family: Trebuchet MS'>
" & gblRegistrationCodeSent & "
</div>
</div>
</div>",
Importance: "Normal"
}
);
Notify(
"A code has been sent to your email",
NotificationType.Information,
4000
);

26. Finally, add another button to navigate users back to the home screen to restart the registration process. A simple navigation function would do this.

Part Two: User Login

https://medium.com/@orisunmibaree/part-two-log-in-and-registration-screen-in-powerapps-eeae2208f0d

--

--