forked from bcit-ci/CodeIgniter
-
Notifications
You must be signed in to change notification settings - Fork 4
Persona Login
Mike Fisher edited this page Feb 23, 2014
·
4 revisions
Persona is a password less login system created by Mozilla (read more). For additional information, look at the Mozilla developer site.
First step to integrate it is, creating a library (+helpers) which does all the complicated stuff
// file: application/libraries/Authentication.php
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Authentication {
private $CI;
private $email;
function __construct() {
// get super object
$this->CI =& get_instance();
// set email
$this->email = $this->CI->session->userdata('email');
}
/** get email
*
* \return email address if set, otherwise false
*/
public function get_email() {
return $this->email;
}
public function login($assertion) {
// verify assertion
$result = $this->verify_assertion($assertion);
// check for success
if ($result->status === 'okay') {
$this->email = $result->email;
$this->CI->session->set_userdata(array('email' => $result->email));
}
}
public function logout() {
// logout
$this->email = false;
$this->CI->session->sess_destroy();
}
private function verify_assertion($assertion) {
$audience = (empty($_SERVER['HTTPS']) ? 'http://' : 'https://') . $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'];
$postdata = 'assertion=' . urlencode($assertion) . '&audience=' . urlencode($audience);
$this->CI->load->helper('post');
$result = post_request('https://verifier.login.persona.org/verify',$postdata);
return json_decode($result);
}
}
// file: application/helpers/post_helper.php
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
if (!function_exists('post_request')) {
function post_request($url, $data, $optional_headers = null)
{
$params = array('http' => array(
'method' => 'POST',
'content' => $data
));
if ($optional_headers !== null) {
$params['http']['header'] = $optional_headers;
}
$ctx = stream_context_create($params);
$fp = @fopen($url, 'rb', false, $ctx);
if (!$fp) {
throw new Exception("Problem with $url, $php_errormsg");
}
$response = @stream_get_contents($fp);
if ($response === false) {
throw new Exception("Problem reading data from $url, $php_errormsg");
}
return $response;
}
}
Next we need a controller, which provides the ability to login / logout. This controller will interact with the library.
// file: application/controllers/auth.php
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Auth extends CI_Controller {
public function login() {
if (isset($_POST['assertion']))
$this->authentication->login($_POST['assertion']);
}
public function logout() {
$this->authentication->logout();
}
}
Library, helpers and the controller is setup, now let's add the HTML / js stuff.
<head>
<script src="https://login.persona.org/include.orig.js"></script>
<script src="jquery.js"></script>
<link rel="stylesheet" type="text/css" href="buttons.css" />
</head>
<body>
<!-- persona -->
<?php if ($email = $this->authentication->get_email()) { ?>
<span><?php echo $email; ?></span>
<a class="persona-button orange" id="signout"><span>Sign out</span></a>
<?php } else { ?>
<a class="persona-button orange" id="signin"><span>Sign in</span></a>
<?php } ?>
<script type="text/javascript">
var signinLink = document.getElementById('signin');
if (signinLink) {
signinLink.onclick = function() { navigator.id.request(); };
};
var signoutLink = document.getElementById('signout');
if (signoutLink) {
signoutLink.onclick = function() { navigator.id.logout(); };
};
navigator.id.watch({
<?php
if (($email = $this->authentication->get_email() ) !== false)
echo "loggedInUser: '$email',\n";
else
echo "loggedInUser: null,\n";
?>
onlogin: function (assertion) {
$.ajax({
type: 'POST',
url: '<?php echo $this->config->item('base_url'); ?>auth/login',
data: {assertion: assertion},
success: function(res, status, xhr) {window.location.reload();},
error: function(res, status, xhr) {alert('unable to login, please try again later');}
});
},
onlogout: function () {
$.ajax({
type: 'POST',
url: '<?php echo $this->config->item('base_url'); ?>auth/logout',
success: function(res, status, xhr) {window.location.reload();},
error: function(res, status, xhr) {alert('unable to logout, please try again later');}
});
}
});
</script>
</body>
Note: in a stock installation, the onlogin/onlogout AJAX URLs should include index.php/
before auth/
.
Note: CSS button style
The last thing we need to do, is to add our new library as well as the session library to the autoload variable inside the config.
$autoload['libraries'] = array('session', 'authentication');