Cisco Meraki - ExCap - Captive Portal / Splash Page service

Overview

This flow provides an example of the ExCAP interface for delivering a custom Captive Portal / Splash Page for Cisco Meraki access points.

More info about the ExCap API: https://meraki.cisco.com/lib/pdf/meraki_whitepaper_captive_portal.pdf

Usage

Configure the Wi-Fi SSID

Logon to the Meraki Dashboard

Dashboard --> Wireless --> Access Control: (select SSID name from list)

Configure an SSID with a Sign-on or Click-through splash page.

Scroll down the page and enable the "Walled Garden". Enter the IP address of your web server, to provide access to your splash page content prior to authentication. Enter any additional IP addresses for hosted content such as images, terms of service, etc in this section as well.

Configure the Splash Page

Dashboard --> Wireless --> Configure --> Splash Page Select: Use custom URL

Enter the URL for the splash page. This flow provides two options, Sign-on and Click-through.

Sign-on

https://yourserver:1880/excapClick

###Click-through

https://yourserver:1880/excapSignOn

Flow Details

There are several flows to handle the captive portal experience.

Click-through

/excapClick

Initial splash page, pulls login parameters from Meraki and delivers an HTML/CSS webpage

/excapClickLogin

Performs the actual login by using the combined login data and using a 302 redirect so the client performs the authentication.

Sign-on

/excapSignOn

Initial splash page, pulls login parameters from Meraki and delivers an HTML/CSS webpage. It then provides a form where the user will “post” the data to Meraki, which redirects the login to the preferred authentication service such as RADIUS or Meraki Authentication.

/excapSuccess

A simple web page to indicate the user connected successfully. Supporting Pages

/excapTerms

Used to deliver the terms of service /excapNotConnected Displayed if the user has left the Meraki wireless network, but still tried using any of the login pages Notes

Notes

Node-RED is insecure by default, so special care should be made to protect your system and data.

  • Host with SSL

http://industrialinternet.co.uk/node-red/adding-https-ssl-to-node-red/

  • Password protect development/flow view

http://nodered.org/docs/security.html

Written by Cory Guynn, 2015

More great projects at http://www.InternetOfLego.com

