Technical Tip: How to enable open Wifi with captive portal with forced Wifi client disconnect after a period of time
Description
This article describes how to configure an open SSID with disclaimer authentication and enforced disconnect after a timeout, for example, after 3 hours.
Currently, FortiGate supports open authentication with a disclaimer; however, it does not provide an option to enforce a session timeout when using disclaimer-only authentication.
While FortiGate does support authentication timeouts when configured through user groups, this approach requires users to authenticate with credentials. This introduces several challenges:
Users must have accounts created before accessing.
FortiOS does not support self-registration portals for guests.
IT administrators must manually create and distribute guest accounts, which does not scale well and increases operational overhead.
Alternatively, solutions such as FortiNAC can enforce guest session timeouts, but this may be excessive for environments that only require simple guest Wi-Fi with disclaimer-based access.
Scope
FortiLink Managed FortiAP,
Solution
A practical workaround is to configure an open SSID with local user authentication and customize the captive portal (using replacement messages) to mimic disclaimer-based access. In this design:
A 'dummy' guest account is used for backend authentication. No need to share the credentials with guests.
A customized user-facing portal presents a disclaimer-style experience rather than traditional credential input.
This approach allows administrators to leverage authentication-based session timeout controls while maintaining a simplified guest experience that closely resembles disclaimer-only access.
Below are the steps required to achieve the desired outcome:
Configure User Authentication settings.
Change the auth-timeout-type to hard-timeout. Note that a hard-timeout option cannot be applied without user-groups, or only to the captive-portal. When hard-timeout is selected, the timer configured in the group will take precedence.
config user setting
set auth-timeout-type hard-timeout
end
If the network is already using this command, administrators can always create a VDOM for guest users.
Configure a dummy user and a user group.
Create a dummy user with a random password.
config user local
edit captive-user
set passwd randompassword
next
end
Create a local user group and increase the auth timeout to the desired period of time. The timeout has been set to 180 mins/3 hours in this example.
config user group
  edit guest-wifi
set member captive-user
set authtimeout 180
next
end
Configure guest Wifi SSID with captive portal.
Configure a TUNNEL SSID, enable open authentication, and include the local captive portal in the exempted services and destinations so that the Wifi endpoints can reach the captive portal page.

Here is the key captive portal configuration: If the administrator does not see the option to set the security mode to Open, navigate to System -> Feature Visibility and toggle the option Wireless Open Security. Note that the Captive-Portal destination below is set to the IP address of this new SSID interface, which, in this example, is 172.16.100.1/32. The idea behind the Exempt destination/services option is so that wireless guests can navigate to the captive portal using HTTPS and DNS services before accepting the disclaimer. The portal type set to authentication means guest users will be prompted for a username and password by default, but the login page will be customized in the next steps.
Note that as best practice, is recommended to enable the block intra-SSID traffic option to prevent traffic between wireless guests.

For reference, the configuration above will generate the following CLI configuration:
config user security-exempt-list
edit "ACME-Guest-exempt-list"
config rule
edit 1
#This is the SSID Interface IP
set dstaddr "Captive-Portal"
next
edit 2
set service "DNS"
next
edit 3
set service "HTTPS"
next
end
next
end
config wireless-controller vap
edit "ACME-Guest"
set ssid "ACME-Guest"
set security open
set captive-portal enable
set selected-usergroups "guest-wifi"
set security-exempt-list "ACME-Guest-exempt-list"
set security-redirect-url "https://www.fortinet.com"
set intra-vap-privacy enable
set schedule "always"
next
end
Configure firewall policy.
A firewall policy is still required. Administrators can lock guest wifi traffic as needed. As a best practice, guests should only be allowed to go to the internet.
config firewall policy
edit 9
set name "guest-wifi"
set srcintf "ACME-Guest"
set dstintf "port3"
set action accept
set srcaddr "all"
set dstaddr "all"
set schedule "always"
set service "ALL"
set nat enable
next
end
Add guest SSID to AP operation profile.
Navigate to Wifi & Switch Controller -> Operation Profiles. Find the Managed FortiAP Profile and add the Guest SSID to the Operation Profile.

