diff --git a/.idea/workspace.xml b/.idea/workspace.xml index f43a95f3..9ccd7ec7 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,41 +2,54 @@ - - - - - - + + + + + + + + + + + + + + - - + + + + + - + + + + + + - - + + - - - - + + - - + + - - + @@ -58,6 +71,11 @@ + + + + + @@ -66,10 +84,10 @@ - - + + - + @@ -77,86 +95,28 @@ - - + + - + - - + + - - - - - - - - - - - - + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -180,25 +140,26 @@ + - + + - - - - - + + + + + + + + - + + + + + + + + + + + + + @@ -568,23 +657,23 @@ - + - + + - + - + - @@ -603,6 +692,43 @@ + + + file://$PROJECT_DIR$/app/services/NonceService.php + 27 + + + file://$PROJECT_DIR$/app/services/NonceService.php + 81 + + + file://$PROJECT_DIR$/app/controllers/UserController.php + 74 + + + file://$PROJECT_DIR$/app/libs/openid/helpers/OpenIdSignatureBuilder.php + 31 + + + file://$PROJECT_DIR$/app/libs/openid/handlers/OpenIdSessionAssociationRequestHandler.php + 43 + + + file://$PROJECT_DIR$/app/libs/openid/handlers/OpenIdSessionAssociationRequestHandler.php + 84 + + + file://$PROJECT_DIR$/app/libs/openid/requests/OpenIdDHAssociationSessionRequest.php + 28 + + @@ -610,124 +736,122 @@ - - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/config/app.php b/app/config/app.php index 7a3523e1..f709b86f 100644 --- a/app/config/app.php +++ b/app/config/app.php @@ -112,11 +112,11 @@ return array( 'Illuminate\Validation\ValidationServiceProvider', 'Illuminate\View\ViewServiceProvider', 'Illuminate\Workbench\WorkbenchServiceProvider', + 'Illuminate\Redis\RedisServiceProvider', 'openid\OpenIdServiceProvider', 'auth\AuthenticationServiceProvider', 'services\ServicesProvider', 'strategies\OpenIdResponseStrategyProvider', - 'Illuminate\Redis\RedisServiceProvider', ), /* diff --git a/app/controllers/UserController.php b/app/controllers/UserController.php index 0a34be41..bcd55d80 100644 --- a/app/controllers/UserController.php +++ b/app/controllers/UserController.php @@ -64,15 +64,24 @@ class UserController extends BaseController{ $data = Input::all(); // Build the validation constraint set. $rules = array( - 'username' => 'required', + 'username' => 'required|email', 'password' => 'required' ); // Create a new validator instance. $validator = Validator::make($data, $rules); + if ($validator->passes()) { + $username = Input::get("username"); $password = Input::get("password"); - if($this->auth_service->Login($username,$password)){ + $remember = Input::get("remember"); + + if(is_null($remember)) + $remember=false; + else + $remember=true; + + if($this->auth_service->Login($username,$password,$remember)){ $msg = $this->memento_service->getCurrentRequest(); if (!is_null($msg) && $msg->IsValid()){ //go to authentication flow again diff --git a/app/database/migrations/2013_10_14_155702_create_extension_table.php b/app/database/migrations/2013_10_14_155702_create_extension_table.php index 239d65f8..20f1030f 100644 --- a/app/database/migrations/2013_10_14_155702_create_extension_table.php +++ b/app/database/migrations/2013_10_14_155702_create_extension_table.php @@ -16,9 +16,10 @@ class CreateExtensionTable extends Migration { $table->bigIncrements('id'); $table->string('name',100); $table->string('namespace',255); - $table->boolean('active'); + $table->boolean('active')->default(false); $table->string('extension_class',255); - $table->string('description',255); + $table->string('description',255)->nullable(); + $table->string('view_name',255); $table->timestamps(); }); } diff --git a/app/database/migrations/2013_10_17_210518_create_users_table.php b/app/database/migrations/2013_10_17_210518_create_users_table.php index 81de02a1..5dfd8756 100644 --- a/app/database/migrations/2013_10_17_210518_create_users_table.php +++ b/app/database/migrations/2013_10_17_210518_create_users_table.php @@ -16,10 +16,13 @@ class CreateUsersTable extends Migration { $table->bigIncrements('id'); $table->string('identifier',255); $table->string('external_id',100); - $table->boolean('active'); - $table->boolean('lock'); + $table->boolean('active')->default(true); + $table->boolean('lock')->default(false); + $table->boolean('public_profile_show_photo')->default(false); + $table->boolean('public_profile_show_fullname')->default(false); + $table->boolean('public_profile_show_email')->default(false); $table->dateTime('last_login_date'); - $table->integer('login_failed_attempt'); + $table->integer('login_failed_attempt')->default(0); $table->timestamps(); }); } diff --git a/app/database/migrations/2013_10_17_210730_create_associations_table.php b/app/database/migrations/2013_10_17_210730_create_associations_table.php index df37f303..297b2491 100644 --- a/app/database/migrations/2013_10_17_210730_create_associations_table.php +++ b/app/database/migrations/2013_10_17_210730_create_associations_table.php @@ -8,12 +8,13 @@ class CreateAssociationsTable extends Migration { { Schema::create('openid_associations', function($table) { - $table->bigIncrements('id'); + $table->bigIncrements('id')->unsigned(); $table->string('identifier',255); - $table->string('mac_function',100); + $table->string('mac_function',255); $table->string('secret',1024); + $table->string('realm',1024)->nullable(); $table->smallInteger('type'); - $table->integer('lifetime'); + $table->integer('lifetime')->unsigned(); $table->dateTime('issued'); }); } diff --git a/app/database/migrations/2013_10_17_211051_create_trusted_sites_table.php b/app/database/migrations/2013_10_17_211051_create_trusted_sites_table.php index 2cf9b9b7..c01e3921 100644 --- a/app/database/migrations/2013_10_17_211051_create_trusted_sites_table.php +++ b/app/database/migrations/2013_10_17_211051_create_trusted_sites_table.php @@ -8,10 +8,10 @@ class CreateTrustedSitesTable extends Migration { { Schema::create('openid_trusted_sites', function($table) { - $table->bigIncrements('id'); - $table->string('realm',255); - $table->string('data',1024); - $table->string('policy',100); + $table->bigIncrements('id')->unsigned(); + $table->string('realm',1024); + $table->string('data',5000)->nullable(); + $table->string('policy',255); $table->bigInteger("user_id")->unsigned(); }); } diff --git a/app/database/seeds/DatabaseSeeder.php b/app/database/seeds/DatabaseSeeder.php index 6a8c204c..d6bad526 100644 --- a/app/database/seeds/DatabaseSeeder.php +++ b/app/database/seeds/DatabaseSeeder.php @@ -11,7 +11,9 @@ class DatabaseSeeder extends Seeder { { Eloquent::unguard(); - // $this->call('UserTableSeeder'); + $this->call('OpenIdExtensionsSeeder'); + + $this->command->info('ServerExtension table seeded!'); } } \ No newline at end of file diff --git a/app/database/seeds/OpenIdExtensionsSeeder.php b/app/database/seeds/OpenIdExtensionsSeeder.php new file mode 100644 index 00000000..521502e3 --- /dev/null +++ b/app/database/seeds/OpenIdExtensionsSeeder.php @@ -0,0 +1,28 @@ +delete(); + + ServerExtension::create( + array( + 'name' => 'AX', + 'namespace' => 'http://openid.net/srv/ax/1.0', + 'active' => true, + 'extension_class' => 'openid\extensions\implementations\OpenIdAXExtension', + 'description' => 'OpenID service extension for exchanging identity information between endpoints', + 'extension_class' => 'openid\extensions\implementations\OpenIdAXExtension', + 'view_name' =>'extensions.ax', + ) + ); + } + +} diff --git a/app/libs/auth/AuthService.php b/app/libs/auth/AuthService.php index 033081c0..1e49c846 100644 --- a/app/libs/auth/AuthService.php +++ b/app/libs/auth/AuthService.php @@ -34,11 +34,12 @@ class AuthService implements IAuthService { /** * @param $username * @param $password + * @param $remember_me * @return mixed */ - public function Login($username, $password) + public function Login($username, $password,$remember_me) { - return Auth::attempt(array('username' => $username, 'password' => $password), false); + return Auth::attempt(array('username' => $username, 'password' => $password), $remember_me); } public function logout(){ diff --git a/app/libs/auth/AuthenticationServiceProvider.php b/app/libs/auth/AuthenticationServiceProvider.php index f0c3be2e..f7db817a 100644 --- a/app/libs/auth/AuthenticationServiceProvider.php +++ b/app/libs/auth/AuthenticationServiceProvider.php @@ -13,9 +13,13 @@ use openid\services\Registry; class AuthenticationServiceProvider extends ServiceProvider { - public function register() - { + public function boot(){ $this->app->singleton('openid\\services\\IAuthService','auth\\AuthService'); Registry::getInstance()->set("openid\\services\\IAuthService",$this->app->make("openid\\services\\IAuthService")); } + + public function register() + { + + } } \ No newline at end of file diff --git a/app/libs/auth/CustomAuthProvider.php b/app/libs/auth/CustomAuthProvider.php index 5943f595..71145955 100644 --- a/app/libs/auth/CustomAuthProvider.php +++ b/app/libs/auth/CustomAuthProvider.php @@ -33,6 +33,7 @@ class CustomAuthProvider implements UserProviderInterface{ */ public function retrieveById($identifier) { + //here we do the manuel join between 2 DB, (openid and SS db) $user = OpenIdUser::where('external_id', '=', $identifier)->first(); $member = Member::where('Email', '=', $identifier)->first(); if(!is_null($member) && !is_null($user)){ @@ -62,27 +63,30 @@ class CustomAuthProvider implements UserProviderInterface{ return null; $user_service = Registry::getInstance()->get("openid\\services\\IUserService"); + //get SS member $member = Member::where('Email', '=', $identifier)->first(); if(!is_null($member)){ - $res = $member->checkPassword($password); + //member must exists + $valid_password = $member->checkPassword($password); //if user does not exists, then create it if(is_null($user)){ //create user $user = new OpenIdUser(); $user->external_id = $member->Email; $user->last_login_date = gmdate("Y-m-d H:i:s", time()); - $user->login_failed_attempt = 0; - $user->active = true; - $user->lock = false; $user->Save(); } $user->setMember($member); $user_name = $member->FirstName.".".$member->Surname; + //do association between user and member $user_service->associateUser($user->id,strtolower($user_name)); + $server_configuration = Registry::getInstance()->get("openid\\services\\IServerConfigurationService"); - if(!$res){ - if($user->login_failed_attempt<$server_configuration->getMaxFailedLoginAttempts()) + + if(!$valid_password){ + //apply lock policy + if($user->login_failed_attempt < $server_configuration->getMaxFailedLoginAttempts()) $user_service->updateFailedLoginAttempts($user->id); else{ $user_service->lockUser($user->id); @@ -90,10 +94,11 @@ class CustomAuthProvider implements UserProviderInterface{ $user = null; } else{ + //update user fields $user->last_login_date = gmdate("Y-m-d H:i:s", time()); $user->login_failed_attempt = 0; - $user->active = true; - $user->lock = false; + $user->active = true; + $user->lock = false; $user->Save(); } } @@ -111,12 +116,16 @@ class CustomAuthProvider implements UserProviderInterface{ { if(!isset($credentials['username']) || !isset($credentials['password'])) throw new AuthenticationException("invalid crendentials"); + $identifier = $credentials['username']; $password = $credentials['password']; $user = OpenIdUser::where('external_id', '=', $identifier)->first(); + if(is_null($user) || $user->lock || !$user->active) return false; + $member = Member::where('Email', '=', $identifier)->first(); - return is_null($member)?false:$member->checkPassword($password); + + return !is_null($member)?$member->checkPassword($password):false; } } \ No newline at end of file diff --git a/app/libs/openid/OpenIdMessage.php b/app/libs/openid/OpenIdMessage.php index a19ce1cf..86c391a3 100644 --- a/app/libs/openid/OpenIdMessage.php +++ b/app/libs/openid/OpenIdMessage.php @@ -59,4 +59,13 @@ class OpenIdMessage implements \ArrayAccess { } return false; } + + + /** + * @param OpenIDProtocol_* $param + * @return string + */ + public function getParam($param){ + return isset($this->container[OpenIdProtocol::param($param,"_")])?$this->container[OpenIdProtocol::param($param,"_")]:null; + } } \ No newline at end of file diff --git a/app/libs/openid/OpenIdProtocol.php b/app/libs/openid/OpenIdProtocol.php index 6340277b..6b8a5fac 100644 --- a/app/libs/openid/OpenIdProtocol.php +++ b/app/libs/openid/OpenIdProtocol.php @@ -37,8 +37,12 @@ class OpenIdProtocol implements IOpenIdProtocol { const ErrorMode = "error"; const AssociateMode = "associate"; - const SignatureAlgorithmHMAC_SHA1 = "HMAC-SHA1"; - const SignatureAlgorithmHMAC_SHA256 = "HMAC-SHA256"; + const SignatureAlgorithmHMAC_SHA1 = "HMAC-SHA1"; + const SignatureAlgorithmHMAC_SHA256 = "HMAC-SHA256"; + + const AssociationSessionTypeNoEncryption = "no-encryption"; + const AssociationSessionTypeDHSHA1 = "DH-SHA1"; + const AssociationSessionTypeDHSHA256 = "DH-SHA256"; const OpenIDProtocol_Mode = "mode"; const OpenIDProtocol_NS = "ns"; @@ -56,7 +60,12 @@ class OpenIdProtocol implements IOpenIdProtocol { const OpenIDProtocol_Contact = "contact"; const OpenIDProtocol_Reference = "reference"; const OpenIDProtocol_IsValid = "is_valid"; - + const OpenIDProtocol_AssocType = "assoc_type"; + const OpenIDProtocol_SessionType = "session_type"; + const OpenIdProtocol_DHModulus = "dh_modulus"; + const OpenIdProtocol_DHGen = "dh_gen"; + const OpenIdProtocol_DHConsumerPublic = "dh_consumer_public"; + const OpenIdProtocol_ExpiresIn = "expires_in"; private static $OpenIDProtocol_ValidModes = array( @@ -87,6 +96,12 @@ class OpenIdProtocol implements IOpenIdProtocol { self::OpenIDProtocol_Contact => self::OpenIDProtocol_Contact, self::OpenIDProtocol_Reference => self::OpenIDProtocol_Reference, self::OpenIDProtocol_IsValid => self::OpenIDProtocol_IsValid, + self::OpenIDProtocol_AssocType => self::OpenIDProtocol_AssocType, + self::OpenIDProtocol_SessionType => self::OpenIDProtocol_SessionType, + self::OpenIdProtocol_DHModulus => self::OpenIdProtocol_DHModulus, + self::OpenIdProtocol_DHGen => self::OpenIdProtocol_DHGen, + self::OpenIdProtocol_DHConsumerPublic => self::OpenIdProtocol_DHConsumerPublic, + self::OpenIdProtocol_ExpiresIn => self::OpenIdProtocol_ExpiresIn, ); /** @@ -106,6 +121,7 @@ class OpenIdProtocol implements IOpenIdProtocol { public function __construct(){ //create chain of responsibility + //todo use registry here $auth_service = \App::make("openid\\services\\IAuthService"); $memento_request_service = \App::make("openid\\services\\IMementoOpenIdRequestService"); $auth_strategy = \App::make("openid\\handlers\\IOpenIdAuthenticationStrategy"); @@ -115,7 +131,7 @@ class OpenIdProtocol implements IOpenIdProtocol { $server_config_service = \App::make("openid\\services\\IServerConfigurationService"); $nonce_service = \App::make("openid\\services\\INonceService"); $check_auth = new OpenIdCheckAuthenticationRequestHandler($association_service,$nonce_service,null); - $session_assoc = new OpenIdSessionAssociationRequestHandler($check_auth); + $session_assoc = new OpenIdSessionAssociationRequestHandler($association_service,$check_auth); $this->request_handlers = new OpenIdAuthenticationRequestHandler($auth_service,$memento_request_service,$auth_strategy,$server_extension_service,$association_service,$trusted_sites_service,$server_config_service,$nonce_service,$session_assoc); } diff --git a/app/libs/openid/exceptions/InvalidNonce.php b/app/libs/openid/exceptions/InvalidNonce.php new file mode 100644 index 00000000..afc4c1a7 --- /dev/null +++ b/app/libs/openid/exceptions/InvalidNonce.php @@ -0,0 +1,19 @@ +addSignParam(OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_OpEndpoint)); + $context->addSignParam(OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm)); $context->addSignParam(OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo)); $context->addSignParam(OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Nonce)); $context->addSignParam(OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_AssocHandle)); @@ -97,8 +98,10 @@ class OpenIdAuthenticationRequestHandler extends OpenIdMessageHandler $op_endpoint = $this->server_configuration_service->getOPEndpointURL(); $identity = $this->server_configuration_service->getUserIdentityEndpointURL($currentUser->getIdentifier()); - $current_nonce = $this->nonce_service->generateNonce(); - $response = new OpenIdPositiveAssertionResponse($op_endpoint, $identity, $identity, $this->current_request->getReturnTo(),$current_nonce); + $nonce = $this->nonce_service->generateNonce(); + $realm = $this->current_request->getRealm(); + $response = new OpenIdPositiveAssertionResponse($op_endpoint, $identity, $identity, $this->current_request->getReturnTo(),$nonce->getRawFormat(),$realm); + foreach ($this->extensions as $ext) { $ext->prepareResponse($this->current_request, $response, $context); @@ -114,7 +117,8 @@ class OpenIdAuthenticationRequestHandler extends OpenIdMessageHandler $new_handle = uniqid(); $lifetime = $this->server_configuration_service->getPrivateAssociationLifetime(); $issued = gmdate("Y-m-d H:i:s", time()); - $this->association_service->addAssociation($new_handle, $new_secret,OpenIdProtocol::SignatureAlgorithmHMAC_SHA256,$lifetime, $issued,IAssociation::TypePrivate); + //create private association ... + $this->association_service->addAssociation($new_handle, $new_secret,OpenIdProtocol::SignatureAlgorithmHMAC_SHA256,$lifetime, $issued,IAssociation::TypePrivate, $realm); $response->setAssocHandle($new_handle); if (!empty($assoc_handle)) { $response->setInvalidateHandle($assoc_handle); @@ -123,13 +127,16 @@ class OpenIdAuthenticationRequestHandler extends OpenIdMessageHandler } else { $response->setAssocHandle($assoc_handle); } + + //create signature ... OpenIdSignatureBuilder::build($context, $association->getMacFunction(), $association->getSecret(), $response); /* * To prevent replay attacks, the OP MUST NOT issue more than one verification response for each * authentication response it had previously issued. An authentication response and its matching * verification request may be identified by their "openid.response_nonce" values. + * so associate $nonce with signature and realm */ - $this->nonce_service->associateNonce($current_nonce, $response->getSig()); + $this->nonce_service->associateNonce($nonce, $response->getSig(),$realm); return $response; } diff --git a/app/libs/openid/handlers/OpenIdCheckAuthenticationRequestHandler.php b/app/libs/openid/handlers/OpenIdCheckAuthenticationRequestHandler.php index 903322d1..0f745f7a 100644 --- a/app/libs/openid/handlers/OpenIdCheckAuthenticationRequestHandler.php +++ b/app/libs/openid/handlers/OpenIdCheckAuthenticationRequestHandler.php @@ -10,6 +10,8 @@ namespace openid\handlers; +use openid\exceptions\InvalidNonce; +use openid\model\OpenIdNonce; use openid\OpenIdMessage; use openid\requests\OpenIdCheckAuthenticationRequest; use openid\exceptions\InvalidOpenIdMessageException; @@ -18,9 +20,7 @@ use openid\services\IAssociationService; use openid\services\INonceService; use openid\model\IAssociation; use openid\exceptions\ReplayAttackException; -use openid\responses\contexts\ResponseContext; use openid\helpers\OpenIdSignatureBuilder; -use openid\responses\OpenIdPositiveAssertionResponse; use openid\responses\OpenIdCheckAuthenticationResponse; class OpenIdCheckAuthenticationRequestHandler extends OpenIdMessageHandler{ @@ -48,7 +48,10 @@ class OpenIdCheckAuthenticationRequestHandler extends OpenIdMessageHandler{ if(!$this->current_request->IsValid()) throw new InvalidOpenIdMessageException("OpenIdCheckAuthenticationRequest is Invalid!"); + $claimed_nonce = new OpenIdNonce($this->current_request->getNonce()); + if(!$this->nonce_service->lockNonce($claimed_nonce)) + throw new ReplayAttackException(sprintf("nonce %s already used on a formed request!",$claimed_nonce->getRawFormat())); /** * For verifying signatures an OP MUST only use private associations and MUST NOT * use associations that have shared keys. If the verification request contains a handle @@ -66,10 +69,9 @@ class OpenIdCheckAuthenticationRequestHandler extends OpenIdMessageHandler{ if(is_null($stored_assoc) || $stored_assoc->getType()!=IAssociation::TypePrivate) throw new InvalidOpenIdMessageException("OpenIdCheckAuthenticationRequest is Invalid!"); - $claimed_nonce = $this->current_request->getNonce(); + + $claimed_realm = $this->current_request->getRealm(); $claimed_sig = $this->current_request->getSig(); - $claimed_op_endpoint = $this->current_request->getOPEndpoint(); - $claimed_identity = $this->current_request->getClaimedId(); $claimed_invalidate_handle = $this->current_request->getInvalidateHandle(); if(!is_null($claimed_invalidate_handle) && !empty($claimed_invalidate_handle)){ @@ -79,10 +81,7 @@ class OpenIdCheckAuthenticationRequestHandler extends OpenIdMessageHandler{ } } - $this->nonce_service->markNonceAsInvalid($claimed_nonce,$claimed_sig); - - - + $this->nonce_service->markNonceAsInvalid($claimed_nonce,$claimed_sig,$claimed_realm); $res = OpenIdSignatureBuilder::verify($this->current_request, $stored_assoc->getMacFunction(), $stored_assoc->getSecret(),$claimed_sig); //delete association @@ -98,6 +97,10 @@ class OpenIdCheckAuthenticationRequestHandler extends OpenIdMessageHandler{ $response = new OpenIdDirectGenericErrorResponse($rEx->getMessage()); return $response; } + catch(InvalidNonce $rInvNonce){ + $response = new OpenIdDirectGenericErrorResponse($rInvNonce->getMessage()); + return $response; + } catch (InvalidOpenIdMessageException $ex) { $response = new OpenIdDirectGenericErrorResponse($ex->getMessage()); return $response; diff --git a/app/libs/openid/handlers/OpenIdMessageHandler.php b/app/libs/openid/handlers/OpenIdMessageHandler.php index fd5aae51..60aeba05 100644 --- a/app/libs/openid/handlers/OpenIdMessageHandler.php +++ b/app/libs/openid/handlers/OpenIdMessageHandler.php @@ -11,7 +11,7 @@ namespace openid\handlers; use openid\OpenIdMessage; -use Whoops\Example\Exception; +use \Exception; abstract class OpenIdMessageHandler { diff --git a/app/libs/openid/handlers/OpenIdSessionAssociationRequestHandler.php b/app/libs/openid/handlers/OpenIdSessionAssociationRequestHandler.php index 15e5d825..95bf2b88 100644 --- a/app/libs/openid/handlers/OpenIdSessionAssociationRequestHandler.php +++ b/app/libs/openid/handlers/OpenIdSessionAssociationRequestHandler.php @@ -11,16 +11,79 @@ namespace openid\handlers; use openid\OpenIdMessage; - +use openid\requests\OpenIdAssociationSessionRequest; +use openid\services\IAssociationService; +use openid\responses\OpenIdDirectGenericErrorResponse; +use openid\requests\OpenIdDHAssociationSessionRequest; +use Zend\Crypt\PublicKey\DiffieHellman; +use Zend\Crypt\Exception\InvalidArgumentException; +use \Zend\Crypt\Exception\RuntimeException; +use openid\helpers\OpenIdCryptoHelper; +use openid\OpenIdProtocol; +/** + * Class OpenIdSessionAssociationRequestHandler + * Implements http://openid.net/specs/openid-authentication-2_0.html#associations + * @package openid\handlers + */ class OpenIdSessionAssociationRequestHandler extends OpenIdMessageHandler{ - protected function InternalHandle(OpenIdMessage $message){ + private $association_service; + private $nonce_service; + private $current_request; + public function __construct(IAssociationService $association_service,$successor){ + parent::__construct($successor); + $this->association_service = $association_service; } + protected function InternalHandle(OpenIdMessage $message){ + $this->current_request = null; + try{ + + //we only implement DH + $this->current_request = new OpenIdDHAssociationSessionRequest($message); + + if(!$this->current_request->IsValid()) + throw new InvalidOpenIdMessageException("Association Session Request is Invalid!"); + $assoc_type = $this->current_request->getAssocType(); + $session_type = $this->current_request->getSessionType(); + //todo: convert $public_prime , $public_generator and $rp_public_key to string + $public_prime = $this->current_request->getDHModulus();//p + $public_generator = $this->current_request->getDHGen();//g + $rp_public_key = $this->current_request->getDHConsumerPublic(); + + $dh = new DiffieHellman($public_prime, $public_generator); + $dh->generateKeys(); + $pk = $dh->getPublicKey(); + $shared_secret = $dh->computeSecretKey($rp_public_key); + + $new_secret = OpenIdCryptoHelper::generateSecret($assoc_type); + $shared_secret = OpenIdCryptoHelper::digest($session_type,$shared_secret); + $dh_server_public = base64_encode(OpenIdCryptoHelper::btwoc($pk)); + $enc_mac_key = base64_encode($new_secret ^ $shared_secret); + $assoc_handle = uniqid(); + $expires_in = 120; + //save $assoc_handle,$expires_in,$assoc_type(mac func), and $new_secret on storage as session one or public one + + } + catch(InvalidArgumentException $exDH1){ + $response = new OpenIdDirectGenericErrorResponse($exDH1->getMessage()); + return $response; + } + catch(RuntimeException $exDH2){ + $response = new OpenIdDirectGenericErrorResponse($exDH2->getMessage()); + return $response; + } + catch (InvalidOpenIdMessageException $ex) { + $response = new OpenIdDirectGenericErrorResponse($ex->getMessage()); + return $response; + } + } + + protected function CanHandle(OpenIdMessage $message) { - $res = false; + $res = OpenIdDHAssociationSessionRequest::IsOpenIdAssociationSessionRequest($message); return $res; } } \ No newline at end of file diff --git a/app/libs/openid/helpers/OpenIdCryptoHelper.php b/app/libs/openid/helpers/OpenIdCryptoHelper.php index be5d3509..0ca1bf7e 100644 --- a/app/libs/openid/helpers/OpenIdCryptoHelper.php +++ b/app/libs/openid/helpers/OpenIdCryptoHelper.php @@ -17,7 +17,9 @@ class OpenIdCryptoHelper private static $signature_algorithms= array( OpenIdProtocol::SignatureAlgorithmHMAC_SHA1 => "sha1", + OpenIdProtocol::AssociationSessionTypeDHSHA1 => "sha1", OpenIdProtocol::SignatureAlgorithmHMAC_SHA256 => "sha256", + OpenIdProtocol::AssociationSessionTypeDHSHA256 => "sha256", ); public static function generateSecret($func) @@ -103,6 +105,10 @@ class OpenIdCryptoHelper */ static public function digest($func, $data) { + if(!isset(self::$signature_algorithms[$func])) + throw new OpenIdCrytoException(sprintf("Invalid mac function %s",$func)); + $func = self::$signature_algorithms[$func]; + if (function_exists('openssl_digest')) { return openssl_digest($data, $func, true); } else if (function_exists('hash')) { diff --git a/app/libs/openid/helpers/OpenIdSignatureBuilder.php b/app/libs/openid/helpers/OpenIdSignatureBuilder.php index 277564a6..ef1f197f 100644 --- a/app/libs/openid/helpers/OpenIdSignatureBuilder.php +++ b/app/libs/openid/helpers/OpenIdSignatureBuilder.php @@ -29,7 +29,7 @@ class OpenIdSignatureBuilder { $data = ''; foreach($claimed_signed as $key){ $key_php = str_ireplace('.','_',$key); - $val = $request->getParam('openid_'.$key_php); + $val = $request->getParam($key_php); $data .= $key . ':' . $val . "\n"; } $computed_sig = base64_encode(OpenIdCryptoHelper::computeHMAC($macAlg, $data, $secret)); diff --git a/app/libs/openid/helpers/OpenIdUriHelper.php b/app/libs/openid/helpers/OpenIdUriHelper.php index 5f9c34aa..61536bbe 100644 --- a/app/libs/openid/helpers/OpenIdUriHelper.php +++ b/app/libs/openid/helpers/OpenIdUriHelper.php @@ -535,7 +535,7 @@ class OpenIdUriHelper * @param string $trust_root The trust root to check * @return bool $sanity Whether the trust root looks OK */ - private static function isSane($trust_root) + private static function _isSane($trust_root) { $parts = self::_parse($trust_root); if ($parts === false) { @@ -608,7 +608,7 @@ class OpenIdUriHelper public static function checkRealm($trust_root, $url) { if (!filter_var($url, FILTER_VALIDATE_URL)) return false; - if (!self::isSane($trust_root)) return false; + if (!self::_isSane($trust_root)) return false; $trust_root_parsed = self::_parse($trust_root); $url_parsed = self::_parse($url); @@ -674,4 +674,8 @@ class OpenIdUriHelper } return true; } + + public static function isValidUrl($url){ + return filter_var($url, FILTER_VALIDATE_URL); + } } \ No newline at end of file diff --git a/app/libs/openid/model/IAssociation.php b/app/libs/openid/model/IAssociation.php index 706d7ac0..eae88536 100644 --- a/app/libs/openid/model/IAssociation.php +++ b/app/libs/openid/model/IAssociation.php @@ -30,6 +30,9 @@ interface IAssociation { public function getType(); public function setType($type); + public function getRealm(); + public function setRealm($realm); + public function IsExpired(); } \ No newline at end of file diff --git a/app/libs/openid/model/OpenIdNonce.php b/app/libs/openid/model/OpenIdNonce.php new file mode 100644 index 00000000..b702f4c1 --- /dev/null +++ b/app/libs/openid/model/OpenIdNonce.php @@ -0,0 +1,84 @@ +timestamp = $timestamp; + $this->unique_id = $unique_id; + $this->raw_format = $nonce_str; + } + + public function getRawFormat(){ + return $this->raw_format; + } + + public function getTimestamp(){ + return $this->timestamp; + } + + public function getUniqueId(){ + return $this->$unique_id; + } + + /** + * The time-stamp MAY be used to reject responses that are too far away from the current time, + * limiting the amount of time that nonces must be stored to prevent attacks. + * The acceptable range is out of the scope of this specification. + * A larger range requires storing more nonces for a longer time. + * A shorter range increases the chance that clock-skew and transaction time will cause + * a spurious rejection. + */ + public function isValid(){ + $server_configuration_service = Registry::getInstance()->get("openid\\services\\IServerConfigurationService"); + $allowed_skew = $server_configuration_service->getNonceLifetime(); + $now = time(); + // Time after which we should not use the nonce + $past = $now - $allowed_skew; + // Time that is too far in the future for us to allow + $future = $now + $allowed_skew; + + // the stamp is not too far in the future and is not too far + // in the past + return (($past <= $this->timestamp) && ($this->timestamp <= $future)); + } +} \ No newline at end of file diff --git a/app/libs/openid/requests/OpenIdAssociationSessionRequest.php b/app/libs/openid/requests/OpenIdAssociationSessionRequest.php new file mode 100644 index 00000000..ef41d65a --- /dev/null +++ b/app/libs/openid/requests/OpenIdAssociationSessionRequest.php @@ -0,0 +1,41 @@ +getParam(OpenIdProtocol::OpenIDProtocol_AssocType); + } + + public function getSessionType(){ + return $this->getParam(OpenIdProtocol::OpenIDProtocol_SessionType); + } + + public static function IsOpenIdAssociationSessionRequest(OpenIdMessage $message){ + $mode = $message->getMode(); + if($mode==OpenIdProtocol::AssociateMode) return true; + return false; + } +} \ No newline at end of file diff --git a/app/libs/openid/requests/OpenIdAuthenticationRequest.php b/app/libs/openid/requests/OpenIdAuthenticationRequest.php index f6d93229..9c5a6ef4 100644 --- a/app/libs/openid/requests/OpenIdAuthenticationRequest.php +++ b/app/libs/openid/requests/OpenIdAuthenticationRequest.php @@ -27,40 +27,29 @@ class OpenIdAuthenticationRequest extends OpenIdRequest { } public function getClaimedId(){ - return isset($this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId,"_")])?$this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId,"_")]:null; + return $this->getParam(OpenIdProtocol::OpenIDProtocol_ClaimedId); } public function getIdentity(){ - return isset($this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity,"_")])?$this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity,"_")]:null; + return $this->getParam(OpenIdProtocol::OpenIDProtocol_Identity); } public function getAssocHandle(){ - return isset($this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_AssocHandle,"_")])?$this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_AssocHandle,"_")]:null; + return $this->getParam(OpenIdProtocol::OpenIDProtocol_AssocHandle); } public function getReturnTo(){ - $return_to = isset($this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo,"_")])?$this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo,"_")]:null; + $return_to = $this->getParam(OpenIdProtocol::OpenIDProtocol_ReturnTo); return (OpenIdUriHelper::checkReturnTo($return_to))?$return_to:""; } public function getRealm(){ - return isset($this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm,"_")])?$this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm,"_")]:null; + $realm = $this->getParam(OpenIdProtocol::OpenIDProtocol_Realm); + return $realm; } - public function getTrustedRoot() { - if (isset($this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm,"_")])) { - $root = $this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm,"_")]; - } else if (isset($this[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo,"_")])) { - $root = $this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo,"_")]; - } else { - return null; - } - if (OpenIdUriHelper::normalizeUrl($root) && !empty($root)) { - return $root; - } - return null; - } + /** * @param $claimed_id @@ -70,7 +59,7 @@ class OpenIdAuthenticationRequest extends OpenIdRequest { private function isValidIdentifier($claimed_id,$identity){ if($claimed_id==$identity && $identity==OpenIdProtocol::IdentifierSelectType && $claimed_id==OpenIdProtocol::IdentifierSelectType) return true; - if($claimed_id==$identity){ + if($claimed_id==$identity && OpenIdUriHelper::isValidUrl($identity)){ //todo: check valid user? return true; } diff --git a/app/libs/openid/requests/OpenIdCheckAuthenticationRequest.php b/app/libs/openid/requests/OpenIdCheckAuthenticationRequest.php index 66cf8adc..024c1b4e 100644 --- a/app/libs/openid/requests/OpenIdCheckAuthenticationRequest.php +++ b/app/libs/openid/requests/OpenIdCheckAuthenticationRequest.php @@ -11,6 +11,8 @@ namespace openid\requests; use openid\OpenIdProtocol; use openid\OpenIdMessage; +use openid\helpers\OpenIdUriHelper; +use openid\services\Registry; class OpenIdCheckAuthenticationRequest extends OpenIdAuthenticationRequest { @@ -26,32 +28,47 @@ class OpenIdCheckAuthenticationRequest extends OpenIdAuthenticationRequest { public function IsValid() { - $mode = $this->getMode(); - $claimed_assoc = $this->getAssocHandle(); - if($mode== OpenIdProtocol::CheckAuthenticationMode - && !is_null($claimed_assoc) && !empty($claimed_assoc)){ + $mode = $this->getMode(); + $claimed_assoc = $this->getAssocHandle(); + $claimed_nonce = $this->getNonce(); + $claimed_sig = $this->getSig(); + $claimed_op_endpoint = $this->getOPEndpoint(); + $claimed_identity = $this->getClaimedId(); + $claimed_realm = $this->getRealm(); + $claimed_returnTo = $this->getReturnTo(); + $server_configuration_service = Registry::getInstance()->get("openid\\services\\IServerConfigurationService"); + if( + !is_null($mode) && !empty($mode) && $mode== OpenIdProtocol::CheckAuthenticationMode + && !is_null($claimed_returnTo) && !empty($claimed_returnTo) && OpenIdUriHelper::checkReturnTo($claimed_returnTo) + && !is_null($claimed_realm) && !empty($claimed_realm) && OpenIdUriHelper::checkRealm($claimed_realm,$claimed_returnTo) + && !is_null($claimed_assoc) && !empty($claimed_assoc) + && !is_null($claimed_sig) && !empty($claimed_sig) + && !is_null($claimed_nonce) && !empty($claimed_nonce) + && !is_null($claimed_op_endpoint) && !empty($claimed_op_endpoint) && $server_configuration_service->getOPEndpointURL() == $claimed_op_endpoint + && !is_null($claimed_identity) && !empty($claimed_identity) && OpenIdUriHelper::isValidUrl($claimed_identity) + ){ return true; } return false; } public function getSig(){ - return $this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Sig,"_")]; + return $this->getParam(OpenIdProtocol::OpenIDProtocol_Sig); } public function getSigned(){ - return $this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Signed,"_")]; + return $this->getParam(OpenIdProtocol::OpenIDProtocol_Signed); } public function getNonce(){ - return $this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Nonce,"_")]; + return $this->getParam(OpenIdProtocol::OpenIDProtocol_Nonce); } public function getOPEndpoint(){ - return $this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_OpEndpoint,"_")]; + return $this->getParam(OpenIdProtocol::OpenIDProtocol_OpEndpoint); } public function getInvalidateHandle(){ - return $this->message[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_InvalidateHandle,"_")]; + return $this->getParam(OpenIdProtocol::OpenIDProtocol_InvalidateHandle); } -} \ No newline at end of file +} diff --git a/app/libs/openid/requests/OpenIdDHAssociationSessionRequest.php b/app/libs/openid/requests/OpenIdDHAssociationSessionRequest.php new file mode 100644 index 00000000..06fdedce --- /dev/null +++ b/app/libs/openid/requests/OpenIdDHAssociationSessionRequest.php @@ -0,0 +1,61 @@ +getDHModulus(); + $dh_gen = $this->getDHGen(); + $dh_consumer_public = $this->getDHConsumerPublic(); + if(!empty($dh_modulus) && !empty($dh_gen) && !empty($dh_consumer_public)) + return true; + return true; + } + + public function getDHModulus(){ + $p = $this->getParam(OpenIdProtocol::OpenIdProtocol_DHModulus); + return empty($p)?pack('H*', OpenIdDHAssociationSessionRequest::DH_P): base64_decode($p); + } + + public function getDHGen(){ + $g = $this->getParam(OpenIdProtocol::OpenIdProtocol_DHGen); + return empty($g)?pack('H*', OpenIdDHAssociationSessionRequest::DH_G): base64_decode($g); + } + + public function getDHConsumerPublic(){ + $pk = $this->getParam(OpenIdProtocol::OpenIdProtocol_DHConsumerPublic); + return empty($pk)?"": base64_decode($pk); + } + + public static function IsOpenIdDHAssociationSessionRequest(OpenIdMessage $message){ + if(OpenIdAssociationSessionRequest::IsOpenIdAssociationSessionRequest($message)){ + $session_type = $message->getParam(OpenIdProtocol::OpenIDProtocol_AssocType); + if($session_type==OpenIdProtocol::AssociationSessionTypeDHSHA1 || $session_type==OpenIdProtocol::AssociationSessionTypeDHSHA256) + return true; + } + return false; + } + +} \ No newline at end of file diff --git a/app/libs/openid/requests/OpenIdRequest.php b/app/libs/openid/requests/OpenIdRequest.php index c2057d34..9ef23143 100644 --- a/app/libs/openid/requests/OpenIdRequest.php +++ b/app/libs/openid/requests/OpenIdRequest.php @@ -28,7 +28,12 @@ abstract class OpenIdRequest { abstract public function IsValid(); - public function getParam($param){ - return $this->message[$param]; - } + + /** + * @param OpenIDProtocol_* $param + * @return string + */ + public function getParam($param){ + return $this->message->getParam($param); + } } \ No newline at end of file diff --git a/app/libs/openid/responses/OpenIdAssociationSessionResponse.php b/app/libs/openid/responses/OpenIdAssociationSessionResponse.php new file mode 100644 index 00000000..a471d8b4 --- /dev/null +++ b/app/libs/openid/responses/OpenIdAssociationSessionResponse.php @@ -0,0 +1,40 @@ +setMode(OpenIdProtocol::IdMode); $this[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_OpEndpoint)] = $op_endpoint; @@ -22,6 +22,7 @@ class OpenIdPositiveAssertionResponse extends OpenIdIndirectResponse { $this[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity)] = $identity; $this[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo)] = $return_to; $this[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Nonce)] = $nonce; + $this[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm)] = $realm; } diff --git a/app/libs/openid/responses/OpenIdUnencryptedAssociationSessionResponse.php b/app/libs/openid/responses/OpenIdUnencryptedAssociationSessionResponse.php new file mode 100644 index 00000000..04299d0c --- /dev/null +++ b/app/libs/openid/responses/OpenIdUnencryptedAssociationSessionResponse.php @@ -0,0 +1,16 @@ +realm; + } + + public function setRealm($realm) + { + // TODO: Implement setRealm() method. + } } \ No newline at end of file diff --git a/app/services/AssociationService.php b/app/services/AssociationService.php index 43025ac5..3b75bf74 100644 --- a/app/services/AssociationService.php +++ b/app/services/AssociationService.php @@ -8,22 +8,45 @@ */ namespace services; +use openid\exceptions\ReplayAttackException; use openid\model\IAssociation; use openid\services\IAssociationService; use \OpenIdAssociation; use \DateTime; use \DateInterval; +use openid\exceptions\OpenIdInvalidRealmException; + class AssociationService implements IAssociationService{ + private $redis; + + public function __construct(){ + $this->redis = \RedisLV4::connection(); + } + /** * @param $handle - * @return IAssociation + * @param null $realm + * @return null|IAssociation + * @throws \openid\exceptions\ReplayAttackException + * @throws \openid\exceptions\OpenIdInvalidRealmException */ - public function getAssociation($handle) + public function getAssociation($handle, $realm=null) { $assoc = OpenIdAssociation::where('identifier','=',$handle)->first(); if(!is_null($assoc)){ $issued_date = new DateTime($assoc->issued); + if($assoc->type == IAssociation::TypePrivate && !is_null($realm) && !empty($realm)){ + if($assoc->realm!=$realm){ + throw new OpenIdInvalidRealmException(sprintf("Private Association %s was not emit for requested realm %s",$handle,$realm)); + } + $cur_time = time(); + $lock_lifetime = 180; + $success = $this->redis->setnx('lock.'.$handle,$cur_time+$lock_lifetime+1); + if(!$success){ + throw new ReplayAttackException(sprintf("Private Association %s already used",$handle)); + } + } $life_time = $assoc->lifetime; $issued_date->add(new DateInterval('PT'.$life_time.'S')); $now = new DateTime(gmdate("Y-m-d H:i:s", time())); @@ -39,15 +62,17 @@ class AssociationService implements IAssociationService{ * @param IAssociation $association * @return bool */ - public function addAssociation($handle, $secret,$mac_function, $lifetime, $issued,$type) + public function addAssociation($handle, $secret,$mac_function, $lifetime, $issued,$type,$realm=null) { $assoc = new OpenIdAssociation(); - $assoc->identifier = $handle; - $assoc->secret = $secret; - $assoc->type = $type; + $assoc->identifier = $handle; + $assoc->secret = $secret; + $assoc->type = $type; $assoc->mac_function = $mac_function; - $assoc->lifetime = $lifetime; - $assoc->issued = $issued; + $assoc->lifetime = $lifetime; + $assoc->issued = $issued; + if(!is_null($realm)) + $assoc->realm = $realm; $assoc->Save(); } diff --git a/app/services/Facades/ServerConfigurationService.php b/app/services/Facades/ServerConfigurationService.php new file mode 100644 index 00000000..532bff32 --- /dev/null +++ b/app/services/Facades/ServerConfigurationService.php @@ -0,0 +1,14 @@ +redis = \RedisLV4::connection(); } - public function generateNonce() - { - $nonce = gmdate('Y-m-d\TH:i:s\Z') . uniqid(); - //sets the $nonce to live 60 secs - $this->redis->setex($nonce,3600 ,''); - return $nonce; + /** + * @param OpenIdNonce $nonce + * @return bool + */ + public function lockNonce(OpenIdNonce $nonce){ + $raw_nonce = $nonce->getRawFormat(); + $cur_time = time(); + $lock_lifetime = \ServerConfigurationService::getNonceLifetime();; + return $this->redis->setnx('lock.'.$raw_nonce,$cur_time+$lock_lifetime+1); + } + + public function unlockNonce(OpenIdNonce $nonce){ + $raw_nonce = $nonce->getRawFormat(); + $this->redis->del('lock.'.$raw_nonce); } /** - * @param $nonce - * @param $signature - * @throws \openid\exceptions\ReplayAttackException + * @return OpenIdNonce */ - public function markNonceAsInvalid($nonce, $signature) + public function generateNonce() { - $old_signature = $this->redis->get($nonce); - if(!$old_signature){ - throw new ReplayAttackException(sprintf("nonce %s was already used!.",$nonce)); - } - if($old_signature!=$signature){ - throw new ReplayAttackException(sprintf("nonce %s was associated with sig %s, but sig %s was provided.",$nonce,$old_signature,$signature)); - } - $this->redis->del($nonce); + $raw_nonce = gmdate('Y-m-d\TH:i:s\Z') . uniqid(); + return new OpenIdNonce($raw_nonce); } - public function associateNonce($nonce, $signature) + /** + * @param OpenIdNonce $nonce + * @param string $signature + * @param string $realm + * @return mixed|void + * @throws \openid\exceptions\ReplayAttackException + */ + public function markNonceAsInvalid(OpenIdNonce $nonce, $signature, $realm) { - $this->redis->setex($nonce,3600,$signature); + $raw_nonce = $nonce->getRawFormat(); + $key = $raw_nonce.$signature; + + try{ + if($this->redis->exists($key)==0) + throw new ReplayAttackException(sprintf("nonce %s was already used!.",$nonce)); + $old_realm = $this->redis->get($key); + if($realm!=$old_realm){ + throw new ReplayAttackException(sprintf("nonce %s was not emit for realm !.",$realm)); + } + $this->redis->del($key); + } + catch(ReplayAttackException $ex){ + $this->redis->del($key); + throw $ex; + } + } + + /** + * @param OpenIdNonce $nonce + * @param string $signature + * @param string $realm + */ + public function associateNonce(OpenIdNonce $nonce, $signature,$realm) + { + $raw_nonce = $nonce->getRawFormat(); + $lifetime = \ServerConfigurationService::getNonceLifetime(); + $this->redis->setex($raw_nonce.$signature,$lifetime,$realm); } } \ No newline at end of file diff --git a/app/services/ServerConfigurationService.php b/app/services/ServerConfigurationService.php index aaf0a209..3fb0064a 100644 --- a/app/services/ServerConfigurationService.php +++ b/app/services/ServerConfigurationService.php @@ -36,4 +36,8 @@ class ServerConfigurationService implements IServerConfigurationService{ public function getMaxFailedLoginAttempts(){ return 3; } + + public function getNonceLifetime(){ + return 360; + } } \ No newline at end of file diff --git a/app/services/ServicesProvider.php b/app/services/ServicesProvider.php index 692b1898..2a042aaa 100644 --- a/app/services/ServicesProvider.php +++ b/app/services/ServicesProvider.php @@ -14,13 +14,10 @@ use Illuminate\Redis\Database; class ServicesProvider extends ServiceProvider { - public function register() - { - $this->app['redis'] = $this->app->share(function($app) - { - return new Database($app['config']['database.redis']); - }); + public function boot(){ + + //register on boot bc we rely on Illuminate\Redis\ServiceProvider\RedisServiceProvider $this->app->singleton('openid\\services\\IMementoOpenIdRequestService','services\\MementoRequestService'); $this->app->singleton('openid\\handlers\\IOpenIdAuthenticationStrategy','services\\AuthenticationStrategy'); @@ -41,8 +38,19 @@ class ServicesProvider extends ServiceProvider { Registry::getInstance()->set("openid\\services\\INonceService",\App::make("openid\\services\\INonceService")); } - public function provides() + public function register() { - return array('redis'); + $this->app['serverconfigurationservice'] = $this->app->share(function($app) + { + return new ServerConfigurationService(); + }); + + // Shortcut so developers don't need to add an Alias in app/config/app.php + $this->app->booting(function() + { + $loader = \Illuminate\Foundation\AliasLoader::getInstance(); + $loader->alias('ServerConfigurationService', 'services\\Facades\\ServerConfigurationService'); + }); } + } \ No newline at end of file diff --git a/app/start/global.php b/app/start/global.php index fc912c03..5ee992cf 100644 --- a/app/start/global.php +++ b/app/start/global.php @@ -60,7 +60,7 @@ App::error(function(Exception $exception, $code) App::error(function(openid\exceptions\InvalidOpenIdMessageException $exception, $code) { Log::error($exception); - return View::make('error')->with('error', $exception->getMessage()); + return View::make('404'); }); /* diff --git a/app/views/consent.blade.php b/app/views/consent.blade.php index 1d741880..3913a1d0 100644 --- a/app/views/consent.blade.php +++ b/app/views/consent.blade.php @@ -1,7 +1,7 @@ @extends('layout') @section('content')
- {{ Form::open(array('url' => '/accounts/user/consent', 'method' => 'post', "autocomplete" => "off")) }} + {{ Form::open(array('url' => '/accounts/user/consent','id'=>'authorization_form', 'method' => 'post', "autocomplete" => "off")) }} @@ -16,11 +16,23 @@ {{ Form::label("deny_forever","Deny Forever")}} {{ Form::radio('trust[]', 'DenyForever','',array('id'=>'deny_forever')) }}
- {{ Form::submit('Ok') }} - {{ Form::submit('Cancel') }} + {{ Form::submit('Ok',array("id"=>"send_authorization",'class'=>'btn')) }} + {{ Form::button('Cancel',array('id'=>'cancel_authorization','class'=>'btn cancel_authorization')) }} {{ Form::close() }} @foreach ($views as $view) {{ $view}} @endforeach +@section('scripts') + @stop \ No newline at end of file diff --git a/app/views/extensions/ax.blade.php b/app/views/extensions/ax.blade.php index 9bc48bfe..ee1b1e6f 100644 --- a/app/views/extensions/ax.blade.php +++ b/app/views/extensions/ax.blade.php @@ -1,7 +1,7 @@ @if(count($attributes)>0)
    @foreach ($attributes as $attr) -
  • {{$attr}}
  • +
  • {{$attr}} 
  • @endforeach
