logon page
9 TopicsAPM Advanced Customization Examples with Modern Template, v15.1+
Introduction This guide will walk through how the logon, webtop, and other UI pages are created by APM, how it works, and some examples.The new APM modern template has an updated look in both mobile and desktop browsers. It uses the popular Preact framework to provide a consistent and familiar end user experience. How to activate the new customization system New policies created in 15.1 and later default to the new Modern template. Existing policies made before 15.1 continue to use the Standard template. When creating a new access policy: You can see the customization types applied to all access policies in the Per-Session access policy menu: Customization Sections Basic, General, and Advanced Customization APM has different ways to customize, depending on the desired complexity. Some administrators simply want to change colors, while others would prefer to completely rewrite the APM user-facing HTML and CSS so they have similar branding to other corporate web properties. As is typical with CSS, style customizations can be applied simultaneously with later style changes overriding earlier ones. Basic Customization Simple customization settings such as images, titles, captions, and colors are applied to resources and policies using Basic Customization. The tables and screenshot below detail the settings. Elements in Basic Customization Header/Footer/Title Header Image for Desktop (Max height: 60px) Header Image for Mobile (Max height: 30px) Layout Settings Maximum viewport width for applying small (mobile) screen styles (px) Browser width for mobile clients Minimum viewport width for applying large (desktop) screen styles (px) Browser width for desktop clients Colors (see image for sections) Active Links and Buttons Color Footer Background Color Form Background Color Header Color Page Background Color Solid Button Text Color Text Color Top Strip Color General Customization General Customization offers a more advanced tree view of the Basic Customization settings as well as text options for user-facing messages. Like Basic customization, the settings are applied individually to each access policy and policy item via the item’s XML file specified in the cache-pathparameter of the associated customization group configuration object. To use General Customization Create the policies and/or resources you would like to customize. Find them in the tree view. Make the changes. Perform the standard 3-step save process: Save Draft, Save, then Apply the access policy. You use General Customization to apply changes to the informational text strings and error messages that are displayed to users. Browse the configuration tree to see the available customization areas. The settings are divided into Branding and Text. Text are the localized messages that are displayed to the end users, including associated HTML. User-facing status and text messages can be selected in the Text tab.Branding options are about page styling, colors, fonts, and the like. These are selected in the Branding tab. Special General Options APM customization has a few non-branding and non-text special options in the configuration tree. Disable all external scripts and styles The new Modern customization includes a new resource loader feature. This feature loads all added CSS and JS resources dynamically, including 3 rd party external code. You use this option like a “Revert” to restore the default branding in case there is some unknown trouble. If enabled, it disables loading of all external CSS and JS, including the APM-hosted user-XXXX.js and user-XXXX.css files. External Javascript / CSS You can now easily add external javascript references, for libraries such as JQuery that you wouldlike your users to load from an external CDN. Historically this would present a security problem because the CDN content may be vulnerable to malicious injection. APM uses the W3C subresource integrity feature(https://www.w3.org/TR/SRI/) mechanism to ensure that the external files are not tampered. You can also specify external scripts manually in user-XXXX.js, but using the inbuilt APM script-loader mechanism allows us to trap loading errors and disable all external scripts globally, in case of any problems (see the previous section). To use this feature: Find the checksum* and URL of your resource. jQuery makes this very simple: It’s directly on their CDN page. Alternatively, you can compute them using srihash.org. Place the values into External Scripts / Styles. Save, Apply the access policy, and visit the access policy virtual. *Note*: APM’s end-user pages are built using Preactwith built-in libraries, so don't load another copy of Preact using this mechanism. See the Advanced Examples section below for usage ideas. If the checksum is incorrect the stock APM javascript will function correctly, but the external resource will not be loaded and the browser will produce a “Failed to find a valid digest in the integrity attribute for resource ‘xxxxxx’” error in the console similar to this screenshot: * Supported checksum mechanisms are SHA-256, SHA-384, or SHA-512. Advanced Customization Use Advanced Customization to edit or place code directly into the files that are referenced from the primary APM user-facing HTML. Common settings are available which load on all pages, along with separate CSS and JS for each policy item that is present in the policy. Generally, the CSS/JS for each policy item load after the common settings so later settings will override earlier ones. You must first add policy items to customize before customizing them. This is a customization tree view before and after adding Logon Page to access policy: Before After Operation of Advanced Customization With Advanced Customization, you can do essentially any styling you want using standard CSS. Advanced Customization has some common settings, agent settings, and some special settings. After making any change, Save Draft, then Save., then Apply the access policy. Common settings These two files (user-common.css and user-common.js) are loaded on all* APM user-facing pages, including policy evaluation (logon, message, etc), webtop, and logout. Use these if you want to change a page style in all areas. For example, perhaps we always want to hide the header and footer and add a background image. To do that, we can simply add some CSS to user-common.css to set a few properties targeting the apmui-header, apmui-main, and apmui-footer CSS selectors. Example: logon page customization Hide header and footer, and add a picture: *Note*: You should usually make logon-specific changes on the logon page rather than “common”, since the webtop places some GUI links in apmui-header. Hiding the header removes access to these links! You can useuser-common.jsto load a tracker such as Google Analytics. Example: Google Analytics Customization Types There are two broad categories for the customization of APM objects: Resources areAssigned during per-session access policy execution. They include customizable icons, captions, and descriptions that are visible on the APM full webtop (sometimes called a portal). OAuth Client App OAuth Scope App Tunnel Network Access Remote Desktop SAML Web App (Portal Access) Webtop Link Webtop Section Non-Resourceseach have different configuration properties General Framework Installation EPS Logout (Ending Denied) Error message Decision Box Confirm/Continue Ending Denied Message Box Oauth Authz Webtop Screenshots *Example*: Simple resource customization of a webtop link resource End-User view from APM webtop: Troubleshooting Tips: Configuration Structure Resource customization settings, text strings, and image files are stored as interdependent configuration and file objects. When troubleshooting, check the following configuration areas. This diagram represents the dependencies: This table represents the item details, and troubleshooting tips: NOTE: To create resource customization using scripting or automation, they must be created all at once using a TMSH transaction rather than individually because of the interdependency between resources, profiles, policies, policy items, agents, and customization groups. To get started, use the GUI to create a policy you like, then review the configuration objects defined in tmsh list apm.The objects inter-referred-to must be copied into a transaction. equivalent create apm xxxx commands inside of a transaction. For detail on transactions with APM policies, see tmsh help apm policy access-policy tmsh help cli transaction HTML Rendering Details Access profiles, Per Request Policies and other objects (customized independently from an access profile) share similar syntaxand structure. Each object has customization settings. Access Profiles have multiple groups of customization settings. Every time you change customization, it generates a set of files that are combined to form the user-displayed page. Settings (color, font, text, and so on) for the header and footer can be defined in access profile customization. Settings for the location and alignment of the content area can also be defined in access profile customization. Settings forresourcesdisplayed in the APM Webtop can be defined in the resource's configuration area (see payroll example above). APM Sandbox / Image Hosting To place images or other files in APM for convenient access by end users, use the Hosted Content feature. On a BIG-IP system, on the Main tab, clickAccess > Webtops > Hosted Content > Manage Files. Upload an image file. Click Upload >> Manage Access, and make sure the checkbox for your access policy attached to the virtual server is selected. Access the file at the location indicated in thePublicly Accessible URIcolumn. General Examples Execute external javascript code after Logon Page browser rendering is complete. This example can be placed into user-logon.js to use the D3 library to display a small pop-up message. Additional code can be inserted for custom functions. define(["require", "exports", "tslib", "module", "apmui/page/logon/View"], function (require, exports, tslib_1, module, View_1) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); requirejs.config({ map: { 'apmui/master/View': { 'apmui/page/logon/View': module.id, }, }, }); /* Replacement View component */ var CustomLogonView = /** @class */ (function (_super) { tslib_1.__extends(CustomLogonView, _super); function CustomLogonView() { return _super !== null && _super.apply(this, arguments) || this; } CustomLogonView.prototype.componentDidMount = function () { _super.prototype.componentDidMount.call(this); requirejs(['https://d3js.org/d3.v6.min.js'], function (d3) { // Place your code inside this function d3.select("form").append("span") .text("Hello from D3 library"); }); }; return CustomLogonView; }(View_1.default)); exports.default = CustomLogonView; }); Execute local javascript code inside Logon Page. This example can be placed into user-logon.js to perform custom actions. define(["require", "exports", "tslib", "module", "apmui/page/logon/View"], function (require, exports, tslib_1, module, View_1) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); requirejs.config({ map: { 'apmui/master/View': { 'apmui/page/logon/View': module.id, }, }, }); /* Replacement View component */ var CustomLogonView = /** @class */ (function (_super) { tslib_1.__extends(CustomLogonView, _super); function CustomLogonView() { return _super !== null && _super.apply(this, arguments) || this; } CustomLogonView.prototype.componentDidMount = function () { _super.prototype.componentDidMount.call(this); alert('PLACE CUSTOM CODE HERE'); }; return CustomLogonView; }(View_1.default)); exports.default = CustomLogonView; }); Advanced Examples These use TypeScript and preact You should be familiar with these technologies and their usage. To use these examples, you need a standard TypeScript/NodeJS+NPM build environment. This can be most easily achieved by using Linux, Microsoft Windows Subsystem for Linux (WSL), or Mac, then installing NodeJS which includes NPM. The examples are attached to this article as a ZIP archive. Download and decompress this file to a suitable location on your workstation. Read README.md from the package. Each example here assumes you have already downloaded the package and run npm install; npm run build. The compilation result is placed in the dist directory. For each one of the examples, you simply copy the user-xxxx.css and user-xxxx.js files into the correct object in Advanced Customization. To make changes to these examples, modify the files in src, then npm run build, as specified in README.md. Example 1: Decision box with more options By default, the APM Decision Box has only two choices. We can use this advanced customization example to append additional choices. Follow this procedure: Add a decision box to your access policy. Navigate to customization-examples/dist/decisionBox-more-options and copy the contents of user-decision.js to the appropriate area in Advanced Customization. Click Save Draft, Save, and apply the access policy. As a user, navigate to the decision box on the APM virtual server. Now the decision box has 4 options rather than two. The option and icon detail are in the example user-decision.ts source file: The result: value is the raw POST data, which is transferred from the client browser when the my.policy page is submitted. It must match an agent expression in the branch rules defined for the decision box object. As with all other agents, the branch rules must be defined in the policy-item configuration so that the additional branches are available in the VPE for use: Once these additional branch rules are defined, they can be added to the VPE flow: When a user makes a choice, it appears in log files thusly: To host your own icons, you can use the APM sandbox hosting feature, discussed elsewhere in this doc. Example 2: Logon box custom component This example adds a custom Preactcomponent to the Logon Box. Add a Logon Page to your access policy, then copy the example dist code into your user-logon.js and user-logon.css files. Output: Example 3: Logon custom view This is an example of how to obtain a JSON-formatted dump of data available programmatically. Add the code from logon-custom-view to your APM policy files, then visit the APM virtual. You will see JSON data that provides the detailed data available. Example 4: PIN Pad replaces standard forms logon page This is an example of an alternative method of rendering a standard forms logon page with a polymorphic virtual PIN pad. It uses Preactand CSS to achieve this result. Note: A similar result with a virtual keyboard is possible as well, using other modules available via npm. This requires Preactdevelopment. As with the other examples, compile the TypeScript and place the dist’s user-logon.css and user-logon.js into the APM’s advanced customization area for your logon agent. The result when visiting this logon page is illustrated in this screenshot: Example 5: Validation of input fields logon-validate-domain contains a sample that has an example of input field validation: The input validation logic can be changed with the following TypeScript: This kind of validation logic can be extended for almost any purpose. Example 6: Pin resource to top of webtop Recently-used-resources implements a mechanism that uses local storage to track how many times a resource has been clicked. It also creates a new webtop section that displays most-clicked-on resources. You must have a full webtop and multiple resources assigned to the user (any type is fine). Use this example like the others: Copy the dist directory files user-webtop.css and user-webtop.js to the advanced customization object and click Save Draft, then Save, and apply the access policy. Note that you may have to clear BIG-IP or browser cache to see the update. Take a few minutes to examine the browser's Local Storage contents while clicking various favorites assigned to the user. Example 7: Pin resources on full webtop Most application portals offer some kind of system to save often-used resources at the top of the list. This example uses HTML5 Browser Local Storage to save the user’s resources and render them at the top of the webtop application portal. You must assign a full webtop and multiple resources to the user. Use this example like the others: Copy the dist directory files user-webtop.css and user-webtop.js to the advanced customization object and click Save Draft, then Save, and apply the access policy. Note that you may have to clear BIG-IP or browser cache to see the update. Afterwards, logon as a user to the webtop and click the corner pin icon to add the resource to Pinned Resources. Try to log out and back in and see that the resource(s) are saved. Check the browser developer tools to query the local storage contents. Examples Conclusion We hope these examples are helpful to performing customization of APM web pages. Please let us know of any further examples that you would like to share! Request For Examples We have received the following requests for examples and hope to add these soon. Let us know if you can contribute! Simplest way to add an HTML link and text into the logon page Simplest way to add a select box to a logon page Example virtual keyboard logon page Attributions / Licensing / Support Status Support Status: F5 Support cannot provide assistance with TypeScript, JavaScript, or Preactcoding or web development. To validate the operation of any of these examples, standard web development practices should be used. F5 code: These examples include code produced by F5 intended to showcase the possibilities of the v15.1.0 APM customization system and can be used by any APM customer. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3 rd Party Code: As with most open source software, each module in this example includes a separate license (MIT, CC, etc). Before using any of these in a production environment, please review the licensing requirements for each NPM package in node_modules. Media: Beach scene used in customization examples:Stones in the Beach By Xavierfsc - Own work, CC BY 4.0, https://commons.wikimedia.org/w/index.php?curid=8443060714KViews6likes26Comments[BIG-IP 16.0] APM Logon page and HREF links
Hello everyone, I've been trying to include links to external resources in my APM Logon page. Something in the lines of 'click here' to register with a very simple text and one HTML href reference. I've been messing a little with my configurations and I've got it working pretty easily in BIGIP v13.1 by using HTML tags in General Text customization for Logon page, but the very same edit isn't working as expected in BIG-IP v16.0. I've been reading techdocs and also this very useful article, where was requested an example for this very same problem but it's still marked as an 'open point' to be added. Since I've already spent quite a long time fine-tuning all my access profile's pages, I don't wanna have to do it all again in Standard mode ; also I believe this would be a pretty common problem, so I was wondering if anyone was able to make it work, and please share with me a couple tips on how to. I've tried messing with .js for a while but I confess I'm not very skilled and couldn't find a way to include my simple paragraph. Thanks in advance, CASolved2KViews0likes4CommentsAPM - Provide file at access policy logon page stored on the APM
Hello community, I have to add a download link (help file; .pdf format) to a custom logon page. I could of course place this file on a web server but I'd like to store the file directly on the APM. I've found something about "Hosted content" (http://support.f5.com/kb/en-us/products/big-ip_apm/manuals/product/apm-hosted-content-implementations-11-4-0/1.html) but I really don't know if this is what fits my need and second...we run 11.3 at the moment. Any idea would be appreciated. Best regards, h0nky658Views0likes8CommentsOWA Timeout, Redirect to Logon Page, not BIG-IP Logout page, iRule?
Hello Community, I am looking for an iRule or a way to redirect to the Logon Page when a user session timesout, (specifically for OWA) instead of sending them to the BIG-IP logged off page. I know little about writing iRule (working on getting taking the class), I can read and understand the basics but of course that is like any foreign language :-) I have searched around and have not really found anything, any pointers would be greatly appreciated! Thanks in advance! Thanks! DamonSolved628Views0likes4CommentsAPM Policy - AD Auth Fallback
I have a policy that presents F5 generated Forms logon page. The policy is doing Active Directory authentication. When user enters invalid credentials, the policy does not seem to follow the 'Fallback' branch from the 'AD Auth' item, but rather updates the page with basic message, but remains on the logon page. Where is this logon retry configured at?520Views0likes7Commentscustomize logon page
Hi all - This post from 2014 is what I'm looking for an update for in v 11.5. Is there a way to customize the logon page? It's the same use case as the linked article. We have a general logon page and a subsequent challenge response page. Are there options to customize both logon pages? Think of something along the lines of replacing the out-of-the-boxo F5 pages with something like Google's initial and 2FA logon pages. We do not have a CMS to host the webpage on and are looking to host it locally on the F5. Not sure if this is technically possible but wanted to reach out to see if the F5 community could help. Thanks in advance!338Views0likes5CommentsMultiple Logon Pages (APM) Reset Customisation
We use a custom view for a logon page through a macro on an Access Policy. The custom view changes the logon page to have (1) a single field for entry and (2) a different link that does a loop within the macro (part of our one time password configuration). The problem is that I am trying to add an AD query after this to prompt the user if their password is due to expire. The AD query doesn't present as the normal logon view and configuration is altered by this custom logon page. In order to resolve my issue, I need to add a normal logon page before the AD query to allow the logon page to "reset". The issue with doing this though is that there is user intervention required for them to click on the Logon button. Is there a way to (1) auto click the logon button or (2) reset the logon page via an iRule for example?336Views0likes3CommentsAPM Logon Page Input Field
Is it possible to use the value of a custom session variable in "Logon Page Input Fields"? Instead of showing always the same text I need to show different texts in each session as we are using a grid card for sencond factor authentication and each time the system will ask for the value of two random cells.221Views0likes1CommentAPM Modern Customization - modify Header in user-common.js and form in user-logon.js
Hi! I try to customize the modern logon pages and as I have multiple pages so I want to modify the header section in the user-common.js and the single logon pages in the user-logon.js files. I somehow cannot make it work, currently only the header from user-common.js gets rendered but not the user-logon.js. It seems to me that they interfere with each other the way that I try to do that. user-common.js: define(['require', 'exports', 'tslib', 'module', 'apmui/page/logon/View'], function ( require, exports, tslib_1, module, View_1 ) { 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); requirejs.config({ map: { 'apmui/master/View': { 'apmui/page/logon/View': module.id, }, }, }); /* Replacement View component */ var CustomLogonView = /** @class */ (function (_super) { tslib_1.__extends(CustomLogonView, _super); function CustomLogonView() { return (_super !== null && _super.apply(this, arguments)) || this; } CustomLogonView.prototype.componentDidMount = function () { _super.prototype.componentDidMount.call(this); var header = document.getElementsByClassName('apmui-header')[0]; header.classList.add( 'header', 'sticky', 'top-0', 'left-0', 'z-10', 'w-full', 'box-border', 'flex', 'items-center', 'justify-center', 'text-sm', 'border-b', 'border-b-gray-300', 'dark:border-b-neutral-700' ); header.innerHTML = '<div class="flex flex-col w-full max-w-7xl p-4 gap-4 justify-between"><div class="flex flex-col w-full gap-2 overflow-hidden"><div class="flex flex-row w-full gap-8 select-none"><a class="h-14 pointer-events-none flex flex-shrink-0 place-items-center gap-4 p-8 lg:pointer-events-auto lg:p-0" href="/"><img alt="" loading="lazy" width="185" height="56" decoding="async" data-nimg="1" src="images/logo.svg" style="color: transparent;"></a><span class="flex flex-col flex-grow justify-center text-primary text-3xl font-semibold">PAGE HEADER</span></div></div></div>'; }; return CustomLogonView; })(View_1.default); exports.default = CustomLogonView; }); user-logon.js: define(['require', 'exports', 'tslib', 'module', 'apmui/page/logon/View'], function ( require, exports, tslib_1, module, View_1 ) { 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); requirejs.config({ map: { 'apmui/master/View': { 'apmui/page/logon/View': module.id, }, }, }); /* Replacement View component */ var CustomLogonView = /** @class */ (function (_super) { tslib_1.__extends(CustomLogonView, _super); function CustomLogonView() { return (_super !== null && _super.apply(this, arguments)) || this; } CustomLogonView.prototype.componentDidMount = function () { _super.prototype.componentDidMount.call(this); var content = document.getElementsByClassName('apmui-content')[0]; var content = document.createElement('div'); content.style.cssText = 'max-width: 400px; width: 100%; padding-top: 20px;'; content.innerHTML = "<p>Please register <a href='/register.php'>here</a> if you don't have an account yet.</p>"; }; return CustomLogonView; })(View_1.default); exports.default = CustomLogonView; }); How can I then modify only the header (or footer) via the user-common.js and the logon page content via user-logon.js files? I'm thankful for any advice :) Greetings, Eric20Views0likes2Comments