PHP OpenSSO FAQ: Can you share a PHP script to manually authenticate OpenSSO users during a login process?
I've been working with OpenSSO a lot lately, and towards the end of my project most of that work involved writing PHP code to interact with an OpenSSO identity server. Specifically, I wrote several PHP scripts to (a) manually authenticate a user's credentials against an OpenSSO server, (b) get information about the user's identity, and (c) manually log out of an OpenSSO login session, all using the OpenSSO identity services API (a REST, or RESTful API).
The PHP code I'm sharing today demonstrates how to manually authenticate a user's credentials against an OpenSSO data store during the login process. For this example I've stripped the code down the to just demonstrate the essentials. That way you don't have to worry about the details of the framework I used in the code: the example is plain, and simple, PHP code.
(As a very important note regarding OpenSSO, writing your own PHP code to handle the login process manually is not always required. It's just one of the four ways to interact with an OpenSSO server, and the method I'm most interest in at this time, as it gives me the ultimate flexibility in my web applications.)
The PHP/OpenSSO login page
To get started with, here's the PHP source code for a very simple OpenSSO login page, which I've named login.php
:
<html> <head> <title>Please Log In</title> </head> <body> <form action="loginHandler.php" method="post"> <table> <tr> <td>Username</td> <td><input type="text" name="username" /></td> </tr> <tr> <td>Password</td> <td><input type="password" name="password" /></td> </tr> <tr> <td> </td> <td><input type="submit" value="login" /></td> </tr> </table> </form> </body> </html>
As you can see from that code it's a very simple login page that will post its data to another PHP script named loginHandler.php
. As you'll see, that PHP script will handle all of the heavy lifting.
The PHP login handler code
The loginHandler.php
code is just a tad bit more complicated than the sample login page. This handler class needs to get the information from the login form, and then validate the user's credentials against the OpenSSO user data store using the RESTful OpenSSO Identity Services calls.
I'll show you the source code here first, then add some comments about it afterwards.
<?php require 'HTTP/Request.php'; # redirect the user back to the login page if the authentication process # fails, and redirect them to the main.php page if it succeeds $LOGIN_PAGE = 'http://loginserver.example.com:8000/identity-tests/login.php'; $MAIN_PAGE = 'http://loginserver.example.com:8000/identity-tests/main.php'; # our opensso identity services authentication url $OPENSSO_AUTH_URL = 'http://opensso.example.com:8080/opensso/identity/authenticate'; # we should get a POST from the login page. # check for a username and password, and go from there. $username = trim($_POST['username']); $password = trim($_POST['password']); # i'm not a php expert, i'm sure there's a better way to handle this $len_username = strlen($username); $len_password = strlen($password); if ($len_username==0 || $len_password==0) { # didn't get both a username and a password; go back to login error_log('DIDNT GET USERNAME AND PASSWORD, GOING BACK TO LOGIN PAGE'); header("Location: $LOGIN_PAGE"); return; } # have both a username and password, try to validate them $req = new HTTP_Request($OPENSSO_AUTH_URL); $req->setMethod(HTTP_REQUEST_METHOD_POST); $req->addHeader('Content-Type','application/x-www-form-urlencoded'); $req->addHeader('Cookie',"iPlanetDirectoryPro=$_COOKIE[iPlanetDirectoryPro]"); $req->addPostData('username', $username); $req->addPostData('password', $password); $req->sendRequest(); $res = $req->getResponseBody(); # this is cheesy, but the current response from opensso is a full web page # that contains the string 'Failed'. $pos = strpos($res, 'Failed'); if ($pos === false) { # RESPONSE: token.id=AQIC5wM2LY4SfcziG_wO0gqy3VUCrNndCq5tJHkDihQlFcU.*AAJTSQACMDE.*\n, # referer: http://loginserver.example.com:8000/identity-tests/login.php $pos1 = strpos($res, 'token.id='); $pos2 = strpos($res, "\n"); $start = $pos1 + 9; $len = $pos2 - $start; $token = substr($res, $start, $len); error_log('LOGIN SUCCEEDED, GOING ON TO MAIN'); setcookie('iPlanetDirectoryPro', $token); header("Location: $MAIN_PAGE"); } else { error_log('LOGIN FAILED, GOING BACK TO LOGIN PAGE'); header("Location: $LOGIN_PAGE"); } ?>
Here are a few notes about this PHP login handler:
- The main purpose of this script is to authenticate the user's login credentials against our OpenSSO server, and then redirect them to our
main.php
page if the authentication process succeeds, or redirect them back to the login.php page if it fails. - As noted, I'm not a PHP expert, so the way I'm checking for the existence of a
username
andpassword
may not be a great or preferred way of doing this. That being said, I like to keep from sending junk to the authentication server, and this is a start. - To call the OpenSSO
authenticate
identity service you just need to build up a POST request, which I demonstrate in the code. - I'd like to come up with a better way of dealing with the
responseBody
than what I've shown, but for the purposes of a prototype this worked okay. - If you haven't done much web programming like this before, it's very important to write all your header information before you try to write anything related to the response body content. (I'll write more about this in a future blog post.)
As mentioned, when a login request is successful, this script redirects the user to another page named main.php
. I'll write about that PHP page in a near-future blog post as well, because it demonstrates how to get the OpenSSO browser cookie, and validate it against my OpenSSO server, which is very important when you want to manually secure your web pages using OpenSSO.