Commit 6c3b3d08 authored by Daniel Kraft's avatar Daniel Kraft
Browse files

Switch web site to new event-based add-on.

Implement a JS support library for the new event-based communication
with the login add-on.  Adapt the loginForm page for it.
parent 210a9c8d
/*
NameID, a namecoin based OpenID identity provider.
Copyright (C) 2014 by Daniel Kraft <d@domob.eu>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* JavaScript support routines for NameID login forms. In particular,
to implement the proper communication with the NameID login browser
add-on (if it is installed). */
/**
* The main object encapsulating the NameID status.
* @param url Site url to use for login.
* @param nonce Login nonce.
*/
function NameId (url, nonce)
{
this.url = url;
this.nonce = nonce;
this.apiEl = null;
/* Set names used also in the add-on. These must be the same
as in the add-on. */
this.apiEvent = "nameid-login-event";
this.apiRequestEvent = "nameid-login-requestAPI";
this.apiElement = "nameid-login-eventTarget";
}
NameId.prototype =
{
/**
* Try to activate the login add-on on the current page. This
* must be called before the "signChallenge" method can be attempted.
* It may fail if the add-on is not available or the user denies
* trust for the current page.
* @return True iff the add-on was successfully activated.
*/
requestApi: function ()
{
if (this.apiEl !== null)
throw "NameID login API is already active.";
var evt = document.createEvent ("Events");
evt.initEvent (this.apiRequestEvent, true, false);
document.dispatchEvent (evt);
this.apiEl = document.getElementById (this.apiElement);
return this.hasApi ();
},
/**
* Check if the add-on is active.
* @return True iff the add-on was already activated.
*/
hasApi: function ()
{
return (this.apiEl !== null);
},
/**
* Request to sign the challenge message.
* @param id Identity to log in.
* @return The signed challenge message or null if the sign failed.
* @throws Error in case the API is not yet activated.
*/
signChallenge: function (id)
{
var data =
{
"version": 1,
"method": "signChallenge",
"url": this.url,
"nonce": this.nonce,
"identity": id
};
var res = this.callApi (data);
if (res.success)
return res.signature;
return null;
},
/**
* Call the API with the given JSON data.
* @param data Data to pass to the add-on as JSON object.
* @return The resulting data object.
* @throws Error in case the API is not yet activated.
*/
callApi: function (data)
{
if (this.apiEl === null)
throw "NameID login API is not active.";
var str = JSON.stringify (data);
this.apiEl.setAttribute ("data", str);
var evt = document.createEvent ("Events");
evt.initEvent (this.apiEvent, true, false);
this.apiEl.dispatchEvent (evt);
var resStr = this.apiEl.getAttribute ("result");
return JSON.parse (resStr);
},
/**
* Construct the challenge message for a given ID.
* @param id The user entered ID.
* @return The full challenge message.
*/
getChallenge: function (id)
{
/* This must of course be in sync with the PHP code as well as
the "ordinary" page JavaScript! */
var fullId = this.url + "?name=" + encodeURIComponent (id);
var msg = "login " + fullId + " " + this.nonce;
return msg;
}
};
<?php
/*
NameID, a namecoin based OpenID identity provider.
Copyright (C) 2013 by Daniel Kraft <d@domob.eu>
Copyright (C) 2013-2014 by Daniel Kraft <d@domob.eu>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
......@@ -70,41 +70,81 @@ message:</label></p>
</form>
<!-- Store values for constructing the challenge here for the
NameID addon. -->
<div class="hidden">
<span id="nameid-nonce"><?php echo $html->escape ($loginNonce); ?></span>
<span id="nameid-uri"><?php echo $html->escape ($serverUri); ?></span>
</div>
<!-- ======================================================================= -->
<!-- A little JavaScript to construct the message to sign dynamically
based on the entered id. It is probably not necessary to include
the id in the challenge message, but it doesn't matter. -->
<!-- Load JS script. -->
<script type="text/javascript" src="js/NameId.js"></script>
<!-- Custom JS code for this page. -->
<script type="text/javascript">
function updateChallenge (evt)
{
var id = document.getElementById ("identity").value;
var data = <?php
/* The NameId object used. Will be constructed in onload event. */
var nameid = null;
/* Store basic login information from PHP. */
var data = <?php
$data = array ("nonce" => $loginNonce,
"url" => $serverUri);
echo json_encode ($data);
?>;
?>;
/* The code below must be in sync with authenticator.inc.php! */
/* Update the challenge field. */
function updateChallenge (evt)
{
var id = document.getElementById ("identity").value;
var msg = nameid.getChallenge (id);
document.getElementById ("message").value = msg;
}
var fullId = data.url + "?name=" + encodeURIComponent (id);
var msg = "login " + fullId + " " + data.nonce;
/* Try to sign the challenge message via the add-on. */
function signChallenge ()
{
var id = document.getElementById ("identity").value;
var signature = nameid.signChallenge (id);
document.getElementById ("message").value = msg;
if (signature === null)
return false;
document.getElementById ("signature").value = signature;
return true;
}
/* Set up everything on page load. */
function setup (evt)
{
nameid = new NameId (data.url, data.nonce);
nameid.requestApi ();
if (nameid.hasApi ())
{
var body = document.getElementsByTagName ("body");
body[0].className = "withAddon";
}
var idEntry = document.getElementById ("identity");
idEntry.addEventListener ("change", updateChallenge);
var cancelClicked = false;
function handleSubmit (evt)
{
if (cancelClicked)
return;
var res = signChallenge ();
if (!res)
evt.preventDefault ();
}
function handleCancel (evt)
{
cancelClicked = true;
}
if (nameid.hasApi ())
{
var form = document.getElementById ("loginForm");
form.addEventListener ("submit", handleSubmit);
var cancel = document.getElementById ("cancel");
cancel.addEventListener ("click", handleCancel);
}
}
window.addEventListener ("load", setup);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment