[smarcet] - Refs #4578 - OpenId - Server Core Logic - Authentication Workflow
This commit is contained in:
parent
122ea0c0a5
commit
f1ad337e3a
File diff suppressed because it is too large
Load Diff
|
@ -23,10 +23,14 @@ class DiscoveryController extends BaseController {
|
|||
* @return xrds document on response
|
||||
*/
|
||||
public function idp(){
|
||||
$value = Request::header('Content-Type');
|
||||
if($value == XRDSDocumentBuilder::ContentType){
|
||||
//This field contains a semicolon-separated list of representation schemes
|
||||
//which will be accepted in the response to this request.
|
||||
$accept = Request::header('Accept');
|
||||
$accept_values = explode(",",$accept);
|
||||
if(in_array(XRDSDocumentBuilder::ContentType,$accept_values))
|
||||
{
|
||||
$response = Response::make($this->openid_protocol->getXRDSDiscovery(), 200);
|
||||
$response->header('Content-Type', "application/xrds+xml");
|
||||
$response->header('Content-Type', "application/xrds+xml; charset=UTF-8");
|
||||
}
|
||||
else{
|
||||
$response = View::make("home");
|
||||
|
|
|
@ -3,8 +3,11 @@ use openid\XRDS\XRDSDocumentBuilder;
|
|||
class HomeController extends BaseController {
|
||||
|
||||
public function index(){
|
||||
$value = Request::header('Content-Type');
|
||||
if($value == XRDSDocumentBuilder::ContentType)
|
||||
//This field contains a semicolon-separated list of representation schemes
|
||||
//which will be accepted in the response to this request.
|
||||
$accept = Request::header('Accept');
|
||||
$accept_values = explode(",",$accept);
|
||||
if(in_array(XRDSDocumentBuilder::ContentType,$accept_values))
|
||||
return Redirect::action('DiscoveryController@idp');
|
||||
return View::make("home");
|
||||
}
|
||||
|
|
|
@ -44,6 +44,8 @@ Route::filter('auth.basic', function()
|
|||
return Auth::basic();
|
||||
});
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Guest Filter
|
||||
|
|
|
@ -38,7 +38,7 @@ class AuthService implements IAuthService {
|
|||
*/
|
||||
public function Login($username, $password)
|
||||
{
|
||||
return Auth::attempt(array('username' => $username, 'password' => $password), true);
|
||||
return Auth::attempt(array('username' => $username, 'password' => $password), false);
|
||||
}
|
||||
|
||||
public function logout(){
|
||||
|
@ -50,8 +50,11 @@ class AuthService implements IAuthService {
|
|||
*/
|
||||
public function getUserAuthorizationResponse()
|
||||
{
|
||||
if(Session::has("openid.authorization.response"))
|
||||
return Session::get("openid.authorization.response");
|
||||
if(Session::has("openid.authorization.response")){
|
||||
$value= Session::get("openid.authorization.response");
|
||||
Session::remove('openid.authorization.response');
|
||||
return $value;
|
||||
}
|
||||
return IAuthService::AuthorizationResponse_None;
|
||||
}
|
||||
|
||||
|
|
|
@ -117,14 +117,16 @@ class OpenIdProtocol implements IOpenIdProtocol {
|
|||
}
|
||||
|
||||
public function getXRDSDiscovery(){
|
||||
$active_extensions = $this->server_extension_repository->GetAllExtensions();
|
||||
$server_extension_service = \App::make("openid\\services\\IServerExtensionsService");
|
||||
$server_config_service = \App::make("openid\\services\\IServerConfigurationService");
|
||||
$active_extensions = $server_extension_service->getAllActiveExtensions();
|
||||
$extensions = array();
|
||||
foreach($active_extensions as $ext){
|
||||
array_push($extensions,$ext->namespace);
|
||||
array_push($extensions,$ext->getNamespace());
|
||||
}
|
||||
|
||||
$services = array();
|
||||
array_push($services, new XRDSService(0,self::OPIdentifierType,$this->server_configuration->getOPEndpointURL(),$extensions));
|
||||
array_push($services, new XRDSService(0,self::OPIdentifierType,$server_config_service->getOPEndpointURL(),$extensions));
|
||||
$builder = new XRDSDocumentBuilder($services);
|
||||
$xrds = $builder->render();
|
||||
return $xrds;
|
||||
|
|
|
@ -23,17 +23,8 @@ class XRDSDocumentBuilder {
|
|||
public function render(){
|
||||
$XRDNamespace = self::XRDNamespace;
|
||||
$XRDSNamespace = self::XRDSNamespace;
|
||||
$header = <<< XRDS
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xrds:XRDS
|
||||
xmlns:xrds="{$XRDSNamespace}"
|
||||
xmlns="{$XRDNamespace}">
|
||||
<XRD>
|
||||
XRDS;
|
||||
$footer = <<< XRDS
|
||||
</XRD>
|
||||
</xrds:XRDS>
|
||||
XRDS;
|
||||
$header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<xrds:XRDS xmlns:xrds=\"{$XRDSNamespace}\" xmlns=\"{$XRDNamespace}\">\n<XRD>\n";
|
||||
$footer = "</XRD>\n</xrds:XRDS>";
|
||||
$xrds = $header;
|
||||
foreach($this->elements as $service){
|
||||
$xrds .= $service->render();
|
||||
|
|
|
@ -29,21 +29,14 @@ class XRDSService {
|
|||
}
|
||||
|
||||
public function render(){
|
||||
$local_id =empty($this->local_id)?"":"<LocalID>{$this->local_id}</LocalID>";
|
||||
$local_id =empty($this->local_id)?"":"<LocalID>{$this->local_id}</LocalID>\n";
|
||||
|
||||
$extensions ="";
|
||||
foreach($this->extensions as $extension){
|
||||
$extensions.="<Type>{$extension}</Type>";
|
||||
$extensions.="<Type>{$extension}</Type>\n";
|
||||
}
|
||||
|
||||
$element = <<< SERVICE
|
||||
<Service priority="{$this->priority}">
|
||||
<Type>{$this->type}</Type>
|
||||
{$extensions}
|
||||
<URI>{$this->uri}</URI>
|
||||
{$local_id}
|
||||
</Service>
|
||||
SERVICE;
|
||||
$element ="<Service priority=\"{$this->priority}\">\n<Type>{$this->type}</Type>\n{$extensions}<URI>{$this->uri}</URI>\n{$local_id}</Service>\n";
|
||||
return $element;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,9 +20,13 @@ abstract class OpenIdExtension {
|
|||
protected $description;
|
||||
|
||||
public function __construct($name,$namespace,$description){
|
||||
$this->namespace=$namespace;
|
||||
$this->name=$name;
|
||||
$this->description = $description;
|
||||
$this->namespace = $namespace;
|
||||
$this->name = $name;
|
||||
$this->description = $description;
|
||||
}
|
||||
|
||||
public function getNamespace(){
|
||||
return $this->namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,6 +18,7 @@ use openid\responses\contexts\ResponseContext;
|
|||
use openid\responses\OpenIdResponse;
|
||||
use openid\services\Registry;
|
||||
use openid\OpenIdMessage;
|
||||
use openid\exceptions\InvalidOpenIdMessageException;
|
||||
|
||||
class OpenIdAXRequest extends OpenIdRequest
|
||||
{
|
||||
|
@ -50,7 +51,7 @@ class OpenIdAXRequest extends OpenIdRequest
|
|||
)
|
||||
throw new InvalidOpenIdMessageException("AX: not set or invalid mode mode");
|
||||
|
||||
if (isset($this->message[OpenIdProtocol::OpenIdPrefix . "_" . OpenIdAXExtension::Prefix . "_" . OpenIdAXExtension::RequiredAttributes]))
|
||||
if (!isset($this->message[OpenIdProtocol::OpenIdPrefix . "_" . OpenIdAXExtension::Prefix . "_" . OpenIdAXExtension::RequiredAttributes]))
|
||||
throw new InvalidOpenIdMessageException("AX: not set required attributes!");
|
||||
|
||||
$attributes = $this->message[OpenIdProtocol::OpenIdPrefix . "_" . OpenIdAXExtension::Prefix . "_" . OpenIdAXExtension::RequiredAttributes];
|
||||
|
@ -58,13 +59,14 @@ class OpenIdAXRequest extends OpenIdRequest
|
|||
foreach ($attributes as $attr) {
|
||||
$attr = trim($attr);
|
||||
if (!isset(OpenIdAXExtension::$available_properties[$attr]))
|
||||
throw new InvalidOpenIdMessageException(sprintf("AX: invalid attribute requested %s", $attr));
|
||||
if (!isset($this->message[OpenIdProtocol::OpenIdPrefix . "_" . self::Prefix . "_" . self::Type . "_" . $attr]))
|
||||
//throw new InvalidOpenIdMessageException(sprintf("AX: invalid attribute requested %s", $attr));
|
||||
continue;
|
||||
if (!isset($this->message[OpenIdProtocol::OpenIdPrefix . "_" . OpenIdAXExtension::Prefix . "_" . OpenIdAXExtension::Type . "_" . $attr]))
|
||||
throw new InvalidOpenIdMessageException(sprintf("AX: invalid ns for attribute %s", $attr));
|
||||
$ns = $this->message[OpenIdProtocol::OpenIdPrefix . "_" . self::Prefix . "_" . self::Type . "_" . $attr];
|
||||
$ns = $this->message[OpenIdProtocol::OpenIdPrefix . "_" . OpenIdAXExtension::Prefix . "_" . OpenIdAXExtension::Type . "_" . $attr];
|
||||
if ($ns != OpenIdAXExtension::$available_properties[$attr])
|
||||
throw new InvalidOpenIdMessageException(sprintf("AX: invalid ns for attribute %s", $attr));
|
||||
array_push($this->$attributes, $attr);
|
||||
array_push($this->attributes, $attr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -101,7 +103,7 @@ class OpenIdAXExtension extends OpenIdExtension
|
|||
self::$available_properties[OpenIdAXExtension::Country] = "http://axschema.org/contact/country/home";
|
||||
self::$available_properties[OpenIdAXExtension::Email] = "http://axschema.org/contact/email";
|
||||
self::$available_properties[OpenIdAXExtension::FirstMame] = "http://axschema.org/namePerson/first";
|
||||
self::$available_properties[OpenIdAXExtension::LastName] = "http://axschema.org/pref/language";
|
||||
self::$available_properties[OpenIdAXExtension::LastName] = "http://axschema.org/namePerson/last";
|
||||
self::$available_properties[OpenIdAXExtension::Language] = "http://axschema.org/pref/language";
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ use openid\responses\OpenIdNonImmediateNegativeAssertion;
|
|||
use openid\responses\OpenIdImmediateNegativeAssertion;
|
||||
use openid\services\ITrustedSitesService;
|
||||
use openid\responses\OpenIdIndirectResponse;
|
||||
use openid\exceptions\OpenIdIndirectGenericErrorResponse;
|
||||
use openid\responses\OpenIdIndirectGenericErrorResponse;
|
||||
use openid\helpers\OpenIdErrorMessages;
|
||||
use openid\helpers\OpenIdCryptoHelper;
|
||||
use openid\model\IAssociation;
|
||||
|
@ -111,9 +111,12 @@ class OpenIdAuthenticationRequestHandler extends OpenIdMessageHandler
|
|||
|
||||
protected function InternalHandle(OpenIdMessage $message)
|
||||
{
|
||||
$request = null;
|
||||
try
|
||||
{
|
||||
$request = new OpenIdAuthenticationRequest($message);
|
||||
if(!$request->IsValid())
|
||||
throw new InvalidOpenIdMessageException("OpenIdAuthenticationRequest is Invalid!");
|
||||
$extensions = $this->server_extensions_service->getAllActiveExtensions();
|
||||
$context = new RequestContext;
|
||||
$mode = $request->getMode();
|
||||
|
@ -168,15 +171,22 @@ class OpenIdAuthenticationRequestHandler extends OpenIdMessageHandler
|
|||
return $this->doAssertion($request, $extensions);
|
||||
break;
|
||||
case IAuthService::AuthorizationResponse_DenyOnce:
|
||||
return new OpenIdNonImmediateNegativeAssertion;
|
||||
break;
|
||||
case IAuthService::AuthorizationResponse_DenyForever:
|
||||
{
|
||||
$response = new OpenIdNonImmediateNegativeAssertion;
|
||||
$response->setReturnTo($request->getReturnTo());
|
||||
return $response;
|
||||
}
|
||||
break;
|
||||
case IAuthService::AuthorizationResponse_DenyForever:{
|
||||
$this->trusted_sites_service->addTrustedSite($currentUser, $request->getTrustedRoot(), IAuthService::AuthorizationResponse_DenyForever);
|
||||
return new OpenIdNonImmediateNegativeAssertion;
|
||||
break;
|
||||
$response = new OpenIdNonImmediateNegativeAssertion;
|
||||
$response->setReturnTo($request->getReturnTo());
|
||||
return $response;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new \Exception("Invalid Authorization response!");
|
||||
break;
|
||||
throw new \Exception("Invalid Authorization response!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -206,7 +216,15 @@ class OpenIdAuthenticationRequestHandler extends OpenIdMessageHandler
|
|||
}
|
||||
}
|
||||
catch (InvalidOpenIdMessageException $ex) {
|
||||
return new OpenIdIndirectGenericErrorResponse($ex->getMessage());
|
||||
$response = new OpenIdIndirectGenericErrorResponse($ex->getMessage());
|
||||
|
||||
if(!is_null($request)){
|
||||
$return_to = $request->getReturnTo();
|
||||
if(!empty($return_to))
|
||||
$response->setReturnTo($return_to);
|
||||
}
|
||||
|
||||
return $response ;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,64 @@
|
|||
|
||||
namespace openid\helpers;
|
||||
|
||||
define('OpenIdUriHelper_TLDs',
|
||||
'/\.(ac|ad|ae|aero|af|ag|ai|al|am|an|ao|aq|ar|arpa|as|asia' .
|
||||
'|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|biz|bj|bm|bn|bo|br' .
|
||||
'|bs|bt|bv|bw|by|bz|ca|cat|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co' .
|
||||
'|com|coop|cr|cu|cv|cx|cy|cz|de|dj|dk|dm|do|dz|ec|edu|ee|eg' .
|
||||
'|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl' .
|
||||
'|gm|gn|gov|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie' .
|
||||
'|il|im|in|info|int|io|iq|ir|is|it|je|jm|jo|jobs|jp|ke|kg|kh' .
|
||||
'|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly' .
|
||||
'|ma|mc|md|me|mg|mh|mil|mk|ml|mm|mn|mo|mobi|mp|mq|mr|ms|mt' .
|
||||
'|mu|museum|mv|mw|mx|my|mz|na|name|nc|ne|net|nf|ng|ni|nl|no' .
|
||||
'|np|nr|nu|nz|om|org|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|pro|ps|pt' .
|
||||
'|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|sk|sl' .
|
||||
'|sm|sn|so|sr|st|su|sv|sy|sz|tc|td|tel|tf|tg|th|tj|tk|tl|tm' .
|
||||
'|tn|to|tp|tr|travel|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve' .
|
||||
'|vg|vi|vn|vu|wf|ws|xn--0zwm56d|xn--11b5bs3a9aj6g' .
|
||||
'|xn--80akhbyknj4f|xn--9t4b11yi5a|xn--deba0ad|xn--g6w251d' .
|
||||
'|xn--hgbk6aj7f53bba|xn--hlcj6aya9esc7a|xn--jxalpdlp' .
|
||||
'|xn--kgbechtv|xn--zckzah|ye|yt|yu|za|zm|zw)\.?$/');
|
||||
|
||||
class OpenIdUriHelper {
|
||||
define('OpenIdUriHelper_HostSegmentRe', "/^(?:[-a-zA-Z0-9!$&'\\(\\)\\*+,;=._~]|%[a-zA-Z0-9]{2})*$/");
|
||||
|
||||
|
||||
class OpenIdUriHelper
|
||||
{
|
||||
|
||||
const AuthorityPattern = "/^([^@]*@)?([^:]*)(:.*)?/";
|
||||
const URIPattern = "&^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?&";
|
||||
const EncodedPattern = "/%([0-9A-Fa-f]{2})/";
|
||||
const URLIllegalCharRE = "/([^-A-Za-z0-9:\/\?#\[\]@\!\$&'\(\)\*\+,;=\._~\%])/";
|
||||
|
||||
|
||||
public static function getUnreserved()
|
||||
{
|
||||
$_unreserved = array();
|
||||
for ($i = 0; $i < 256; $i++) {
|
||||
$_unreserved[$i] = false;
|
||||
}
|
||||
|
||||
for ($i = ord('A'); $i <= ord('Z'); $i++) {
|
||||
$_unreserved[$i] = true;
|
||||
}
|
||||
|
||||
for ($i = ord('0'); $i <= ord('9'); $i++) {
|
||||
$_unreserved[$i] = true;
|
||||
}
|
||||
|
||||
for ($i = ord('a'); $i <= ord('z'); $i++) {
|
||||
$_unreserved[$i] = true;
|
||||
}
|
||||
|
||||
$_unreserved[ord('-')] = true;
|
||||
$_unreserved[ord('.')] = true;
|
||||
$_unreserved[ord('_')] = true;
|
||||
$_unreserved[ord('~')] = true;
|
||||
|
||||
return $_unreserved;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an absolute URL for the given one
|
||||
|
@ -18,7 +74,7 @@ class OpenIdUriHelper {
|
|||
* @param string $url absilute or relative URL
|
||||
* @return string
|
||||
*/
|
||||
static public function absoluteUrl($url)
|
||||
public static function absoluteUrl($url)
|
||||
{
|
||||
if (empty($url)) {
|
||||
return Zend_OpenId::selfUrl();
|
||||
|
@ -61,7 +117,7 @@ class OpenIdUriHelper {
|
|||
* @param string &$id url to be normalized
|
||||
* @return bool
|
||||
*/
|
||||
static public function normalizeUrl(&$id)
|
||||
public static function normalizeUrl(&$id)
|
||||
{
|
||||
// RFC 3986, 6.2.2. Syntax-Based Normalization
|
||||
|
||||
|
@ -101,7 +157,8 @@ class OpenIdUriHelper {
|
|||
$ch == '-' ||
|
||||
$ch == '.' ||
|
||||
$ch == '_' ||
|
||||
$ch == '~') {
|
||||
$ch == '~'
|
||||
) {
|
||||
$res .= $ch;
|
||||
} else {
|
||||
$res .= '%';
|
||||
|
@ -201,14 +258,420 @@ class OpenIdUriHelper {
|
|||
return true;
|
||||
}
|
||||
|
||||
static public function checkRealmWildcard($root,$realm){
|
||||
$n = strpos($realm, '://*.');
|
||||
if ($n != false) {
|
||||
$regex = '/^'. preg_quote(substr($realm, 0, $n+3), '/'). '[A-Za-z1-9_\.]+?'. preg_quote(substr($realm, $n+4), '/'). '/';
|
||||
if (preg_match($regex, $root)) {
|
||||
return true;
|
||||
private static function startswith($s, $stuff)
|
||||
{
|
||||
return strpos($s, $stuff) === 0;
|
||||
}
|
||||
|
||||
private static function remove_dot_segments($path)
|
||||
{
|
||||
$result_segments = array();
|
||||
|
||||
while ($path) {
|
||||
if (self::startswith($path, '../')) {
|
||||
$path = substr($path, 3);
|
||||
} else if (self::startswith($path, './')) {
|
||||
$path = substr($path, 2);
|
||||
} else if (self::startswith($path, '/./')) {
|
||||
$path = substr($path, 2);
|
||||
} else if ($path == '/.') {
|
||||
$path = '/';
|
||||
} else if (self::startswith($path, '/../')) {
|
||||
$path = substr($path, 3);
|
||||
if ($result_segments) {
|
||||
array_pop($result_segments);
|
||||
}
|
||||
} else if ($path == '/..') {
|
||||
$path = '/';
|
||||
if ($result_segments) {
|
||||
array_pop($result_segments);
|
||||
}
|
||||
} else if (($path == '..') ||
|
||||
($path == '.')
|
||||
) {
|
||||
$path = '';
|
||||
} else {
|
||||
$i = 0;
|
||||
if ($path[0] == '/') {
|
||||
$i = 1;
|
||||
}
|
||||
$i = strpos($path, '/', $i);
|
||||
if ($i === false) {
|
||||
$i = strlen($path);
|
||||
}
|
||||
$result_segments[] = substr($path, 0, $i);
|
||||
$path = substr($path, $i);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
return implode('', $result_segments);
|
||||
}
|
||||
|
||||
private static function urinorm($uri)
|
||||
{
|
||||
$uri_matches = array();
|
||||
preg_match(self::URIPattern, $uri, $uri_matches);
|
||||
|
||||
if (count($uri_matches) < 9) {
|
||||
for ($i = count($uri_matches); $i <= 9; $i++) {
|
||||
$uri_matches[] = '';
|
||||
}
|
||||
}
|
||||
|
||||
$illegal_matches = array();
|
||||
preg_match(self::URLIllegalCharRE,
|
||||
$uri, $illegal_matches);
|
||||
if ($illegal_matches) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$scheme = $uri_matches[2];
|
||||
if ($scheme) {
|
||||
$scheme = strtolower($scheme);
|
||||
}
|
||||
|
||||
$scheme = $uri_matches[2];
|
||||
if ($scheme === '') {
|
||||
// No scheme specified
|
||||
return null;
|
||||
}
|
||||
|
||||
$scheme = strtolower($scheme);
|
||||
if (!in_array($scheme, array('http', 'https'))) {
|
||||
// Not an absolute HTTP or HTTPS URI
|
||||
return null;
|
||||
}
|
||||
|
||||
$authority = $uri_matches[4];
|
||||
if ($authority === '') {
|
||||
// Not an absolute URI
|
||||
return null;
|
||||
}
|
||||
|
||||
$authority_matches = array();
|
||||
preg_match(self::AuthorityPattern,
|
||||
$authority, $authority_matches);
|
||||
if (count($authority_matches) === 0) {
|
||||
// URI does not have a valid authority
|
||||
return null;
|
||||
}
|
||||
|
||||
if (count($authority_matches) < 4) {
|
||||
for ($i = count($authority_matches); $i <= 4; $i++) {
|
||||
$authority_matches[] = '';
|
||||
}
|
||||
}
|
||||
|
||||
list($_whole, $userinfo, $host, $port) = $authority_matches;
|
||||
|
||||
if ($userinfo === null) {
|
||||
$userinfo = '';
|
||||
}
|
||||
|
||||
if (strpos($host, '%') !== -1) {
|
||||
$host = strtolower($host);
|
||||
$host = preg_replace_callback(
|
||||
self::EncodedPattern,
|
||||
function ($mo) {
|
||||
return chr(intval($mo[1], 16));
|
||||
}, $host);
|
||||
// NO IDNA.
|
||||
// $host = unicode($host, 'utf-8').encode('idna');
|
||||
} else {
|
||||
$host = strtolower($host);
|
||||
}
|
||||
|
||||
if ($port) {
|
||||
if (($port == ':') ||
|
||||
($scheme == 'http' && $port == ':80') ||
|
||||
($scheme == 'https' && $port == ':443')
|
||||
) {
|
||||
$port = '';
|
||||
}
|
||||
} else {
|
||||
$port = '';
|
||||
}
|
||||
|
||||
$authority = $userinfo . $host . $port;
|
||||
|
||||
$path = $uri_matches[5];
|
||||
$path = preg_replace_callback(
|
||||
self::EncodedPattern,
|
||||
function ($mo) {
|
||||
$_unreserved = OpenIdUriHelper::getUnreserved();
|
||||
|
||||
$i = intval($mo[1], 16);
|
||||
if ($_unreserved[$i]) {
|
||||
return chr($i);
|
||||
} else {
|
||||
return strtoupper($mo[0]);
|
||||
}
|
||||
|
||||
return $mo[0];
|
||||
}, $path);
|
||||
|
||||
$path = self::remove_dot_segments($path);
|
||||
if (!$path) {
|
||||
$path = '/';
|
||||
}
|
||||
|
||||
$query = $uri_matches[6];
|
||||
if ($query === null) {
|
||||
$query = '';
|
||||
}
|
||||
|
||||
$fragment = $uri_matches[8];
|
||||
if ($fragment === null) {
|
||||
$fragment = '';
|
||||
}
|
||||
|
||||
return $scheme . '://' . $authority . $path . $query . $fragment;
|
||||
}
|
||||
|
||||
private static function _parse($trust_root)
|
||||
{
|
||||
$trust_root = self::urinorm($trust_root);
|
||||
if ($trust_root === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (preg_match("/:\/\/[^:]+(:\d+){2,}(\/|$)/", $trust_root)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parts = @parse_url($trust_root);
|
||||
if ($parts === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$required_parts = array('scheme', 'host');
|
||||
$forbidden_parts = array('user', 'pass', 'fragment');
|
||||
$keys = array_keys($parts);
|
||||
if (array_intersect($keys, $required_parts) != $required_parts) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (array_intersect($keys, $forbidden_parts) != array()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!preg_match(OpenIdUriHelper_HostSegmentRe, $parts['host'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$scheme = strtolower($parts['scheme']);
|
||||
$allowed_schemes = array('http', 'https');
|
||||
if (!in_array($scheme, $allowed_schemes)) {
|
||||
return false;
|
||||
}
|
||||
$parts['scheme'] = $scheme;
|
||||
|
||||
$host = strtolower($parts['host']);
|
||||
$hostparts = explode('*', $host);
|
||||
switch (count($hostparts)) {
|
||||
case 1:
|
||||
$parts['wildcard'] = false;
|
||||
break;
|
||||
case 2:
|
||||
if ($hostparts[0] ||
|
||||
($hostparts[1] && substr($hostparts[1], 0, 1) != '.')
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
$host = $hostparts[1];
|
||||
$parts['wildcard'] = true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (strpos($host, ':') !== false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$parts['host'] = $host;
|
||||
|
||||
if (isset($parts['path'])) {
|
||||
$path = strtolower($parts['path']);
|
||||
if (substr($path, 0, 1) != '/') {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
$path = '/';
|
||||
}
|
||||
|
||||
$parts['path'] = $path;
|
||||
if (!isset($parts['port'])) {
|
||||
$parts['port'] = false;
|
||||
}
|
||||
|
||||
|
||||
$parts['unparsed'] = $trust_root;
|
||||
|
||||
return $parts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this trust root sane?
|
||||
*
|
||||
* A trust root is sane if it is syntactically valid and it has a
|
||||
* reasonable domain name. Specifically, the domain name must be
|
||||
* more than one level below a standard TLD or more than two
|
||||
* levels below a two-letter tld.
|
||||
*
|
||||
* For example, '*.com' is not a sane trust root, but '*.foo.com'
|
||||
* is. '*.co.uk' is not sane, but '*.bbc.co.uk' is.
|
||||
*
|
||||
* This check is not always correct, but it attempts to err on the
|
||||
* side of marking sane trust roots insane instead of marking
|
||||
* insane trust roots sane. For example, 'kink.fm' is marked as
|
||||
* insane even though it "should" (for some meaning of should) be
|
||||
* marked sane.
|
||||
*
|
||||
* This function should be used when creating OpenID servers to
|
||||
* alert the users of the server when a consumer attempts to get
|
||||
* the user to accept a suspicious trust root.
|
||||
*
|
||||
* @static
|
||||
* @param string $trust_root The trust root to check
|
||||
* @return bool $sanity Whether the trust root looks OK
|
||||
*/
|
||||
private static function isSane($trust_root)
|
||||
{
|
||||
$parts = self::_parse($trust_root);
|
||||
if ($parts === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Localhost is a special case
|
||||
if ($parts['host'] == 'localhost') {
|
||||
return true;
|
||||
}
|
||||
|
||||
$host_parts = explode('.', $parts['host']);
|
||||
if ($parts['wildcard']) {
|
||||
// Remove the empty string from the beginning of the array
|
||||
array_shift($host_parts);
|
||||
}
|
||||
|
||||
if ($host_parts && !$host_parts[count($host_parts) - 1]) {
|
||||
array_pop($host_parts);
|
||||
}
|
||||
|
||||
if (!$host_parts) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't allow adjacent dots
|
||||
if (in_array('', $host_parts, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the top-level domain of the host. If it is not a valid TLD,
|
||||
// it's not sane.
|
||||
preg_match(OpenIdUriHelper_TLDs, $parts['host'], $matches);
|
||||
if (!$matches) {
|
||||
return false;
|
||||
}
|
||||
$tld = $matches[1];
|
||||
|
||||
if (count($host_parts) == 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($parts['wildcard']) {
|
||||
// It's a 2-letter tld with a short second to last segment
|
||||
// so there needs to be more than two segments specified
|
||||
// (e.g. *.co.uk is insane)
|
||||
$second_level = $host_parts[count($host_parts) - 2];
|
||||
if (strlen($tld) == 2 && strlen($second_level) <= 3) {
|
||||
return count($host_parts) > 2;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does this URL match the given trust root?
|
||||
*
|
||||
* Return whether the URL falls under the given trust root. This
|
||||
* does not check whether the trust root is sane. If the URL or
|
||||
* trust root do not parse, this function will return false.
|
||||
*
|
||||
* @param string $trust_root The trust root to match against
|
||||
*
|
||||
* @param string $url The URL to check
|
||||
*
|
||||
* @return bool $matches Whether the URL matches against the
|
||||
* trust root
|
||||
*/
|
||||
public static function checkRealm($trust_root, $url)
|
||||
{
|
||||
if (!filter_var($url, FILTER_VALIDATE_URL)) return false;
|
||||
if (!self::isSane($trust_root)) return false;
|
||||
|
||||
$trust_root_parsed = self::_parse($trust_root);
|
||||
$url_parsed = self::_parse($url);
|
||||
if (!$trust_root_parsed || !$url_parsed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check hosts matching
|
||||
if ($url_parsed['wildcard']) {
|
||||
return false;
|
||||
}
|
||||
if ($trust_root_parsed['wildcard']) {
|
||||
$host_tail = $trust_root_parsed['host'];
|
||||
$host = $url_parsed['host'];
|
||||
if ($host_tail &&
|
||||
substr($host, -(strlen($host_tail))) != $host_tail &&
|
||||
substr($host_tail, 1) != $host
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if ($trust_root_parsed['host'] != $url_parsed['host']) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check path and query matching
|
||||
$base_path = $trust_root_parsed['path'];
|
||||
$path = $url_parsed['path'];
|
||||
if (!isset($trust_root_parsed['query'])) {
|
||||
if ($base_path != $path) {
|
||||
if (substr($path, 0, strlen($base_path)) != $base_path) {
|
||||
return false;
|
||||
}
|
||||
if (substr($base_path, strlen($base_path) - 1, 1) != '/' &&
|
||||
substr($path, strlen($base_path), 1) != '/'
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$base_query = $trust_root_parsed['query'];
|
||||
$query = @$url_parsed['query'];
|
||||
$qplus = substr($query, 0, strlen($base_query) + 1);
|
||||
$bqplus = $base_query . '&';
|
||||
if ($base_path != $path ||
|
||||
($base_query != $query && $qplus != $bqplus)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// The port and scheme need to match exactly
|
||||
return ($trust_root_parsed['scheme'] == $url_parsed['scheme'] &&
|
||||
$url_parsed['port'] === $trust_root_parsed['port']);
|
||||
}
|
||||
|
||||
public static function checkReturnTo($return_to){
|
||||
if (!filter_var($return_to, FILTER_VALIDATE_URL)) return false;
|
||||
$url_parsed = self::_parse($return_to);
|
||||
if (!$url_parsed) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -35,7 +35,8 @@ class OpenIdAuthenticationRequest extends OpenIdRequest{
|
|||
}
|
||||
|
||||
public function getReturnTo(){
|
||||
return isset($this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo,"_")])?$this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo,"_")]:null;
|
||||
$return_to = isset($this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo,"_")])?$this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo,"_")]:null;
|
||||
return (OpenIdUriHelper::checkReturnTo($return_to))?$return_to:"";
|
||||
}
|
||||
|
||||
public function getRealm(){
|
||||
|
@ -58,12 +59,14 @@ class OpenIdAuthenticationRequest extends OpenIdRequest{
|
|||
}
|
||||
|
||||
public function IsValid(){
|
||||
$return_to = $this->getReturnTo();
|
||||
$return_to = $this->getReturnTo();
|
||||
$claimed_id = $this->getClaimedId();
|
||||
$identity = $this->getIdentity();
|
||||
$mode = $this->getMode();
|
||||
//todo: validate url(format-regex) - white list /black list?
|
||||
$identity = $this->getIdentity();
|
||||
$mode = $this->getMode();
|
||||
$realm = $this->getRealm();
|
||||
return !empty($return_to)
|
||||
&& !empty($realm)
|
||||
&& OpenIdUriHelper::checkRealm($realm,$return_to)
|
||||
&& !empty($claimed_id) && $claimed_id == OpenIdProtocol::IdentifierSelectType
|
||||
&& !empty($identity) && $identity == OpenIdProtocol::IdentifierSelectType
|
||||
&& !empty($mode) && ($mode == OpenIdProtocol::ImmediateMode || $mode == OpenIdProtocol::SetupMode);
|
||||
|
|
|
@ -17,6 +17,8 @@ use openid\exceptions\InvalidKVFormat;
|
|||
*/
|
||||
class OpenIdDirectResponse extends OpenIdResponse {
|
||||
|
||||
const OpenIdDirectResponse="OpenIdDirectResponse";
|
||||
|
||||
const DirectResponseContentType ="text/plain";
|
||||
|
||||
public function __construct(){
|
||||
|
@ -64,6 +66,6 @@ class OpenIdDirectResponse extends OpenIdResponse {
|
|||
|
||||
public function getType()
|
||||
{
|
||||
return "direct";
|
||||
return self::OpenIdDirectResponse;
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ use openid\OpenIdProtocol;
|
|||
|
||||
class OpenIdIndirectGenericErrorResponse extends OpenIdIndirectResponse {
|
||||
|
||||
public function __construct($error,$contact,$reference){
|
||||
public function __construct($error,$contact=null,$reference=null){
|
||||
parent::__construct();
|
||||
$this->setHttpCode(self::HttpErrorResponse);
|
||||
$this[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Error)] = $error;
|
||||
|
|
|
@ -14,6 +14,7 @@ use openid\responses\OpenIdResponse;
|
|||
class OpenIdIndirectResponse extends OpenIdResponse {
|
||||
|
||||
const IndirectResponseContentType ="application/x-www-form-urlencoded";
|
||||
const OpenIdIndirectResponse="OpenIdIndirectResponse";
|
||||
|
||||
public function __construct(){
|
||||
// Successful Responses: A server receiving a valid request MUST send a
|
||||
|
@ -47,7 +48,7 @@ class OpenIdIndirectResponse extends OpenIdResponse {
|
|||
|
||||
public function getType()
|
||||
{
|
||||
return "indirect";
|
||||
return self::OpenIdIndirectResponse;
|
||||
}
|
||||
|
||||
public function setReturnTo($return_to){
|
||||
|
|
|
@ -27,7 +27,7 @@ class Registry {
|
|||
|
||||
public function set($key, $value) {
|
||||
if (isset($this->registry[$key])) {
|
||||
throw new Exception("There is already an entry for key " . $key);
|
||||
throw new \Exception("There is already an entry for key " . $key);
|
||||
}
|
||||
|
||||
$this->registry[$key] = $value;
|
||||
|
@ -35,7 +35,7 @@ class Registry {
|
|||
|
||||
public function get($key) {
|
||||
if (!isset($this->registry[$key])) {
|
||||
throw new Exception("There is no entry for key " . $key);
|
||||
throw new \Exception("There is no entry for key " . $key);
|
||||
}
|
||||
|
||||
return $this->registry[$key];
|
||||
|
|
|
@ -9,13 +9,32 @@
|
|||
|
||||
namespace openid\strategies;
|
||||
use openid\responses\OpenIdResponse;
|
||||
use openid\responses\OpenIdDirectResponse;
|
||||
use openid\responses\OpenIdIndirectResponse;
|
||||
use openid\services\Registry;
|
||||
|
||||
class OpenIdResponseStrategyFactoryMethod {
|
||||
/**
|
||||
* @param OpenIdResponse $response
|
||||
* @return IOpenIdResponseStrategy
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function buildStrategy(OpenIdResponse $response){
|
||||
return null;
|
||||
$type = $response->getType();
|
||||
switch($type)
|
||||
{
|
||||
case OpenIdIndirectResponse::OpenIdIndirectResponse:
|
||||
{
|
||||
return Registry::getInstance()->get(OpenIdIndirectResponse::OpenIdIndirectResponse);
|
||||
}
|
||||
break;
|
||||
case OpenIdDirectResponse::OpenIdDirectResponse:
|
||||
{
|
||||
return Registry::getInstance()->get(OpenIdIndirectResponse::OpenIdDirectResponse);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new \Exception("Invalid OpenId response Type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,7 +11,8 @@ namespace services;
|
|||
use openid\model\IAssociation;
|
||||
use openid\services\IAssociationService;
|
||||
use \OpenIdAssociation;
|
||||
|
||||
use \DateTime;
|
||||
use \DateInterval;
|
||||
class AssociationService implements IAssociationService{
|
||||
|
||||
/**
|
||||
|
@ -20,8 +21,18 @@ class AssociationService implements IAssociationService{
|
|||
*/
|
||||
public function getAssociation($handle)
|
||||
{
|
||||
//todo: need to add expiration logic
|
||||
return OpenIdAssociation::where('identifier','=',$handle)->first();
|
||||
$assoc = OpenIdAssociation::where('identifier','=',$handle)->first();
|
||||
if(!is_null($assoc)){
|
||||
$issued_date = new DateTime($assoc->issued);
|
||||
$life_time = $assoc->lifetime;
|
||||
$issued_date->add(new DateInterval('PT'.$life_time.'S'));
|
||||
$now = new DateTime(gmdate("Y-m-d H:i:s", time()));
|
||||
if($now>$issued_date){
|
||||
$this->deleteAssociation($handle);
|
||||
$assoc = null;
|
||||
}
|
||||
}
|
||||
return $assoc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
namespace strategies;
|
||||
use openid\responses\OpenIdResponse;
|
||||
use openid\strategies\IOpenIdResponseStrategy;
|
||||
use \Response;
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
namespace strategies;
|
||||
use openid\strategies\IOpenIdResponseStrategy;
|
||||
use \Response;
|
||||
use \Redirect;
|
||||
|
||||
class OpenIdIndirectResponseStrategy implements IOpenIdResponseStrategy {
|
||||
|
||||
|
|
|
@ -7,13 +7,20 @@
|
|||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
namespace strategies;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use openid\responses\OpenIdIndirectResponse;
|
||||
use openid\responses\OpenIdDirectResponse;
|
||||
use openid\services\Registry;
|
||||
|
||||
class OpenIdResponseStrategyProvider extends ServiceProvider {
|
||||
|
||||
public function register()
|
||||
{
|
||||
$this->app->singleton('OpenIdDirectResponseStrategy','strategies\\OpenIdDirectResponseStrategy');
|
||||
$this->app->singleton('OpenIdIndirectResponseStrategy','strategies\\OpenIdIndirectResponseStrategy');
|
||||
$this->app->singleton(OpenIdDirectResponse::OpenIdDirectResponse,'strategies\\OpenIdDirectResponseStrategy');
|
||||
$this->app->singleton(OpenIdIndirectResponse::OpenIdIndirectResponse,'strategies\\OpenIdIndirectResponseStrategy');
|
||||
|
||||
Registry::getInstance()->set(OpenIdDirectResponse::OpenIdDirectResponse, $this->app->make(OpenIdDirectResponse::OpenIdDirectResponse));
|
||||
Registry::getInstance()->set(OpenIdIndirectResponse::OpenIdIndirectResponse, $this->app->make(OpenIdIndirectResponse::OpenIdIndirectResponse));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue