Last year, I posted a JavaScript snippet that I've started using in all my projects that have an IndieAuth login form, which will automatically add the http
scheme if you type a plain domain. This is particularly a problem because the iOS keyboard doesn't include the :
character in URL mode.
My solution last year was to automatically prepend http://
when a plain domain is entered. This works, but it would be nice if I could use https://
as the default. The problem is I can't assume everyone has https on their websites, and I don't want to have the flow error out when the site can't fetch your domain over https because it's only available on http.
The trick is that the frontend can tell the backend whether the https scheme was automatically entered or was user-entered. And then, the backend can attempt the https connection first, and if that fails, fall back to http, but only if the https scheme was added automatically.
This provides the best of both worlds. If you explicitly enter https, then it will only use the https URL. If you enter just a domain, then it tries https first, and only falls back to http if that fails due to an ssl error.
The revised code snippet is below. The change if you're using this code is that you have to explicitly opt in to this new behavior. The code attaches to all URL input fields, and then if it finds a corresponding field to add this toggle, it will switch to https by default instead of http, and add a "1" to your defined form field.
<script>
/* add https:// to URL fields on blur */
document.addEventListener('DOMContentLoaded', function() {
function addDefaultScheme(target) {
var auto_scheme_field = document.querySelector("input[name="+target.getAttribute('name')+"_auto_scheme]");
if(target.value.match(/^(?!https?:).+\..+/)) {
if(auto_scheme_field) {
target.value = "https://"+target.value;
auto_scheme_field.value = "1";
} else {
target.value = "http://"+target.value;
}
}
}
var elements = document.querySelectorAll("input[type=url]");
Array.prototype.forEach.call(elements, function(el, i){
el.addEventListener("blur", function(e){
addDefaultScheme(e.target);
});
el.addEventListener("keydown", function(e){
if(e.keyCode == 13) {
addDefaultScheme(e.target);
}
});
});
});
</script>
To use this code with the auto-https upgrade feature, just create any url
type input field in the page, and create a hidden
input field with a name
that is the same as the url field with _auto_scheme
appended. The value "1" will be written to this field if this code adds the default scheme.
<form action="/login">
<input type="url" name="url"><br>
<input type="hidden" name="url_auto_scheme">
<input type="submit" value="Log In">
</form>
Then in your backend, begin the IndieAuth discovery using the url
value as normal. If that step returns an SSL error, then check if url_auto_scheme
is 1
, and if it is, modify the input URL to switch to the http
scheme and try the discovery step again.
That little bit of frontend JavaScript and backend logic provides a great balance between usability and security for websites that ask users to enter URLs!