Customize replacement messages.
This is where the magic happens. Customize the Login replacement messages to hide the user credentials but still show the disclaimer so that when the guest selects the Continue button, the form will send the dummy credentials and authenticate endpoint.
Navigate to System -> Replacement Messages, find the Login Page, and select it to customize it. Use the right panel and replace the HTML code with the following:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=8; IE=EDGE">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style type="text/css">
body {
height: 100%;
font-family: Helvetica, Arial, sans-serif;
color: #6a6a6a;
margin: 0;
display: flex;
align-items: center;
justify-content: center;
}
input[type=date], input[type=email], input[type=number], input[type=password], input[type=search], input[type=tel], input[type=text], input[type=time], input[type=url], select, textarea {
color: #262626;
vertical-align: baseline;
margin: .2em;
border-style: solid;
border-width: 1px;
border-color: #a9a9a9;
background-color: #fff;
box-sizing: border-box;
padding: 2px .5em;
appearance: none;
border-radius: 0;
}
input:focus {
border-color: #646464;
box-shadow: 0 0 1px 0 #a2a2a2;
outline: 0;
}
button {
padding: .5em 1em;
border: 1px solid;
border-radius: 3px;
min-width: 6em;
font-weight: 400;
font-size: .8em;
cursor: pointer;
}
button.primary {
color: #fff;
background-color: rgb(47, 113, 178);
border-color: rgb(34, 103, 173);
}
.message-container {
height: 500px;
width: 500px;
padding: 0;
margin: 10px;
}
.logo {
background: url(%%IMAGE:logo_v3_fguard_app%%) no-repeat left center;
height: 267px;
object-fit: contain;
}
table {
background-color: #fff;
border-spacing: 0;
margin: 1em;
}
table > tbody > tr > td:first-of-type:not([colspan]) {
white-space: nowrap;
color: rgba(0,0,0,.5);
}
table > tbody > tr > td:first-of-type {
vertical-align: top;
}
table > tbody > tr > td {
padding: .3em .3em;
}
.field {
display: table-row;
}
.field > :first-child {
display: table-cell;
width: 20%;
}
.field.single > :first-child {
display: inline;
}
.field > :not(:first-child) {
width: auto;
max-width: 100%;
display: inline-flex;
align-items: baseline;
vertical-align: top;
box-sizing: border-box;
margin: .3em;
}
.field > :not(:first-child) > input {
width: 230px;
}
.form-footer {
display: inline-flex;
justify-content: flex-start;
}
.form-footer > * {
margin: 1em;
}
.text-scrollable {
overflow: auto;
height: 150px;
border: 1px solid rgb(200, 200, 200);
padding: 5px;
font-size: 1em;
}
.text-centered {
text-align: center;
}
.text-container {
margin: 1em 1.5em;
}
.flex-container {
display: flex;
}
.flex-container.column {
flex-direction: column;
}
</style>
<title>
Firewall Authentication
</title>
</head>
<body>
<div class="message-container">
<div class="logo">
</div>
<h1>
Terms and Disclaimer Agreement
</h1>
<p class="text-scrollable text-container">
You are about to access Internet content that is not under the control of the network access provider. The network access provider is therefore not responsible for any of these sites, their content or their privacy policies. The network access provider and its staff do not endorse nor make any representations about these sites, or any information, software or other products or materials found there, or any results that may be obtained from using them. If you decide to access any Internet content, you do this entirely at your own risk and you are responsible for ensuring that any accessed material does not infringe the laws governing, but not exhaustively covering, copyright, trademarks, pornography, or any other material which is slanderous, defamatory or might cause offence in any other way.
</p>
<form action="%%AUTH_POST_URL%%" method="post">
<input type="hidden" name="%%REDIRID%%" value="%%PROTURI%%">
<input type="hidden" name="%%MAGICID%%" value="%%MAGICVAL%%">
<input type="hidden" name="%%METHODID%%" value="%%METHODVAL%%">
<p>
%%QUESTION%%
</p>
<div class="field">
<label for="ft_un">
</label>
<div>
<input name="%%USERNAMEID%%" id="ft_un" type="hidden" autocorrect="off" autocapitalize="off" value="captive-user">
</div>
</div>
<div class="field">
<label for="ft_pd">
</label>
<div>
<input name="%%PASSWORDID%%" id="ft_pd" type="hidden" autocomplete="off" value="randompassword">
</div>
</div>
<div class="form-footer">
<button class="primary" type="submit">
Continue
</button>
</div>
</form>
</div>
</body>
</html>
The code above is essentially creating a combination of a disclaimer + login page in a single HTML page. The important fields to note here are the username and the password fields inside the HTML form. Note how the value of the input type parameter has been changed from text and password to 'hidden' so that these do not show in the portal page. Additionally, the value parameter has been manually added to match our dummy user credentials. In this example, username captive-user and password randompassword. Make sure to customize these values.

Note that nothing is preventing a tech-savvy user from discovering these dummy user credentials using the web browser, but even if doing it, the risk is minimal as long as the credentials are not used anywhere else. Plus, intra-SSID traffic has been disabled within the guest SSID.
Solution validation.
Connect to the guest SSID. Guests will see the customized captive portal, and selecting Continue will connect the endpoint to the network.

Finally back on FortiGate, navigate to Dashboard -> Asset and Identities -> Firewall Users and find the user session. If the administrator does not see the 'Time Left', column, mouse over the table header and select the gear icon to customize the table layout.

In the example above, each guest user will automatically disconnect from the guest Wifi after 3 hours. Optionally, administrators can select the user and select 'Deauthenticate' to manually disconnect the endpoint.