[{"id":"bab953a1.e5b8e","type":"debug","z":"58d7d40c.1d422c","name":"excapSignOn raw data","active":true,"console":"false","complete":"payload","x":391,"y":555,"wires":[]},{"id":"f8f01a65.d89488","type":"http in","z":"58d7d40c.1d422c","name":"","url":"/excapSignOn","method":"get","swaggerDoc":"","x":181,"y":485,"wires":[["bab953a1.e5b8e","213a3eb.60a93c2"]]},{"id":"b1194722.ea18f8","type":"http response","z":"58d7d40c.1d422c","name":"","x":783,"y":172,"wires":[]},{"id":"9fbc69d.af2b898","type":"http in","z":"58d7d40c.1d422c","name":"","url":"/excapClick","method":"get","swaggerDoc":"","x":167,"y":172,"wires":[["11c99e84.d3aa81","77c7e451.6a3fdc"]]},{"id":"3b7a443c.f79cdc","type":"http response","z":"58d7d40c.1d422c","name":"","x":770,"y":484,"wires":[]},{"id":"86e6f6ae.922598","type":"template","z":"58d7d40c.1d422c","name":"HTML Login Page","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!DOCTYPE html>\n<html>\n<head>\n{{{payload.css}}}\n\n\n    <meta charset=\"utf-8\">\n    <meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\n    <title>Registration Form</title>\n\n</head>\n<body>\n\n    \n\n\n    <div class=\"main-content\">\n    <form class=\"form-register\" method=POST action={{payload.login_url}} />\n        <input type=\"hidden\" name=\"continue_url\" value={{payload.continue_url}} />\n        <input type=\"hidden\" name=\"host\" value ={{host}}>\n        <input type=\"hidden\" name=\"base_grant_url\" value = {{payload.base_grant_url}}/>\n        <input type=\"hidden\" name=\"user_continue_url\" value = {{payload.user_continue_url}}/>\n        <input type=\"hidden\" name=\"node_mac\" value = {{payload.node_mac}}/>\n        <input type=\"hidden\" name=\"client_ip\" value = {{payload.client_ip}}/>\n        <input type=\"hidden\" name=\"client_mac\" value = {{payload.client_mac}}/>\n        <input type=\"hidden\" name=\"success_url\" value={{payload.continue_url}} />\n\n            <div class=\"form-register-with-email\">\n\n                <div class=\"form-white-background\">\n\n                    <div class=\"form-title-row\">\n                        <h1>Login to WiFi</h1>\n                    </div>\n\n                    <div class=\"form-row\">\n                        <label>\n                            <span>Email</span>\n                            <input type=\"email\" name=\"email\" required>\n                        </label>\n                    </div>\n\n                    <div class=\"form-row\">\n                        <label>\n                            <span>Password</span>\n                            <input type=\"password\" name=\"password\" required>\n                        </label>\n                    </div>\n\n                    <div class=\"form-row\">\n                        <label class=\"form-checkbox\">\n                            <input type=\"checkbox\" name=\"checkbox\" checked value=\"accepted\" required>\n                            <span>I agree to the <a href=\"/excapTerms\" target\"_blank\">terms and conditions</a></span>\n                        </label>\n                    </div>\n\n                    <div class=\"form-row\">\n                        <button type=\"submit\">Register</button>\n                    </div>\n\n                </div>\n\n            </div>\n\n            <!-- Future Social Features\n            <div class=\"form-sign-in-with-social\">\n\n                <div class=\"form-row form-title-row\">\n                    <span class=\"form-title\">Sign in with</span>\n                </div>\n\n                <a href=\"#\" class=\"form-google-button\">Google</a>\n                <a href=\"#\" class=\"form-facebook-button\">Facebook</a>\n                <a href=\"#\" class=\"form-twitter-button\">Twitter</a>\n                \n\n            </div>\n            -->\n\n        </form>\n                Your IP: {{payload.client_ip}}\n                <br>\n                Your MAC: {{payload.client_mac}}\n\n    </div>\n\n</body>\n\n</html>","x":585,"y":500,"wires":[["3b7a443c.f79cdc"]]},{"id":"11c99e84.d3aa81","type":"function","z":"58d7d40c.1d422c","name":"Set login_url","func":"msg.payload.login_url = msg.payload.base_grant_url + '?continue_url=' + msg.payload.user_continue_url;\n\nreturn msg;","outputs":1,"noerr":0,"x":355,"y":172,"wires":[["ee9d29b8.29d768"]]},{"id":"77c7e451.6a3fdc","type":"debug","z":"58d7d40c.1d422c","name":"excapClick raw data","active":true,"console":"false","complete":"payload","x":378,"y":209,"wires":[]},{"id":"7742a638.6a5cd8","type":"comment","z":"58d7d40c.1d422c","name":"Meraki Click-through, read more...","info":"Configure by placing this host server address\nfollowed by /excapClick in the Custom Splash Page URL\nsection of the Meraki Dashboard.\n\nie. https://yourserver:1880/excapClick\n\nBe sure to update the \"walled garden\" in the \nMeraki Dashboard with the IP address of your \nserver and any other resources required before\nlogin, such as your website, images, CSS, etc.\n\nThe HTML page can be modified as needed. \n","x":173,"y":118,"wires":[]},{"id":"68f982df.7a5a8c","type":"comment","z":"58d7d40c.1d422c","name":"Meraki Sign-on, read more...","info":"Configure by placing this host server address\nfollowed by /excapClick in the Custom Splash Page URL\nsection of the Meraki Dashboard.\n\nie. https://yourserver:1880/excapSignOn\n\nBe sure to update the \"walled garden\" in the \nMeraki Dashboard with the IP address of your \nserver and any other resources required before\nlogin, such as your website, images, CSS, etc.\n\n","x":159,"y":435,"wires":[]},{"id":"dce1b1b6.c7232","type":"template","z":"58d7d40c.1d422c","name":"HTML Splash Page","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!DOCTYPE html>\n<html>\n<head>\n{{{payload.css}}}\n\n\n\t<meta charset=\"utf-8\">\n\t<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\">\n\t<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\n\t<title>Registration Form</title>\n\n</head>\n<body>\n\n\t\n\n\n    <div class=\"main-content\">\n\n        <form class=\"form-register\" method=POST action=\"/excapClickLogin\">\n                <input type=\"hidden\" name=\"continue_url\" value={{payload.continue_url}} />\n                <input type=\"hidden\" name=\"host\" value ={{host}}>\n                <input type=\"hidden\" name=\"base_grant_url\" value = {{payload.base_grant_url}}/>\n                <input type=\"hidden\" name=\"user_continue_url\" value = {{payload.user_continue_url}}/>\n                <input type=\"hidden\" name=\"node_mac\" value = {{payload.node_mac}}/>\n                <input type=\"hidden\" name=\"client_ip\" value = {{payload.client_ip}}/>\n                <input type=\"hidden\" name=\"client_mac\" value = {{payload.client_mac}}/>\n            \n            <div class=\"form-register-with-email\">\n\n                <div class=\"form-white-background\">\n\n                    <div class=\"form-title-row\">\n                        <h1>Login to WiFi</h1>\n                    </div>\n\n                    <div class=\"form-row\">\n                        <label>\n                            <span>Name</span>\n                            <input type=\"text\" name=\"name\" required>\n                        </label>\n                    </div>\n\n                    <div class=\"form-row\">\n                        <label>\n                            <span>Email</span>\n                            <input type=\"email\" name=\"email\" required>\n                        </label>\n                    </div>\n\n                    <div class=\"form-row\">\n                        <label class=\"form-checkbox\">\n                            <input type=\"checkbox\" name=\"checkbox\" checked value=\"accepted\" required>\n                            <span>I agree to the <a href=\"/excapTerms\" target\"_blank\">terms and conditions</a></span>\n                        </label>\n                    </div>\n\n                    <div class=\"form-row\">\n                        <button type=\"submit\">Register</button>\n                    </div>\n\n                </div>\n\n            </div>\n\n            <!-- Future Social Features\n            <div class=\"form-sign-in-with-social\">\n\n                <div class=\"form-row form-title-row\">\n                    <span class=\"form-title\">Sign in with</span>\n                </div>\n\n                <a href=\"#\" class=\"form-google-button\">Google</a>\n                <a href=\"#\" class=\"form-facebook-button\">Facebook</a>\n                <a href=\"#\" class=\"form-twitter-button\">Twitter</a>\n                \n\n            </div>\n            -->\n\n        </form>\n                Your IP: {{payload.client_ip}}\n                <br>\n                Your MAC: {{payload.client_mac}}\n\n    </div>\n\n</body>\n\n</html>\n\n","x":616,"y":172,"wires":[["b1194722.ea18f8"]]},{"id":"47dd6060.3121f","type":"http in","z":"58d7d40c.1d422c","name":"","url":"/excapClickLogin","method":"post","swaggerDoc":"","x":256,"y":277,"wires":[["1fb28772.03d4a9","5e36894f.fc09f8"]]},{"id":"1fb28772.03d4a9","type":"function","z":"58d7d40c.1d422c","name":"Process login with 302 redirect","func":"// check if client has connected properly and received response from AP\nif (msg.payload.base_grant_url){\n    msg.statusCode = 302;\n    msg.headers = {\n      'Location': msg.payload.base_grant_url + '?continue_url=' + msg.payload.user_continue_url\n      //add other headers here...\n    };\n}else{\n    // error: send client back to login\n    msg.statusCode = 302;\n    msg.headers = {\n      'Location': '/excapNotConnected'\n      //add other headers here...\n    };\n}\n\nreturn msg;","outputs":1,"noerr":0,"x":531,"y":277,"wires":[["d77739fa.b4fa68","faeaccef.f8801"]]},{"id":"d77739fa.b4fa68","type":"http response","z":"58d7d40c.1d422c","name":"","x":773,"y":277,"wires":[]},{"id":"5e36894f.fc09f8","type":"debug","z":"58d7d40c.1d422c","name":"excapClick session data to console","active":true,"console":"false","complete":"payload","x":564.9999847412109,"y":356.0000114440918,"wires":[]},{"id":"f241c131.5a044","type":"comment","z":"58d7d40c.1d422c","name":"Store form data - read more...","info":"Instead of the debug console output, export\nthe form/session data to a database, file, etc.","x":519,"y":323,"wires":[]},{"id":"62b79ca4.bb2294","type":"comment","z":"58d7d40c.1d422c","name":"Terms and Conditions","info":"","x":144,"y":789,"wires":[]},{"id":"9d005fa6.b3913","type":"comment","z":"58d7d40c.1d422c","name":"Success","info":"","x":106,"y":577,"wires":[]},{"id":"e4bd15bc.35ce78","type":"http in","z":"58d7d40c.1d422c","name":"","url":"/excapTerms","method":"get","swaggerDoc":"","x":204,"y":828,"wires":[["27811e1a.685ad2"]]},{"id":"bde2a374.2a2a","type":"http response","z":"58d7d40c.1d422c","name":"","x":786,"y":828,"wires":[]},{"id":"cb1ea20c.28c48","type":"template","z":"58d7d40c.1d422c","name":"HTML Terms and Conditions","field":"payload","format":"handlebars","template":"<head>\n    <title>Terms and Conditions</title>\n{{{payload}}}\n</head>\n<body>\n    <div class=\"container\">\n    <h1>Terms and Conditions</h1>\n    <ul>\n        <li>Please use our network responsibly. </li>\n        <li>Your computer's MAC and IP address will be logged.</li>\n    </ul>\n    </div>\n</body>\n\n\n","x":555,"y":828,"wires":[["bde2a374.2a2a"]]},{"id":"3ab1c14.66e893e","type":"http in","z":"58d7d40c.1d422c","name":"","url":"/excapSuccess","method":"get","swaggerDoc":"","x":184,"y":632,"wires":[["3ebb91b2.3af17e"]]},{"id":"111baab0.1bda75","type":"http response","z":"58d7d40c.1d422c","name":"","x":773,"y":632,"wires":[]},{"id":"22d885ae.2984ea","type":"template","z":"58d7d40c.1d422c","name":"HTML Success","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<head>\n    <title>Success!</title>\n{{{payload.css}}}\n</head>\n<body>\n    <div class=\"container\">\n    <center><h1>Success!</h1>\n    <h2>You can now use the network.</h2>\n    </center>\n    </div>\n</body>\n\n\n","x":567,"y":632,"wires":[["111baab0.1bda75"]]},{"id":"555cc27d.3c976c","type":"comment","z":"58d7d40c.1d422c","name":"Error: Not connected to AP","info":"","x":160,"y":912,"wires":[]},{"id":"88d8f11b.34c17","type":"http in","z":"58d7d40c.1d422c","name":"","url":"/excapNotConnected","method":"get","swaggerDoc":"","x":205,"y":985,"wires":[["40f3da2d.f3cd84"]]},{"id":"a1ea8923.d36ac8","type":"http response","z":"58d7d40c.1d422c","name":"","x":787,"y":985,"wires":[]},{"id":"b27f59c.a2e41a8","type":"template","z":"58d7d40c.1d422c","name":"HTML Terms and Conditions","field":"payload","format":"handlebars","template":"<head>\n    <title>Error: Not Connected</title>\n{{{payload}}}\n</head>\n<body>\n    <div class=\"container\">\n    <h1>Error: Not Connected</h1>\n    <p>\n        Hmm, somethings not right. It appears you\n        are not connected to the correct wireless network.\n    </p>\n    </div>\n</body>\n\n\n","x":556,"y":985,"wires":[["a1ea8923.d36ac8"]]},{"id":"1bdcc059.255dd","type":"comment","z":"58d7d40c.1d422c","name":"Cisco Meraki ExCap Service - by Cory Guynn","info":"More information about the Meraki ExCap API:\nhttps://meraki.cisco.com/lib/pdf/meraki_whitepaper_captive_portal.pdf\n\nEnjoy!\n\nWritten by Cory Guynn, 2015.\nConsulting Engineer @ https://meraki.cisco.com/\nTechnical Blogger @ http://www.InternetOfLego.com","x":488.5,"y":70,"wires":[]},{"id":"ee9d29b8.29d768","type":"template","z":"58d7d40c.1d422c","name":"CSS Style","field":"payload.css","fieldType":"msg","format":"html","syntax":"mustache","template":"<style>\nhtml{\n    background-color: #f3f3f3;\n}\n\n.form-register{\n    max-width: 1000px;\n    width: 100%;\n    margin: 0 auto;\n\n    font: bold 14px sans-serif;\n    text-align: center;\n}\n\n.form-register-with-email{\n    position: relative;\n    display: inline-block;\n    vertical-align: top;\n    margin-right: 130px;\n    text-align: center;\n}\n\n.form-register-with-email .form-white-background{\n    width: 570px;\n    box-sizing: border-box;\n    background-color: #ffffff;\n    box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);\n    padding: 60px 80px;\n    margin-bottom: 35px;\n}\n\n.form-register-with-email .form-row{\n    text-align: left;\n    margin-bottom: 23px;\n}\n\n.form-register-with-email .form-title-row{\n    text-align: center;\n    margin-bottom: 50px;\n}\n\n.form-register-with-email h1{\n    display: inline-block;\n    box-sizing: border-box;\n    color:  #4c565e;\n    font-size: 24px;\n    padding: 0 20px 15px;\n    border-bottom: 2px solid #6caee0;\n    margin: 0;\n}\n\n.form-register-with-email .form-row > label span{\n    display: inline-block;\n    box-sizing: border-box;\n    color:  #5f5f5f;\n    width: 125px;\n    text-align: right;\n    padding-right: 25px;\n}\n\n.form-register-with-email input{\n    color:  #5f5f5f;\n    box-sizing: border-box;\n    width: 230px;\n    box-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.08);\n    padding: 12px 18px;\n    border: 1px solid #dbdbdb;\n}\n\n.form-register-with-email .form-checkbox input{\n    margin-left: 128px;\n    margin-right: 10px;\n    width: auto;\n    vertical-align: top;\n}\n\n.form-register-with-email .form-row .form-checkbox span{\n    font-size: 12px;\n    font-weight: normal;\n    display: inline-block;\n    text-align: left;\n    width: 220px;\n    margin: 0;\n}\n\n.form-register-with-email .form-checkbox span a{\n    text-decoration: none;\n    color:  #6caee0;\n}\n\n.form-register-with-email button{\n    display: block;\n    border-radius: 2px;\n    background-color:  #6caee0;\n    color: #ffffff;\n    font-weight: bold;\n    box-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.08);\n    padding: 15px 35px;\n    border: 0;\n    margin: 55px auto 0;\n    cursor: pointer;\n}\n\n.form-register-with-email .form-log-in-with-existing{\n    text-decoration: none;\n    padding: 4px 8px;\n    font-weight: normal;\n    color: #7b9d62;\n    background-color: #d6f0c3;\n}\n\n\n.form-sign-in-with-social{\n    display: inline-block;\n    max-width: 180px;\n    box-sizing: border-box;\n    vertical-align: top;\n    text-align: center;\n    margin-top: 100px;\n}\n\n.form-sign-in-with-social .form-title-row{\n    margin-bottom: 50px;\n}\n\n.form-sign-in-with-social .form-title{\n    box-sizing: border-box;\n    color:  #4c565e;\n    font-size: 24px;\n    padding: 15px 20px;\n    border-bottom: 2px solid #6caee0;\n}\n\n.form-sign-in-with-social .form-google-button{\n    color:  #ffffff;\n    display: block;\n    width: 145px;\n    height: 40px;\n    font-size: 12px;\n    line-height: 40px;\n    background-color:  rgba(222, 110, 60, 0.9);\n    box-shadow: 1px 2px 2px 0 rgba(0, 0, 0, 0.08);\n    border-radius: 2px;\n    margin: 8px auto;\n    text-decoration: none;\n}\n\n.form-sign-in-with-social .form-facebook-button{\n    color:  #ffffff;\n    display: block;\n    width: 145px;\n    height: 40px;\n    font-size: 12px;\n    line-height: 40px;\n    background-color:  rgba(75, 136, 194, 0.9);\n    box-shadow: 1px 2px 2px 0 rgba(0, 0, 0, 0.08);\n    border-radius: 2px;\n    margin: 8px auto;\n    text-decoration: none;\n}\n\n.form-sign-in-with-social .form-twitter-button{\n    color:  #ffffff;\n    display: block;\n    width: 145px;\n    height: 40px;\n    font-size: 12px;\n    line-height: 40px;\n    background-color:  rgba(123, 195, 226, 0.9);\n    box-shadow: 1px 2px 2px 0 rgba(0, 0, 0, 0.08);\n    border-radius: 2px;\n    margin: 8px auto;\n    text-decoration: none;\n}\n\n/*\tMaking the form responsive. Remove these media queries\n    if you don't need the form to work on mobile devices. */\n\[email protected] (max-width: 900px) {\n\n    .form-register{\n        margin: 20px auto;\n    }\n\n    .form-register-with-email{\n        position: relative;\n        display: block;\n        margin: 0;\n    }\n\n    .form-register-with-email .form-white-background{\n        margin: 0 auto 32px;\n    }\n\n\n\n    .form-sign-in-with-social {\n        margin-top: 105px;\n    }\n\n}\n\[email protected] (max-width: 600px) {\n\n    .form-register-with-email .form-white-background{\n        width: 300px;\n        padding-left: 35px;\n        padding-right: 35px;\n    }\n\n    .form-register-with-email .form-row > label span{\n        display: block;\n        text-align: left;\n        padding: 0 0 10px;\n    }\n\n    .form-register-with-email input{\n        display: block;\n        margin: 0 auto;\n    }\n\n    .form-register-with-email .form-checkbox input{\n        display: inline-block;\n        margin-left: 0;\n    }\n\n    .form-register-with-email .form-checkbox span{\n        width: 200px !important;\n    }\n\n    .form-register-with-email:after{\n        bottom: -80px;\n        left: 50%;\n        margin-left: -25px;\n    }\n\n}\n</style>","x":591.5,"y":136,"wires":[["dce1b1b6.c7232"]]},{"id":"213a3eb.60a93c2","type":"template","z":"58d7d40c.1d422c","name":"CSS Style","field":"payload.css","fieldType":"msg","format":"html","syntax":"mustache","template":"<style>\nhtml{\n    background-color: #f3f3f3;\n}\n\n.form-register{\n    max-width: 1000px;\n    width: 100%;\n    margin: 0 auto;\n\n    font: bold 14px sans-serif;\n    text-align: center;\n}\n\n.form-register-with-email{\n    position: relative;\n    display: inline-block;\n    vertical-align: top;\n    margin-right: 130px;\n    text-align: center;\n}\n\n.form-register-with-email .form-white-background{\n    width: 570px;\n    box-sizing: border-box;\n    background-color: #ffffff;\n    box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1);\n    padding: 60px 80px;\n    margin-bottom: 35px;\n}\n\n.form-register-with-email .form-row{\n    text-align: left;\n    margin-bottom: 23px;\n}\n\n.form-register-with-email .form-title-row{\n    text-align: center;\n    margin-bottom: 50px;\n}\n\n.form-register-with-email h1{\n    display: inline-block;\n    box-sizing: border-box;\n    color:  #4c565e;\n    font-size: 24px;\n    padding: 0 20px 15px;\n    border-bottom: 2px solid #6caee0;\n    margin: 0;\n}\n\n.form-register-with-email .form-row > label span{\n    display: inline-block;\n    box-sizing: border-box;\n    color:  #5f5f5f;\n    width: 125px;\n    text-align: right;\n    padding-right: 25px;\n}\n\n.form-register-with-email input{\n    color:  #5f5f5f;\n    box-sizing: border-box;\n    width: 230px;\n    box-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.08);\n    padding: 12px 18px;\n    border: 1px solid #dbdbdb;\n}\n\n.form-register-with-email .form-checkbox input{\n    margin-left: 128px;\n    margin-right: 10px;\n    width: auto;\n    vertical-align: top;\n}\n\n.form-register-with-email .form-row .form-checkbox span{\n    font-size: 12px;\n    font-weight: normal;\n    display: inline-block;\n    text-align: left;\n    width: 220px;\n    margin: 0;\n}\n\n.form-register-with-email .form-checkbox span a{\n    text-decoration: none;\n    color:  #6caee0;\n}\n\n.form-register-with-email button{\n    display: block;\n    border-radius: 2px;\n    background-color:  #6caee0;\n    color: #ffffff;\n    font-weight: bold;\n    box-shadow: 1px 2px 4px 0 rgba(0, 0, 0, 0.08);\n    padding: 15px 35px;\n    border: 0;\n    margin: 55px auto 0;\n    cursor: pointer;\n}\n\n.form-register-with-email .form-log-in-with-existing{\n    text-decoration: none;\n    padding: 4px 8px;\n    font-weight: normal;\n    color: #7b9d62;\n    background-color: #d6f0c3;\n}\n\n\n.form-sign-in-with-social{\n    display: inline-block;\n    max-width: 180px;\n    box-sizing: border-box;\n    vertical-align: top;\n    text-align: center;\n    margin-top: 100px;\n}\n\n.form-sign-in-with-social .form-title-row{\n    margin-bottom: 50px;\n}\n\n.form-sign-in-with-social .form-title{\n    box-sizing: border-box;\n    color:  #4c565e;\n    font-size: 24px;\n    padding: 15px 20px;\n    border-bottom: 2px solid #6caee0;\n}\n\n.form-sign-in-with-social .form-google-button{\n    color:  #ffffff;\n    display: block;\n    width: 145px;\n    height: 40px;\n    font-size: 12px;\n    line-height: 40px;\n    background-color:  rgba(222, 110, 60, 0.9);\n    box-shadow: 1px 2px 2px 0 rgba(0, 0, 0, 0.08);\n    border-radius: 2px;\n    margin: 8px auto;\n    text-decoration: none;\n}\n\n.form-sign-in-with-social .form-facebook-button{\n    color:  #ffffff;\n    display: block;\n    width: 145px;\n    height: 40px;\n    font-size: 12px;\n    line-height: 40px;\n    background-color:  rgba(75, 136, 194, 0.9);\n    box-shadow: 1px 2px 2px 0 rgba(0, 0, 0, 0.08);\n    border-radius: 2px;\n    margin: 8px auto;\n    text-decoration: none;\n}\n\n.form-sign-in-with-social .form-twitter-button{\n    color:  #ffffff;\n    display: block;\n    width: 145px;\n    height: 40px;\n    font-size: 12px;\n    line-height: 40px;\n    background-color:  rgba(123, 195, 226, 0.9);\n    box-shadow: 1px 2px 2px 0 rgba(0, 0, 0, 0.08);\n    border-radius: 2px;\n    margin: 8px auto;\n    text-decoration: none;\n}\n\n/*\tMaking the form responsive. Remove these media queries\n    if you don't need the form to work on mobile devices. */\n\[email protected] (max-width: 900px) {\n\n    .form-register{\n        margin: 20px auto;\n    }\n\n    .form-register-with-email{\n        position: relative;\n        display: block;\n        margin: 0;\n    }\n\n    .form-register-with-email .form-white-background{\n        margin: 0 auto 32px;\n    }\n\n\n\n    .form-sign-in-with-social {\n        margin-top: 105px;\n    }\n\n}\n\[email protected] (max-width: 600px) {\n\n    .form-register-with-email .form-white-background{\n        width: 300px;\n        padding-left: 35px;\n        padding-right: 35px;\n    }\n\n    .form-register-with-email .form-row > label span{\n        display: block;\n        text-align: left;\n        padding: 0 0 10px;\n    }\n\n    .form-register-with-email input{\n        display: block;\n        margin: 0 auto;\n    }\n\n    .form-register-with-email .form-checkbox input{\n        display: inline-block;\n        margin-left: 0;\n    }\n\n    .form-register-with-email .form-checkbox span{\n        width: 200px !important;\n    }\n\n    .form-register-with-email:after{\n        bottom: -80px;\n        left: 50%;\n        margin-left: -25px;\n    }\n\n}\n</style>","x":562,"y":462,"wires":[["86e6f6ae.922598"]]},{"id":"3ebb91b2.3af17e","type":"template","z":"58d7d40c.1d422c","name":"CSS Style","field":"payload.css","fieldType":"msg","format":"html","syntax":"mustache","template":"<style type=\"text/css\">\n.container{\n    max-width: 500px;\n    padding: 10px 20px;\n    background: #f4f7f8;\n    margin: 10px auto;\n    padding: 20px;\n    background: #f4f7f8;\n    border-radius: 8px;\n    font-family: Georgia, \"Times New Roman\", Times, serif;\n}\n</style>","x":551,"y":594,"wires":[["22d885ae.2984ea"]]},{"id":"27811e1a.685ad2","type":"template","z":"58d7d40c.1d422c","name":"CSS Style","field":"payload","format":"html","template":"<style type=\"text/css\">\n.container{\n    max-width: 500px;\n    padding: 10px 20px;\n    background: #f4f7f8;\n    margin: 10px auto;\n    padding: 20px;\n    background: #f4f7f8;\n    border-radius: 8px;\n    font-family: Georgia, \"Times New Roman\", Times, serif;\n}\n</style>","x":499,"y":786,"wires":[["cb1ea20c.28c48"]]},{"id":"40f3da2d.f3cd84","type":"template","z":"58d7d40c.1d422c","name":"CSS Style","field":"payload","format":"html","template":"<style type=\"text/css\">\n.container{\n    max-width: 500px;\n    padding: 10px 20px;\n    background: #f4f7f8;\n    margin: 10px auto;\n    padding: 20px;\n    background: #f4f7f8;\n    border-radius: 8px;\n    font-family: Georgia, \"Times New Roman\", Times, serif;\n}\n</style>","x":500,"y":948,"wires":[["b27f59c.a2e41a8"]]},{"id":"c4171b52.9a08f8","type":"comment","z":"58d7d40c.1d422c","name":"Supporting Pages","info":"","x":95,"y":728,"wires":[]},{"id":"faeaccef.f8801","type":"debug","z":"58d7d40c.1d422c","name":"Process Login","active":true,"console":"false","complete":"payload","x":739.8957977294922,"y":317.3333549499512,"wires":[]}]
dexterlabora

Flow Info

created 1 year, 10 months ago
updated 1 year ago

Node Types

Core
  • comment (x8)
  • debug (x4)
  • function (x2)
  • http in (x6)
  • http response (x6)
  • template (x10)

Tags

  • cisco
  • meraki
  • excap
  • splash
  • captive
  • portal
  • wifi
  • cloud
Copy this flow JSON to your clipboard and then import into Node-RED using the Import From > Clipboard (Ctrl-I) menu option