@endif \ No newline at end of file diff --git a/app/views/layout.blade.php b/app/views/layout.blade.php index f0e57eeb..0368d77f 100644 --- a/app/views/layout.blade.php +++ b/app/views/layout.blade.php @@ -4,12 +4,16 @@ OpenstackId Idp {{ HTML::style('css/bootstrap.css') }} - {{ HTML::script('js/jquery-2.0.3.min.js')}} + -
+
+ @yield('content') +
+
+
+ {{ HTML::script('js/jquery-2.0.3.min.js')}} {{ HTML::script('js/bootstrap.min.js')}} @yield('scripts') diff --git a/app/views/login.blade.php b/app/views/login.blade.php index 20009d9d..39789c20 100644 --- a/app/views/login.blade.php +++ b/app/views/login.blade.php @@ -1,30 +1,41 @@ @extends('layout') @section('content') -

Login

-
- {{ Form::open(array('url' => '/accounts/user/login', 'method' => 'post', "autocomplete" => "off")) }} -
    - @foreach($errors->all() as $message) -
  • {{ $message }}
  • - @endforeach -
- -
- {{ Form::label('username', 'user') }} - {{ Form::text('username') }} -
-
- {{ Form::label('password', 'password') }} - {{ Form::password('password') }} -
-
- {{ Form::label('remember', 'remember me') }} - {{ Form::checkbox('remember', '1', false) }} -
- {{ Form::submit('Login') }} - @if(Session::has('flash_notice')) -
{{ Session::get('flash_notice') }}
- @endif - {{ Form::close() }} + + +
+ +
+ @stop \ No newline at end of file