Implements: blueprint openid-oauth2-authentication-integration-with-openid
[smarcet] - #5037 - Authentication Integration with OpenID custom Idp Change-Id: Ifb704254fa7274b169eb858a2596c9e5651ac76e
This commit is contained in:
parent
e602939754
commit
89bc75eb8c
|
@ -113,12 +113,12 @@ return array(
|
|||
'Illuminate\View\ViewServiceProvider',
|
||||
'Illuminate\Workbench\WorkbenchServiceProvider',
|
||||
'Illuminate\Redis\RedisServiceProvider',
|
||||
'openid\OpenIdServiceProvider',
|
||||
'auth\AuthenticationServiceProvider',
|
||||
'services\ServicesProvider',
|
||||
'strategies\StrategyProvider',
|
||||
'oauth2\OAuth2ServiceProvider',
|
||||
'openid\OpenIdServiceProvider',
|
||||
'Greggilbert\Recaptcha\RecaptchaServiceProvider',
|
||||
'oauth2\OAuth2ServiceProvider'
|
||||
),
|
||||
|
||||
/*
|
||||
|
|
|
@ -113,10 +113,11 @@ return array(
|
|||
'Illuminate\View\ViewServiceProvider',
|
||||
'Illuminate\Workbench\WorkbenchServiceProvider',
|
||||
'Illuminate\Redis\RedisServiceProvider',
|
||||
'openid\OpenIdServiceProvider',
|
||||
'auth\AuthenticationServiceProvider',
|
||||
'services\ServicesProvider',
|
||||
'strategies\StrategyProvider',
|
||||
'auth\AuthenticationServiceProvider',
|
||||
'oauth2\OAuth2ServiceProvider',
|
||||
'openid\OpenIdServiceProvider',
|
||||
'Greggilbert\Recaptcha\RecaptchaServiceProvider',
|
||||
),
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ return array(
|
|||
|
|
||||
*/
|
||||
|
||||
'url' => 'http://localhost',
|
||||
'url' => 'https://dev.openstackid.com',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
@ -113,10 +113,11 @@ return array(
|
|||
'Illuminate\View\ViewServiceProvider',
|
||||
'Illuminate\Workbench\WorkbenchServiceProvider',
|
||||
'Illuminate\Redis\RedisServiceProvider',
|
||||
'openid\OpenIdServiceProvider',
|
||||
'auth\AuthenticationServiceProvider',
|
||||
'services\ServicesProvider',
|
||||
'strategies\StrategyProvider',
|
||||
'oauth2\OAuth2ServiceProvider',
|
||||
'openid\OpenIdServiceProvider',
|
||||
'Greggilbert\Recaptcha\RecaptchaServiceProvider',
|
||||
),
|
||||
|
||||
|
|
|
@ -1,105 +0,0 @@
|
|||
<?php
|
||||
|
||||
return array(
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| PDO Fetch Style
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| By default, database results will be returned as instances of the PHP
|
||||
| stdClass object; however, you may desire to retrieve records in an
|
||||
| array format for simplicity. Here you can tweak the fetch style.
|
||||
|
|
||||
*/
|
||||
|
||||
'fetch' => PDO::FETCH_CLASS,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Default Database Connection Name
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here you may specify which of the database connections below you wish
|
||||
| to use as your default connection for all database work. Of course
|
||||
| you may use many connections at once using the Database library.
|
||||
|
|
||||
*/
|
||||
|
||||
'default' => 'mysql',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Database Connections
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Here are each of the database connections setup for your application.
|
||||
| Of course, examples of configuring each database platform that is
|
||||
| supported by Laravel is shown below to make development simple.
|
||||
|
|
||||
|
|
||||
| All database work in Laravel is done through the PHP PDO facilities
|
||||
| so make sure you have the driver for your particular database of
|
||||
| choice installed on your machine before you begin development.
|
||||
|
|
||||
*/
|
||||
|
||||
'connections' => array(
|
||||
'mysql' => array(
|
||||
'driver' => 'mysql',
|
||||
'host' => 'localhost',
|
||||
'database' => 'openstackid',
|
||||
'username' => 'root',
|
||||
'password' => 'Koguryo@1981',
|
||||
'charset' => 'utf8',
|
||||
'collation' => 'utf8_unicode_ci',
|
||||
'prefix' => '',
|
||||
),
|
||||
'mysql_external' => array(
|
||||
'driver' => 'mysql',
|
||||
'host' => 'localhost',
|
||||
'database' => '506635_oslive',
|
||||
'username' => 'root',
|
||||
'password' => 'Koguryo@1981',
|
||||
'charset' => 'utf8',
|
||||
'collation' => 'utf8_unicode_ci',
|
||||
'prefix' => '',
|
||||
),
|
||||
),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Migration Repository Table
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This table keeps track of all the migrations that have already run for
|
||||
| your application. Using this information, we can determine which of
|
||||
| the migrations on disk have not actually be run in the databases.
|
||||
|
|
||||
*/
|
||||
|
||||
'migrations' => 'migrations',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Redis Databases
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Redis is an open source, fast, and advanced key-value store that also
|
||||
| provides a richer set of commands than a typical key-value systems
|
||||
| such as APC or Memcached. Laravel makes it easy to dig right in.
|
||||
|
|
||||
*/
|
||||
|
||||
'redis' => array(
|
||||
|
||||
'cluster' => true,
|
||||
|
||||
'default' => array(
|
||||
'host' => '127.0.0.1',
|
||||
'port' => 6379,
|
||||
),
|
||||
|
||||
),
|
||||
|
||||
);
|
|
@ -6,16 +6,35 @@ class ApiScopeSeeder extends Seeder {
|
|||
{
|
||||
DB::table('oauth2_api_scope')->delete();
|
||||
|
||||
$resource_server_api = Api::where('name','=','resource server api')->first();
|
||||
$resource_server_api_create = Api::where('name','=','create resource server')->first();
|
||||
$resource_server_api_get = Api::where('name','=','get resource server')->first();
|
||||
$resource_server_api_get_page = Api::where('name','=','resource server get page')->first();
|
||||
$resource_server_api_regenerate = Api::where('name','=','resource server regenerate secret')->first();
|
||||
$resource_server_api_delete = Api::where('name','=','resource server delete')->first();
|
||||
$resource_server_api_update = Api::where('name','=','resource server update')->first();
|
||||
$resource_server_api_update_status = Api::where('name','=','resource server update status')->first();
|
||||
|
||||
$current_realm = Config::get('app.url');
|
||||
|
||||
|
||||
// create api scopes
|
||||
|
||||
ApiScope::create(
|
||||
array(
|
||||
'name' => sprintf('%s/api/resource-server/read',$current_realm),
|
||||
'short_description' => 'Resource Server Read Access',
|
||||
'description' => 'Resource Server Read Access',
|
||||
'api_id' => $resource_server_api->id,
|
||||
'api_id' => $resource_server_api_get->id,
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
ApiScope::create(
|
||||
array(
|
||||
'name' => sprintf('%s/api/resource-server/read.page',$current_realm),
|
||||
'short_description' => 'Resource Server Page Read Access',
|
||||
'description' => 'Resource Server Page Read Access',
|
||||
'api_id' => $resource_server_api_get_page->id,
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -24,6 +43,43 @@ class ApiScopeSeeder extends Seeder {
|
|||
'name' => sprintf('%s/api/resource-server/write',$current_realm),
|
||||
'short_description' => 'Resource Server Write Access',
|
||||
'description' => 'Resource Server Write Access',
|
||||
'api_id' => $resource_server_api_create->id,
|
||||
)
|
||||
);
|
||||
|
||||
ApiScope::create(
|
||||
array(
|
||||
'name' => sprintf('%s/api/resource-server/delete',$current_realm),
|
||||
'short_description' => 'Resource Server Delete Access',
|
||||
'description' => 'Resource Server Delete Access',
|
||||
'api_id' => $resource_server_api_delete->id,
|
||||
)
|
||||
);
|
||||
|
||||
ApiScope::create(
|
||||
array(
|
||||
'name' => sprintf('%s/api/resource-server/update',$current_realm),
|
||||
'short_description' => 'Resource Server Update Access',
|
||||
'description' => 'Resource Server Update Access',
|
||||
'api_id' => $resource_server_api_update->id,
|
||||
)
|
||||
);
|
||||
|
||||
ApiScope::create(
|
||||
array(
|
||||
'name' => sprintf('%s/api/resource-server/update.status',$current_realm),
|
||||
'short_description' => 'Resource Server Update Status',
|
||||
'description' => 'Resource Server Update Status',
|
||||
'api_id' => $resource_server_api_update_status->id,
|
||||
)
|
||||
);
|
||||
|
||||
ApiScope::create(
|
||||
array(
|
||||
'name' => sprintf('%s/api/resource-server/regenerate.secret',$current_realm),
|
||||
'short_description' => 'Resource Server Regenerate Client Secret',
|
||||
'description' => 'Resource Server Regenerate Client Secret',
|
||||
'api_id' => $resource_server_api_regenerate->id,
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -6,15 +6,82 @@ class ApiSeeder extends Seeder {
|
|||
DB::table('oauth2_api')->delete();
|
||||
|
||||
$resource_server = ResourceServer::first();
|
||||
//create api endpoints
|
||||
|
||||
Api::create(
|
||||
array(
|
||||
'name' => 'get resource server api',
|
||||
'logo' => null,
|
||||
'active' => true,
|
||||
'name' => 'create resource server',
|
||||
'logo' => null,
|
||||
'active' => true,
|
||||
'resource_server_id' => $resource_server->id,
|
||||
'route' => '/api/v1/resource-server/{id}',
|
||||
'http_method' => 'GET'
|
||||
'route' => '/api/v1/resource-server',
|
||||
'http_method' => 'POST'
|
||||
)
|
||||
);
|
||||
|
||||
Api::create(
|
||||
array(
|
||||
'name' => 'get resource server',
|
||||
'logo' => null,
|
||||
'active' => true,
|
||||
'resource_server_id' => $resource_server->id,
|
||||
'route' => '/api/v1/resource-server/{id}',
|
||||
'http_method' => 'GET'
|
||||
)
|
||||
);
|
||||
|
||||
Api::create(
|
||||
array(
|
||||
'name' => 'resource server regenerate secret',
|
||||
'logo' => null,
|
||||
'active' => true,
|
||||
'resource_server_id' => $resource_server->id,
|
||||
'route' => '/api/v1/resource-server/regenerate-client-secret/{id}',
|
||||
'http_method' => 'GET'
|
||||
)
|
||||
);
|
||||
|
||||
Api::create(
|
||||
array(
|
||||
'name' => 'resource server get page',
|
||||
'logo' => null,
|
||||
'active' => true,
|
||||
'resource_server_id' => $resource_server->id,
|
||||
'route' => '/api/v1/resource-server/{page_nbr}/{page_size}',
|
||||
'http_method' => 'GET'
|
||||
)
|
||||
);
|
||||
|
||||
Api::create(
|
||||
array(
|
||||
'name' => 'resource server delete',
|
||||
'logo' => null,
|
||||
'active' => true,
|
||||
'resource_server_id' => $resource_server->id,
|
||||
'route' => '/api/v1/resource-server/{id}',
|
||||
'http_method' => 'DELETE'
|
||||
)
|
||||
);
|
||||
|
||||
Api::create(
|
||||
array(
|
||||
'name' => 'resource server update',
|
||||
'logo' => null,
|
||||
'active' => true,
|
||||
'resource_server_id' => $resource_server->id,
|
||||
'route' => '/api/v1/resource-server',
|
||||
'http_method' => 'PUT'
|
||||
)
|
||||
);
|
||||
|
||||
Api::create(
|
||||
array(
|
||||
'name' => 'resource server update status',
|
||||
'logo' => null,
|
||||
'active' => true,
|
||||
'resource_server_id' => $resource_server->id,
|
||||
'route' => '/api/v1/resource-server/status/{id}/{active}',
|
||||
'http_method' => 'GET'
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: smarcet
|
||||
* Date: 10/25/13
|
||||
* Time: 1:34 PM
|
||||
*/
|
||||
|
||||
class OpenIdExtensionsSeeder extends Seeder {
|
||||
|
||||
|
@ -33,6 +27,18 @@ class OpenIdExtensionsSeeder extends Seeder {
|
|||
'view_name' => 'extensions.sreg',
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
ServerExtension::create(
|
||||
array(
|
||||
'name' => 'OAUTH2',
|
||||
'namespace' => 'http://specs.openid.net/extensions/oauth/2.0',
|
||||
'active' => true,
|
||||
'extension_class' => 'openid\extensions\implementations\OpenIdOAuth2Extension',
|
||||
'description' => 'The OpenID OAuth2 Extension describes how to make the OpenID Authentication and OAuth2 Core specifications work well togethe',
|
||||
'view_name' => 'extensions.oauth2',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
<?php
|
||||
|
||||
use oauth2\models\IClient;
|
||||
use auth\OpenIdUser;
|
||||
|
||||
use auth\User;
|
||||
use utils\services\IAuthService;
|
||||
/**
|
||||
* Class OAuth2ApplicationSeeder
|
||||
* This seeder is only for testing purposes
|
||||
|
@ -14,16 +14,19 @@ class TestSeeder extends Seeder {
|
|||
|
||||
Eloquent::unguard();
|
||||
|
||||
DB::table('banned_ips')->delete();
|
||||
DB::table('user_exceptions_trail')->delete();
|
||||
DB::table('server_configuration')->delete();
|
||||
DB::table('server_extensions')->delete();
|
||||
DB::table('oauth2_client_api_scope')->delete();
|
||||
DB::table('oauth2_api_scope')->delete();
|
||||
DB::table('oauth2_api')->delete();
|
||||
DB::table('oauth2_client_authorized_uri')->delete();
|
||||
DB::table('oauth2_client_api_scope')->delete();
|
||||
DB::table('oauth2_access_token')->delete();
|
||||
DB::table('oauth2_refresh_token')->delete();
|
||||
DB::table('oauth2_client')->delete();
|
||||
DB::table('openid_trusted_sites')->delete();
|
||||
DB::table('openid_associations')->delete();
|
||||
DB::table('openid_users')->delete();
|
||||
DB::table('oauth2_resource_server')->delete();
|
||||
|
||||
|
@ -236,6 +239,17 @@ class TestSeeder extends Seeder {
|
|||
)
|
||||
);
|
||||
|
||||
ServerExtension::create(
|
||||
array(
|
||||
'name' => 'OAUTH2',
|
||||
'namespace' => 'http://specs.openid.net/extensions/oauth/2.0',
|
||||
'active' => true,
|
||||
'extension_class' => 'openid\extensions\implementations\OpenIdOAuth2Extension',
|
||||
'description' => 'The OpenID OAuth2 Extension describes how to make the OpenID Authentication and OAuth2 Core specifications work well togethe',
|
||||
'view_name' => 'extensions.oauth2',
|
||||
)
|
||||
);
|
||||
|
||||
ResourceServer::create(
|
||||
array(
|
||||
'friendly_name' => 'test resource server',
|
||||
|
@ -404,7 +418,7 @@ class TestSeeder extends Seeder {
|
|||
);
|
||||
|
||||
// create users and clients ...
|
||||
OpenIdUser::create(
|
||||
User::create(
|
||||
array(
|
||||
'identifier'=>'sebastian.marcet',
|
||||
'external_id'=>'smarcet@gmail.com',
|
||||
|
@ -412,7 +426,15 @@ class TestSeeder extends Seeder {
|
|||
)
|
||||
);
|
||||
|
||||
$user = OpenIdUser::where('external_id','=','smarcet@gmail.com')->first();
|
||||
$user = User::where('external_id','=','smarcet@gmail.com')->first();
|
||||
|
||||
OpenIdTrustedSite::create(
|
||||
array(
|
||||
'user_id'=>$user->id,
|
||||
'realm'=>'https://www.test.com/',
|
||||
'policy'=>IAuthService::AuthorizationResponse_AllowForever
|
||||
)
|
||||
);
|
||||
|
||||
Client::create(
|
||||
array(
|
||||
|
|
|
@ -48,12 +48,17 @@ class AuthService implements IAuthService
|
|||
{
|
||||
if (Session::has("openid.authorization.response")) {
|
||||
$value = Session::get("openid.authorization.response");
|
||||
Session::remove('openid.authorization.response');
|
||||
return $value;
|
||||
}
|
||||
return IAuthService::AuthorizationResponse_None;
|
||||
}
|
||||
|
||||
public function clearUserAuthorizationResponse(){
|
||||
if (Session::has("openid.authorization.response")) {
|
||||
Session::remove("openid.authorization.response");
|
||||
}
|
||||
}
|
||||
|
||||
public function setUserAuthorizationResponse($auth_response)
|
||||
{
|
||||
//todo : check valid response
|
||||
|
@ -62,13 +67,13 @@ class AuthService implements IAuthService
|
|||
|
||||
public function getUserByOpenId($openid)
|
||||
{
|
||||
$user = OpenIdUser::where('identifier', '=', $openid)->first();
|
||||
$user = User::where('identifier', '=', $openid)->first();
|
||||
return $user;
|
||||
}
|
||||
|
||||
public function getUserByUsername($username)
|
||||
{
|
||||
$user = OpenIdUser::where('external_id', '=', $username)->first();
|
||||
$user = User::where('external_id', '=', $username)->first();
|
||||
return $user;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
namespace auth;
|
||||
|
||||
/**
|
||||
* Class AuthenticationExtensionService
|
||||
* @package auth
|
||||
*/
|
||||
class AuthenticationExtensionService implements IAuthenticationExtensionService {
|
||||
|
||||
private $extensions;
|
||||
|
||||
public function __construct(){
|
||||
$this->extensions = array();
|
||||
}
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getExtensions()
|
||||
{
|
||||
return $this->extensions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param IAuthenticationExtension $extension
|
||||
* @return bool
|
||||
*/
|
||||
public function addExtension(IAuthenticationExtension $extension)
|
||||
{
|
||||
array_push($this->extensions, $extension);
|
||||
}
|
||||
}
|
|
@ -14,6 +14,9 @@ class AuthenticationServiceProvider extends ServiceProvider
|
|||
{
|
||||
$this->app->singleton(UtilsServiceCatalog::AuthenticationService, 'auth\\AuthService');
|
||||
Registry::getInstance()->set(UtilsServiceCatalog::AuthenticationService, $this->app->make(UtilsServiceCatalog::AuthenticationService));
|
||||
|
||||
$this->app->singleton('auth\\IAuthenticationExtensionService', 'auth\\AuthenticationExtensionService');
|
||||
Registry::getInstance()->set('auth\\IAuthenticationExtensionService', $this->app->make('auth\\IAuthenticationExtensionService'));
|
||||
}
|
||||
|
||||
public function register()
|
||||
|
|
|
@ -4,23 +4,29 @@
|
|||
namespace auth;
|
||||
use auth\exceptions\AuthenticationException;
|
||||
use auth\exceptions\AuthenticationInvalidPasswordAttemptException;
|
||||
use auth\exceptions\AuthenticationLockedUserLoginAttempt;
|
||||
use Exception;
|
||||
use Illuminate\Auth\UserInterface;
|
||||
use Illuminate\Auth\UserProviderInterface;
|
||||
use Log;
|
||||
use Member;
|
||||
use openid\helpers\OpenIdErrorMessages;
|
||||
use openid\requests\OpenIdAuthenticationRequest;
|
||||
use openid\services\OpenIdServiceCatalog;
|
||||
use utils\services\Registry;
|
||||
use utils\services\UtilsServiceCatalog;
|
||||
use DB;
|
||||
|
||||
/**
|
||||
* Class CustomAuthProvider
|
||||
* Custom Authentication Provider against SS DB
|
||||
* @package auth
|
||||
*/
|
||||
class CustomAuthProvider implements UserProviderInterface
|
||||
{
|
||||
|
||||
private $auth_extension_service;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
public function __construct(IAuthenticationExtensionService $auth_extension_service){
|
||||
$this->auth_extension_service = $auth_extension_service;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,7 +39,7 @@ class CustomAuthProvider implements UserProviderInterface
|
|||
{
|
||||
try {
|
||||
//here we do the manuel join between 2 DB, (openid and SS db)
|
||||
$user = OpenIdUser::where('external_id', '=', $identifier)->first();
|
||||
$user = User::where('external_id', '=', $identifier)->first();
|
||||
$member = Member::where('Email', '=', $identifier)->first();
|
||||
if (!is_null($member) && !is_null($user)) {
|
||||
$user->setMember($member);
|
||||
|
@ -54,96 +60,85 @@ class CustomAuthProvider implements UserProviderInterface
|
|||
*/
|
||||
public function retrieveByCredentials(array $credentials)
|
||||
{
|
||||
|
||||
$user = null;
|
||||
try {
|
||||
DB::transaction(function () use ($credentials, &$user) {
|
||||
|
||||
if (!isset($credentials['username']) || !isset($credentials['password']))
|
||||
throw new AuthenticationException("invalid crendentials");
|
||||
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();
|
||||
$identifier = $credentials['username'];
|
||||
$password = $credentials['password'];
|
||||
$user = User::where('external_id', '=', $identifier)->first();
|
||||
|
||||
//check user status...
|
||||
if (!is_null($user) && ($user->lock || !$user->active)){
|
||||
Log::warning(sprintf("user %s is on lock state",$identifier));
|
||||
return null;
|
||||
}
|
||||
//check user status...
|
||||
if (!is_null($user) && ($user->lock || !$user->active)){
|
||||
Log::warning(sprintf("user %s is on lock state",$identifier));
|
||||
throw new AuthenticationLockedUserLoginAttempt($identifier,sprintf("user %s is on lock state",$identifier));
|
||||
}
|
||||
|
||||
//get SS member
|
||||
$member = Member::where('Email', '=', $identifier)->first();
|
||||
if (is_null($member)) //member must exists
|
||||
throw new AuthenticationException(sprintf("member %s does not exists!", $identifier));
|
||||
//get SS member
|
||||
$member = Member::where('Email', '=', $identifier)->first();
|
||||
if (is_null($member)) //member must exists
|
||||
throw new AuthenticationException(sprintf("member %s does not exists!", $identifier));
|
||||
|
||||
$valid_password = $member->checkPassword($password);
|
||||
$valid_password = $member->checkPassword($password);
|
||||
|
||||
if(!$valid_password)
|
||||
throw new AuthenticationInvalidPasswordAttemptException($identifier,sprintf("invalid login attempt for user %s ",$identifier));
|
||||
if(!$valid_password)
|
||||
throw new AuthenticationInvalidPasswordAttemptException($identifier,sprintf("invalid login attempt for user %s ",$identifier));
|
||||
|
||||
//if user does not exists, then create it
|
||||
if (is_null($user)) {
|
||||
//create user
|
||||
$user = new OpenIdUser();
|
||||
$user->external_id = $member->Email;
|
||||
$user->identifier = $member->Email;
|
||||
$user->last_login_date = gmdate("Y-m-d H:i:s", time());
|
||||
//if user does not exists, then create it
|
||||
if (is_null($user)) {
|
||||
//create user
|
||||
$user = new User();
|
||||
$user->external_id = $member->Email;
|
||||
$user->identifier = $member->Email;
|
||||
$user->last_login_date = gmdate("Y-m-d H:i:s", time());
|
||||
$user->Save();
|
||||
$user = User::where('external_id', '=', $identifier)->first();
|
||||
}
|
||||
|
||||
$user_service = Registry::getInstance()->get(OpenIdServiceCatalog::UserService);
|
||||
|
||||
$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(UtilsServiceCatalog::ServerConfigurationService);
|
||||
|
||||
//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->Save();
|
||||
$user = OpenIdUser::where('external_id', '=', $identifier)->first();
|
||||
}
|
||||
|
||||
$user_service = Registry::getInstance()->get(OpenIdServiceCatalog::UserService);
|
||||
//reload user...
|
||||
$user = User::where('external_id', '=', $identifier)->first();
|
||||
$user->setMember($member);
|
||||
|
||||
$user_name = $member->FirstName . "." . $member->Surname;
|
||||
//do association between user and member
|
||||
$user_service->associateUser($user->id, strtolower($user_name));
|
||||
$auth_extensions = $this->auth_extension_service->getExtensions();
|
||||
|
||||
$server_configuration = Registry::getInstance()->get(OpenIdServiceCatalog::ServerConfigurationService);
|
||||
|
||||
//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->Save();
|
||||
|
||||
//reload user...
|
||||
$user = OpenIdUser::where('external_id', '=', $identifier)->first();
|
||||
$user->setMember($member);
|
||||
|
||||
//check if we have a current openid message
|
||||
$memento_service = Registry::getInstance()->get(OpenIdServiceCatalog::MementoService);
|
||||
$msg = $memento_service->getCurrentRequest();
|
||||
if (is_null($msg) || !$msg->isValid() || !OpenIdAuthenticationRequest::IsOpenIdAuthenticationRequest($msg))
|
||||
return $user;
|
||||
else {
|
||||
//check if current user is has the same identity that the one claimed on openid message
|
||||
$auth_request = new OpenIdAuthenticationRequest($msg);
|
||||
if ($auth_request->isIdentitySelectByOP())
|
||||
return $user;
|
||||
$claimed_id = $auth_request->getClaimedId();
|
||||
$identity = $auth_request->getIdentity();
|
||||
$current_identity = $server_configuration->getUserIdentityEndpointURL($user->getIdentifier());
|
||||
if ($claimed_id == $current_identity || $identity == $current_identity)
|
||||
return $user;
|
||||
Log::warning(sprintf(OpenIdErrorMessages::AlreadyExistSessionMessage, $current_identity, $identity));
|
||||
//if not return fail ( we cant log in with a different user that the one stated on the authentication message!
|
||||
return null;
|
||||
}
|
||||
|
||||
} catch (Exception $ex) {
|
||||
foreach($auth_extensions as $auth_extension){
|
||||
$auth_extension->process($user);
|
||||
}
|
||||
});
|
||||
} catch (Exception $ex) {
|
||||
$checkpoint_service = Registry::getInstance()->get(UtilsServiceCatalog::CheckPointService);
|
||||
$checkpoint_service->trackException($ex);
|
||||
Log::error($ex);
|
||||
return null;
|
||||
$user = null;
|
||||
}
|
||||
return $user;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate a user against the given credentials.
|
||||
*
|
||||
* @param \Illuminate\Auth\UserInterface $user
|
||||
* @param array $credentials
|
||||
* @param UserInterface $user
|
||||
* @param array $credentials
|
||||
* @return bool
|
||||
* @throws exceptions\AuthenticationException
|
||||
*/
|
||||
public function validateCredentials(UserInterface $user, array $credentials)
|
||||
{
|
||||
|
@ -152,8 +147,8 @@ class CustomAuthProvider implements UserProviderInterface
|
|||
|
||||
try {
|
||||
$identifier = $credentials['username'];
|
||||
$password = $credentials['password'];
|
||||
$user = OpenIdUser::where('external_id', '=', $identifier)->first();
|
||||
$password = $credentials['password'];
|
||||
$user = User::where('external_id', '=', $identifier)->first();
|
||||
|
||||
if (is_null($user) || $user->lock || !$user->active)
|
||||
return false;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace auth;
|
||||
|
||||
|
||||
interface IAuthenticationExtension {
|
||||
|
||||
public function process(User $user);
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace auth;
|
||||
|
||||
/**
|
||||
* Interface IAuthenticationExtensionService
|
||||
* @package auth
|
||||
*/
|
||||
interface IAuthenticationExtensionService {
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getExtensions();
|
||||
|
||||
/**
|
||||
* @param IAuthenticationExtension $extension
|
||||
* @return bool
|
||||
*/
|
||||
public function addExtension(IAuthenticationExtension $extension);
|
||||
}
|
|
@ -9,8 +9,9 @@ use openid\model\IOpenIdUser;
|
|||
use openid\services\OpenIdServiceCatalog;
|
||||
use utils\services\Registry;
|
||||
use oauth2\models\IOAuth2User;
|
||||
use Eloquent;
|
||||
|
||||
class OpenIdUser extends \Eloquent implements UserInterface, IOpenIdUser, IOAuth2User
|
||||
class User extends Eloquent implements UserInterface, IOpenIdUser, IOAuth2User
|
||||
{
|
||||
|
||||
protected $table = 'openid_users';
|
|
@ -9,7 +9,7 @@ class AuthenticationException extends Exception
|
|||
|
||||
public function __construct($message = "")
|
||||
{
|
||||
$message = "AuthenticationException : " . $message;
|
||||
$message = "Authentication Exception : " . $message;
|
||||
parent::__construct($message, 0, null);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ class AuthenticationInvalidPasswordAttemptException extends Exception
|
|||
|
||||
public function __construct($identifier,$message = "")
|
||||
{
|
||||
$message = "AuthenticationInvalidPasswordAttemptException : " . $message;
|
||||
$message = "Invalid Password Attempt: " . $message;
|
||||
$this->identifier = $identifier;
|
||||
parent::__construct($message, 0, null);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace auth\exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class AuthenticationLockedUserLoginAttempt extends Exception
|
||||
{
|
||||
|
||||
private $identifier;
|
||||
|
||||
public function __construct($identifier,$message = "")
|
||||
{
|
||||
$message = "Locked User Login Attempt : " . $message;
|
||||
$this->identifier = $identifier;
|
||||
parent::__construct($message, 0, null);
|
||||
}
|
||||
|
||||
public function getIdentifier(){
|
||||
return $this->identifier;
|
||||
}
|
||||
|
||||
}
|
|
@ -114,7 +114,7 @@ class OAuth2Protocol implements IOAuth2Protocol
|
|||
* http://tools.ietf.org/html/rfc6749#appendix-A
|
||||
* VSCHAR = %x20-7E
|
||||
*/
|
||||
const VsChar = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz*-.:_|~';
|
||||
const VsChar = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-_~';
|
||||
|
||||
//services
|
||||
private $log_service;
|
||||
|
|
|
@ -1,17 +1,16 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: smarcet
|
||||
* Date: 12/3/13
|
||||
* Time: 10:25 AM
|
||||
*/
|
||||
|
||||
namespace oauth2;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use utils\services\Registry;
|
||||
|
||||
class OAuth2ServiceProvider extends ServiceProvider
|
||||
{
|
||||
public function boot()
|
||||
{
|
||||
Registry::getInstance()->set('oauth2\IOAuth2Protocol', $this->app->make('oauth2\IOAuth2Protocol'));
|
||||
}
|
||||
|
||||
public function register()
|
||||
{
|
||||
|
|
|
@ -33,7 +33,7 @@ use utils\services\ILogService;
|
|||
/**
|
||||
* Class AuthorizationCodeGrantType
|
||||
* Authorization Code Grant Implementation
|
||||
* The authorization code grant type is used to obtain both access
|
||||
* The authorization code grant type is used to obtain both access
|
||||
* tokens and refresh tokens and is optimized for confidential clients.
|
||||
* Since this is a redirection-based flow, the client must be capable of
|
||||
* interacting with the resource owner's user-agent (typically a web
|
||||
|
@ -131,6 +131,7 @@ class AuthorizationCodeGrantType extends AbstractGrantType
|
|||
} else if ($authorization_response === IAuthService::AuthorizationResponse_DenyOnce) {
|
||||
throw new AccessDeniedException;
|
||||
}
|
||||
|
||||
// build current audience ...
|
||||
$audience = $this->scope_service->getStrAudienceByScopeNames(explode(' ',$scope));
|
||||
|
||||
|
@ -138,8 +139,10 @@ class AuthorizationCodeGrantType extends AbstractGrantType
|
|||
|
||||
if (is_null($auth_code))
|
||||
throw new OAuth2GenericException("Invalid Auth Code");
|
||||
|
||||
return new OAuth2AuthorizationResponse($redirect_uri, $auth_code->getValue(), $state);
|
||||
// clear save data ...
|
||||
$this->auth_service->clearUserAuthorizationResponse();
|
||||
$this->memento_service->clearCurrentRequest();
|
||||
return new OAuth2AuthorizationResponse($redirect_uri, $auth_code->getValue() , $scope, $state);
|
||||
}
|
||||
throw new InvalidOAuth2Request;
|
||||
}
|
||||
|
|
|
@ -148,7 +148,9 @@ class ImplicitGrantType extends AbstractGrantType
|
|||
$audience = $this->scope_service->getStrAudienceByScopeNames(explode(' ',$scope));
|
||||
//build access token
|
||||
$access_token = $this->token_service->createAccessTokenFromParams($scope, $client_id, $audience);
|
||||
|
||||
//clear saved data ...
|
||||
$this->memento_service->clearCurrentRequest();
|
||||
$this->auth_service->clearUserAuthorizationResponse();
|
||||
return new OAuth2AccessTokenFragmentResponse($redirect_uri, $access_token->getValue(), $access_token->getLifetime(), $scope, $state);
|
||||
}
|
||||
throw new InvalidOAuth2Request;
|
||||
|
|
|
@ -27,6 +27,7 @@ class AccessToken extends Token {
|
|||
$instance->auth_code = $auth_code->getValue();
|
||||
$instance->audience = $auth_code->getAudience();
|
||||
$instance->lifetime = $lifetime;
|
||||
$instance->is_hashed = false;
|
||||
return $instance;
|
||||
}
|
||||
|
||||
|
@ -39,6 +40,7 @@ class AccessToken extends Token {
|
|||
$instance->audience = $audience;
|
||||
$instance->refresh_token = null;
|
||||
$instance->lifetime = $lifetime;
|
||||
$instance->is_hashed = false;
|
||||
return $instance;
|
||||
}
|
||||
|
||||
|
@ -52,10 +54,11 @@ class AccessToken extends Token {
|
|||
$instance->refresh_token = $refresh_token;
|
||||
$instance->audience = $refresh_token->getAudience();
|
||||
$instance->lifetime = $lifetime;
|
||||
$instance->is_hashed = false;
|
||||
return $instance;
|
||||
}
|
||||
|
||||
public static function load($value, AuthorizationCode $auth_code, $issued = null, $lifetime = 3600){
|
||||
public static function load($value, AuthorizationCode $auth_code, $issued = null, $lifetime = 3600, $is_hashed=false){
|
||||
$instance = new self();
|
||||
$instance->value = $value;
|
||||
$instance->scope = $auth_code->getScope();
|
||||
|
@ -65,6 +68,7 @@ class AccessToken extends Token {
|
|||
$instance->from_ip = $auth_code->getFromIp();
|
||||
$instance->issued = $issued;
|
||||
$instance->lifetime = $lifetime;
|
||||
$instance->is_hashed = $is_hashed;
|
||||
return $instance;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace oauth2\models;
|
||||
|
||||
use services\IPHelper;
|
||||
use Zend\Math\Rand;
|
||||
use oauth2\OAuth2Protocol;
|
||||
/**
|
||||
|
@ -33,10 +34,12 @@ class AuthorizationCode extends Token {
|
|||
$instance->client_id = $client_id;
|
||||
$instance->lifetime = $lifetime;
|
||||
$instance->audience = $audience;
|
||||
$instance->is_hashed = false;
|
||||
$instance->from_ip = IPHelper::getUserIp();
|
||||
return $instance;
|
||||
}
|
||||
|
||||
public static function load($value, $client_id, $scope,$audience='', $redirect_uri = null, $issued = null, $lifetime = 600, $from_ip = '127.0.0.1'){
|
||||
public static function load($value, $client_id, $scope,$audience='', $redirect_uri = null, $issued = null, $lifetime = 600, $from_ip = '127.0.0.1',$is_hashed = false){
|
||||
$instance = new self();
|
||||
$instance->value = $value;
|
||||
$instance->scope = $scope;
|
||||
|
@ -46,6 +49,7 @@ class AuthorizationCode extends Token {
|
|||
$instance->issued = $issued;
|
||||
$instance->lifetime = $lifetime;
|
||||
$instance->from_ip = $from_ip;
|
||||
$instance->is_hashed = $is_hashed;
|
||||
return $instance;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ class RefreshToken extends Token {
|
|||
$instance->audience = $access_token->getAudience();
|
||||
$instance->from_ip = IPHelper::getUserIp();
|
||||
$instance->lifetime = $lifetime;
|
||||
$instance->is_hashed = false;
|
||||
return $instance;
|
||||
}
|
||||
|
||||
|
@ -52,6 +53,7 @@ class RefreshToken extends Token {
|
|||
$instance->audience = $params['audience'];
|
||||
$instance->from_ip = $params['from_ip'];
|
||||
$instance->issued = $params['issued'];
|
||||
$instance->is_hashed = isset($params['is_hashed'])?$params['is_hashed']:false;
|
||||
$instance->lifetime = $lifetime;
|
||||
return $instance;
|
||||
}
|
||||
|
|
|
@ -22,11 +22,13 @@ abstract class Token
|
|||
protected $scope;
|
||||
protected $audience;
|
||||
protected $from_ip;
|
||||
protected $is_hashed;
|
||||
|
||||
public function __construct($len = self::DefaultByteLength)
|
||||
{
|
||||
$this->len = $len;
|
||||
$this->issued = gmdate("Y-m-d H:i:s", time());
|
||||
$this->len = $len;
|
||||
$this->is_hashed = false;
|
||||
$this->issued = gmdate("Y-m-d H:i:s", time());
|
||||
}
|
||||
|
||||
public function getIssued()
|
||||
|
@ -78,7 +80,12 @@ abstract class Token
|
|||
return $seconds;
|
||||
}
|
||||
|
||||
public function isHashed(){
|
||||
return $this->is_hashed;
|
||||
}
|
||||
|
||||
public abstract function toJSON();
|
||||
|
||||
|
||||
public abstract function fromJSON($json);
|
||||
}
|
|
@ -10,14 +10,35 @@ use oauth2\OAuth2Protocol;
|
|||
*/
|
||||
class OAuth2AuthorizationResponse extends OAuth2IndirectResponse {
|
||||
|
||||
|
||||
public function __construct($return_url, $code, $state=null)
|
||||
/**
|
||||
* @param $return_url
|
||||
* @param $code
|
||||
* @param null $scope
|
||||
* @param null $state
|
||||
*/
|
||||
public function __construct($return_url, $code, $scope=null, $state=null)
|
||||
{
|
||||
parent::__construct();
|
||||
$this[OAuth2Protocol::OAuth2Protocol_ResponseType_Code] = $code;
|
||||
$this->setReturnTo($return_url);
|
||||
|
||||
if(!is_null($scope))
|
||||
$this[OAuth2Protocol::OAuth2Protocol_Scope] = $scope;
|
||||
|
||||
if(!is_null($state))
|
||||
$this[OAuth2Protocol::OAuth2Protocol_State] = $state;
|
||||
}
|
||||
|
||||
public function getAuthCode(){
|
||||
return isset($this[OAuth2Protocol::OAuth2Protocol_ResponseType_Code])?$this[OAuth2Protocol::OAuth2Protocol_ResponseType_Code] :null;
|
||||
}
|
||||
|
||||
public function getState(){
|
||||
return isset($this[OAuth2Protocol::OAuth2Protocol_State])?$this[OAuth2Protocol::OAuth2Protocol_State] :null;
|
||||
}
|
||||
|
||||
public function getScope(){
|
||||
return isset($this[OAuth2Protocol::OAuth2Protocol_Scope])?$this[OAuth2Protocol::OAuth2Protocol_Scope] :null;
|
||||
}
|
||||
|
||||
}
|
|
@ -9,7 +9,18 @@ use openid\services\OpenIdServiceCatalog;
|
|||
use openid\XRDS\XRDSDocumentBuilder;
|
||||
use openid\XRDS\XRDSService;
|
||||
use utils\services\Registry;
|
||||
use utils\services\UtilsServiceCatalog;
|
||||
//services
|
||||
use utils\services\ILogService;
|
||||
use openid\services\IMementoOpenIdRequestService;
|
||||
use openid\handlers\IOpenIdAuthenticationStrategy;
|
||||
use openid\services\IServerExtensionsService;
|
||||
use openid\services\IAssociationService;
|
||||
use openid\services\ITrustedSitesService;
|
||||
use openid\services\IServerConfigurationService;
|
||||
use openid\services\INonceService;
|
||||
use utils\services\IAuthService;
|
||||
use utils\services\ICheckPointService;
|
||||
|
||||
|
||||
/**
|
||||
* Class OpenIdProtocol
|
||||
|
@ -64,9 +75,11 @@ class OpenIdProtocol implements IOpenIdProtocol
|
|||
const OpenIdProtocol_DHServerPublic = "dh_server_public";
|
||||
const OpenIdProtocol_DHEncMacKey = "enc_mac_key";
|
||||
const OpenIdProtocol_MacKey = "mac_key";
|
||||
|
||||
private static $OpenIDProtocol_SupportedAssocType = array(
|
||||
self::SignatureAlgorithmHMAC_SHA1,
|
||||
self::SignatureAlgorithmHMAC_SHA256
|
||||
self::SignatureAlgorithmHMAC_SHA256,
|
||||
self::AssociationSessionTypeNoEncryption,
|
||||
);
|
||||
private static $OpenIDProtocol_SupportedSessionType = array(
|
||||
self::AssociationSessionTypeNoEncryption,
|
||||
|
@ -111,25 +124,26 @@ class OpenIdProtocol implements IOpenIdProtocol
|
|||
self::OpenIdProtocol_DHEncMacKey => self::OpenIdProtocol_DHEncMacKey,
|
||||
self::OpenIdProtocol_MacKey => self::OpenIdProtocol_MacKey,
|
||||
);
|
||||
|
||||
private $request_handlers;
|
||||
|
||||
public function __construct()
|
||||
|
||||
public function __construct(
|
||||
IAuthService $auth_service,
|
||||
IMementoOpenIdRequestService $memento_request_service,
|
||||
IOpenIdAuthenticationStrategy $auth_strategy,
|
||||
IServerExtensionsService $server_extension_service,
|
||||
IAssociationService $association_service,
|
||||
ITrustedSitesService $trusted_sites_service,
|
||||
IServerConfigurationService $server_config_service,
|
||||
INonceService $nonce_service,
|
||||
ILogService $log_service,
|
||||
ICheckPointService $checkpoint_service)
|
||||
{
|
||||
//create chain of responsibility
|
||||
|
||||
$auth_service = Registry::getInstance()->get(UtilsServiceCatalog::AuthenticationService);
|
||||
$memento_request_service = Registry::getInstance()->get(OpenIdServiceCatalog::MementoService);
|
||||
$auth_strategy = Registry::getInstance()->get(OpenIdServiceCatalog::AuthenticationStrategy);
|
||||
$server_extension_service = Registry::getInstance()->get(OpenIdServiceCatalog::ServerExtensionsService);
|
||||
$association_service = Registry::getInstance()->get(OpenIdServiceCatalog::AssociationService);
|
||||
$trusted_sites_service = Registry::getInstance()->get(OpenIdServiceCatalog::TrustedSitesService);
|
||||
$server_config_service = Registry::getInstance()->get(OpenIdServiceCatalog::ServerConfigurationService);
|
||||
$nonce_service = Registry::getInstance()->get(OpenIdServiceCatalog::NonceService);
|
||||
$log = Registry::getInstance()->get(UtilsServiceCatalog::LogService);
|
||||
|
||||
$check_auth = new OpenIdCheckAuthenticationRequestHandler($association_service, $nonce_service, $log, null);
|
||||
$session_assoc = new OpenIdSessionAssociationRequestHandler($log, $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, $log, $session_assoc);
|
||||
$check_auth = new OpenIdCheckAuthenticationRequestHandler($association_service, $nonce_service, $log_service,$checkpoint_service, null);
|
||||
$session_assoc = new OpenIdSessionAssociationRequestHandler($log_service,$checkpoint_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, $log_service,$checkpoint_service, $session_assoc);
|
||||
}
|
||||
|
||||
public static function isAssocTypeSupported($assoc_type)
|
||||
|
@ -154,7 +168,7 @@ class OpenIdProtocol implements IOpenIdProtocol
|
|||
|
||||
public static function param($param, $separator = '.')
|
||||
{
|
||||
return self::OpenIdPrefix . $separator . self::$protocol_definition[$param];
|
||||
return self::OpenIdPrefix . $separator . $param ;
|
||||
}
|
||||
|
||||
public function getXRDSDiscovery($mode, $canonical_id = null)
|
||||
|
@ -179,4 +193,4 @@ class OpenIdProtocol implements IOpenIdProtocol
|
|||
{
|
||||
return $this->request_handlers->handleMessage($openIdMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
namespace openid;
|
||||
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use openid\extensions\OpenIdAuthenticationExtension;
|
||||
use openid\services\OpenIdServiceCatalog;
|
||||
use utils\services\UtilsServiceCatalog;
|
||||
|
||||
/**
|
||||
* Class OpenIdServiceProvider
|
||||
|
@ -12,8 +15,26 @@ use Illuminate\Support\ServiceProvider;
|
|||
class OpenIdServiceProvider extends ServiceProvider
|
||||
{
|
||||
|
||||
public function register()
|
||||
public function boot()
|
||||
{
|
||||
$this->app->bind('openid\IOpenIdProtocol', 'openid\OpenIdProtocol');
|
||||
|
||||
$auth_extension_service = $this->app->make('auth\\IAuthenticationExtensionService');
|
||||
|
||||
if(!is_null($auth_extension_service)){
|
||||
$memento_service = $this->app->make(OpenIdServiceCatalog::MementoService);
|
||||
$server_configuration_service = $this->app->make(UtilsServiceCatalog::ServerConfigurationService);
|
||||
$auth_extension_service->addExtension(new OpenIdAuthenticationExtension($memento_service,$server_configuration_service));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the service provider.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function register()
|
||||
{
|
||||
// TODO: Implement register() method.
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
<?php
|
||||
|
||||
namespace openid\exceptions;
|
||||
|
||||
use Exception;
|
||||
|
||||
class InvalidAssociation extends Exception
|
||||
{
|
||||
|
||||
public function __construct($message = "")
|
||||
{
|
||||
$message = "Invalid Association: " . $message;
|
||||
parent::__construct($message, 0, null);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,10 +1,4 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: smarcet
|
||||
* Date: 10/28/13
|
||||
* Time: 6:03 PM
|
||||
*/
|
||||
|
||||
namespace openid\exceptions;
|
||||
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
namespace openid\extensions;
|
||||
|
||||
use auth\exceptions\AuthenticationException;
|
||||
use auth\IAuthenticationExtension;
|
||||
use auth\User;
|
||||
use openid\helpers\OpenIdErrorMessages;
|
||||
use openid\requests\OpenIdAuthenticationRequest;
|
||||
use openid\services\IServerConfigurationService;
|
||||
use openid\services\IMementoOpenIdRequestService;
|
||||
|
||||
/**
|
||||
* Class OpenIdAuthenticationExtension
|
||||
* @package openid\extensions
|
||||
*/
|
||||
class OpenIdAuthenticationExtension implements IAuthenticationExtension
|
||||
{
|
||||
private $memento_service;
|
||||
private $server_configuration;
|
||||
|
||||
/**
|
||||
* @param IMementoOpenIdRequestService $memento_service
|
||||
* @param IServerConfigurationService $server_configuration
|
||||
*/
|
||||
public function __construct(IMementoOpenIdRequestService $memento_service, IServerConfigurationService $server_configuration){
|
||||
$this->server_configuration = $server_configuration;
|
||||
$this->memento_service = $memento_service;
|
||||
}
|
||||
|
||||
public function process(User $user)
|
||||
{
|
||||
//check if we have a current openid message
|
||||
$msg = $this->memento_service->getCurrentRequest();
|
||||
if (!is_null($msg) && $msg->isValid() && OpenIdAuthenticationRequest::IsOpenIdAuthenticationRequest($msg)) {
|
||||
//check if current user is has the same identity that the one claimed on openid message
|
||||
$auth_request = new OpenIdAuthenticationRequest($msg);
|
||||
if (!$auth_request->isIdentitySelectByOP()) {
|
||||
$claimed_id = $auth_request->getClaimedId();
|
||||
$identity = $auth_request->getIdentity();
|
||||
$current_identity = $this->server_configuration->getUserIdentityEndpointURL($user->getIdentifier());
|
||||
|
||||
//if not return fail ( we cant log in with a different user that the one stated on the authentication message!
|
||||
if ($claimed_id !== $current_identity && $identity !== $current_identity) {
|
||||
Log::warning(sprintf(OpenIdErrorMessages::AlreadyExistSessionMessage, $current_identity, $identity));
|
||||
throw new AuthenticationException(sprintf(OpenIdErrorMessages::AlreadyExistSessionMessage, $current_identity, $identity));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,7 +30,7 @@ abstract class OpenIdExtension
|
|||
protected $name;
|
||||
protected $description;
|
||||
protected $view;
|
||||
protected $log;
|
||||
protected $log_service;
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
|
@ -44,7 +44,7 @@ abstract class OpenIdExtension
|
|||
$this->name = $name;
|
||||
$this->view = $view;
|
||||
$this->description = $description;
|
||||
$this->log = Registry::getInstance()->get(UtilsServiceCatalog::LogService);
|
||||
$this->log_service = Registry::getInstance()->get(UtilsServiceCatalog::LogService);
|
||||
}
|
||||
|
||||
public function getNamespace()
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace openid\extensions\implementations;
|
||||
|
||||
use Exception;
|
||||
use openid\extensions\OpenIdExtension;
|
||||
use openid\OpenIdProtocol;
|
||||
use openid\requests\contexts\PartialView;
|
||||
|
@ -9,11 +10,9 @@ use openid\requests\contexts\RequestContext;
|
|||
use openid\requests\OpenIdRequest;
|
||||
use openid\responses\contexts\ResponseContext;
|
||||
use openid\responses\OpenIdResponse;
|
||||
use openid\services\OpenIdServiceCatalog;
|
||||
use utils\services\Registry;
|
||||
use utils\services\UtilsServiceCatalog;
|
||||
|
||||
|
||||
/**
|
||||
* Class OpenIdAXExtension
|
||||
* Implements
|
||||
|
@ -59,8 +58,8 @@ class OpenIdAXExtension extends OpenIdExtension
|
|||
}
|
||||
$partial_view = new PartialView($this->view, array("attributes" => $data));
|
||||
$context->addPartialView($partial_view);
|
||||
} catch (\Exception $ex) {
|
||||
$this->log->error($ex);
|
||||
} catch (Exception $ex) {
|
||||
$this->log_service->error($ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,8 +95,8 @@ class OpenIdAXExtension extends OpenIdExtension
|
|||
$response->addParam(self::param(self::Value) . "." . $attr, $user->getLanguage());
|
||||
}
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
$this->log->error($ex);
|
||||
} catch (Exception $ex) {
|
||||
$this->log_service->error($ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,8 +121,8 @@ class OpenIdAXExtension extends OpenIdExtension
|
|||
array_push($data, $attr);
|
||||
}
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
$this->log->error($ex);
|
||||
} catch (Exception $ex) {
|
||||
$this->log_service->error($ex);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: smarcet
|
||||
* Date: 11/4/13
|
||||
* Time: 10:45 AM
|
||||
*/
|
||||
|
||||
namespace openid\extensions\implementations;
|
||||
|
||||
|
@ -36,41 +30,38 @@ class OpenIdAXRequest extends OpenIdRequest
|
|||
*/
|
||||
public function isValid()
|
||||
{
|
||||
try {
|
||||
//check identifier
|
||||
if (isset($this->message[OpenIdAXExtension::paramNamespace('_')])
|
||||
&& $this->message[OpenIdAXExtension::paramNamespace('_')] == OpenIdAXExtension::NamespaceUrl
|
||||
) {
|
||||
|
||||
//check required fields
|
||||
//check identifier
|
||||
if (isset($this->message[OpenIdAXExtension::paramNamespace('_')])
|
||||
&& $this->message[OpenIdAXExtension::paramNamespace('_')] == OpenIdAXExtension::NamespaceUrl
|
||||
) {
|
||||
|
||||
if (!isset($this->message[OpenIdAXExtension::param(OpenIdAXExtension::Mode, '_')])
|
||||
|| $this->message[OpenIdAXExtension::param(OpenIdAXExtension::Mode, '_')] != OpenIdAXExtension::FetchRequest
|
||||
)
|
||||
throw new InvalidOpenIdMessageException(OpenIdErrorMessages::AXInvalidModeMessage);
|
||||
//check required fields
|
||||
|
||||
if (!isset($this->message[OpenIdAXExtension::param(OpenIdAXExtension::RequiredAttributes, '_')]))
|
||||
throw new InvalidOpenIdMessageException(OpenIdErrorMessages::AXInvalidRequiredAttributesMessage);
|
||||
if (!isset($this->message[OpenIdAXExtension::param(OpenIdAXExtension::Mode, '_')])
|
||||
|| $this->message[OpenIdAXExtension::param(OpenIdAXExtension::Mode, '_')] != OpenIdAXExtension::FetchRequest
|
||||
)
|
||||
throw new InvalidOpenIdMessageException(OpenIdErrorMessages::AXInvalidModeMessage);
|
||||
|
||||
//get attributes
|
||||
$attributes = $this->message[OpenIdAXExtension::param(OpenIdAXExtension::RequiredAttributes, '_')];
|
||||
$attributes = explode(",", $attributes);
|
||||
if (!isset($this->message[OpenIdAXExtension::param(OpenIdAXExtension::RequiredAttributes, '_')]))
|
||||
throw new InvalidOpenIdMessageException(OpenIdErrorMessages::AXInvalidRequiredAttributesMessage);
|
||||
|
||||
foreach ($attributes as $attr) {
|
||||
$attr = trim($attr);
|
||||
if (!isset(OpenIdAXExtension::$available_properties[$attr]))
|
||||
continue;
|
||||
if (!isset($this->message[OpenIdAXExtension::param(OpenIdAXExtension::Type, '_') . "_" . $attr]))
|
||||
throw new InvalidOpenIdMessageException(sprintf(OpenIdErrorMessages::AXInvalidNamespaceMessage, $attr));
|
||||
$ns = $this->message[OpenIdAXExtension::param(OpenIdAXExtension::Type, "_") . "_" . $attr];
|
||||
if ($ns != OpenIdAXExtension::$available_properties[$attr])
|
||||
throw new InvalidOpenIdMessageException(sprintf(OpenIdErrorMessages::AXInvalidNamespaceMessage, $attr));
|
||||
array_push($this->attributes, $attr);
|
||||
}
|
||||
return true;
|
||||
//get attributes
|
||||
$attributes = $this->message[OpenIdAXExtension::param(OpenIdAXExtension::RequiredAttributes, '_')];
|
||||
$attributes = explode(",", $attributes);
|
||||
|
||||
foreach ($attributes as $attr) {
|
||||
$attr = trim($attr);
|
||||
if (!isset(OpenIdAXExtension::$available_properties[$attr]))
|
||||
continue;
|
||||
if (!isset($this->message[OpenIdAXExtension::param(OpenIdAXExtension::Type, '_') . "_" . $attr]))
|
||||
throw new InvalidOpenIdMessageException(sprintf(OpenIdErrorMessages::AXInvalidNamespaceMessage, $attr));
|
||||
$ns = $this->message[OpenIdAXExtension::param(OpenIdAXExtension::Type, "_") . "_" . $attr];
|
||||
if ($ns != OpenIdAXExtension::$available_properties[$attr])
|
||||
throw new InvalidOpenIdMessageException(sprintf(OpenIdErrorMessages::AXInvalidNamespaceMessage, $attr));
|
||||
array_push($this->attributes, $attr);
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
$this->log->error($ex);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,181 @@
|
|||
<?php
|
||||
|
||||
namespace openid\extensions\implementations;
|
||||
|
||||
use openid\requests\contexts\PartialView;
|
||||
use oauth2\services\OAuth2ServiceCatalog;
|
||||
use openid\extensions\OpenIdExtension;
|
||||
use openid\OpenIdProtocol;
|
||||
use openid\requests\contexts\RequestContext;
|
||||
use openid\requests\OpenIdRequest;
|
||||
use openid\responses\contexts\ResponseContext;
|
||||
use openid\responses\OpenIdResponse;
|
||||
use Exception;
|
||||
|
||||
use utils\services\Registry;
|
||||
use utils\services\UtilsServiceCatalog;
|
||||
|
||||
use oauth2\requests\OAuth2AuthorizationRequest;
|
||||
use oauth2\OAuth2Protocol;
|
||||
use oauth2\OAuth2Message;
|
||||
|
||||
|
||||
/**
|
||||
* Class OpenIdOAuthExtension
|
||||
* Implements
|
||||
* http://step2.googlecode.com/svn/spec/openid_oauth_extension/latest/openid_oauth_extension.html
|
||||
* OpenID+OAuth Hybrid protocol lets web developers combine an OpenID request with an
|
||||
* OAuth authentication request. This extension is useful for web developers who use both OpenID
|
||||
* and OAuth, particularly in that it simplifies the process for users by requesting
|
||||
* their approval once instead of twice.
|
||||
* In this way, the user can approve login and service access at the same time.
|
||||
* @package openid\extensions\implementations
|
||||
*/
|
||||
class OpenIdOAuth2Extension extends OpenIdExtension
|
||||
{
|
||||
|
||||
const Prefix = "oauth";
|
||||
const NamespaceUrl = "http://specs.openid.net/extensions/oauth/2.0";
|
||||
const NamespaceType = 'ns';
|
||||
const RequestToken = 'request_token';
|
||||
const Scope = OAuth2Protocol::OAuth2Protocol_Scope;
|
||||
const ClientId = OAuth2Protocol::OAuth2Protocol_ClientId;
|
||||
const State = OAuth2Protocol::OAuth2Protocol_State;
|
||||
|
||||
private $oauth2_protocol;
|
||||
private $checkpoint_service;
|
||||
private $client_service;
|
||||
private $scope_service;
|
||||
|
||||
public function __construct($name, $namespace, $view, $description)
|
||||
{
|
||||
parent::__construct($name, $namespace, $view, $description);
|
||||
|
||||
$this->oauth2_protocol = Registry::getInstance()->get('oauth2\IOAuth2Protocol');
|
||||
$this->checkpoint_service = Registry::getInstance()->get(UtilsServiceCatalog::CheckPointService);
|
||||
$this->client_service = Registry::getInstance()->get(OAuth2ServiceCatalog::ClientService);
|
||||
$this->scope_service = Registry::getInstance()->get(OAuth2ServiceCatalog::ScopeService);
|
||||
}
|
||||
|
||||
public static function param($param, $separator = '.')
|
||||
{
|
||||
return OpenIdProtocol::OpenIdPrefix . $separator . self::Prefix . $separator . $param;
|
||||
}
|
||||
|
||||
public static function paramNamespace($separator = '.')
|
||||
{
|
||||
return OpenIdProtocol::OpenIdPrefix . $separator . OpenIdProtocol::OpenIDProtocol_NS . $separator . self::Prefix;
|
||||
}
|
||||
|
||||
public function parseRequest(OpenIdRequest $request, RequestContext $context)
|
||||
{
|
||||
try {
|
||||
|
||||
$oauth2_request = new OpenIdOAuth2Request($request->getMessage());
|
||||
if (!$oauth2_request->isValid()) return;
|
||||
|
||||
$scopes = $oauth2_request->getScope();
|
||||
$client_id = $oauth2_request->getClientId();
|
||||
|
||||
$client = $this->client_service->getClientById($client_id);
|
||||
// do some validations to allow show the oauth2 sub view...
|
||||
if(is_null($client)) return;
|
||||
|
||||
//check is redirect uri is allowed for client
|
||||
$redirect_uri = $request->getParam(OpenIdProtocol::OpenIDProtocol_ReturnTo);
|
||||
if (!$client->isUriAllowed($redirect_uri)) return;
|
||||
|
||||
//check if requested client is allowed to use this scopes
|
||||
if(!$client->isScopeAllowed($scopes)) return;
|
||||
|
||||
$scopes = explode(' ', $scopes);
|
||||
//get scopes entities
|
||||
$requested_scopes = $this->scope_service->getScopesByName($scopes);
|
||||
|
||||
// set view data
|
||||
|
||||
$return_to = $request->getParam(OpenIdProtocol::OpenIDProtocol_ReturnTo);
|
||||
$url_parts = @parse_url($return_to);
|
||||
$return_to = $url_parts['scheme'] . '://' . $url_parts['host'] . $url_parts['path'];
|
||||
|
||||
$partial_view = new PartialView ($this->view, array(
|
||||
'requested_scopes' => $requested_scopes,
|
||||
'app_name' => $client->getApplicationName(),
|
||||
'app_logo' => $client->getApplicationLogo(),
|
||||
'redirect_to' => $return_to,
|
||||
'dev_info_email' => $client->getDeveloperEmail()
|
||||
));
|
||||
|
||||
$context->addPartialView($partial_view);
|
||||
} catch (Exception $ex) {
|
||||
$this->log_service->error($ex);
|
||||
}
|
||||
}
|
||||
|
||||
public function prepareResponse(OpenIdRequest $request, OpenIdResponse $response, ResponseContext $context)
|
||||
{
|
||||
try{
|
||||
$oauth2_request = new OpenIdOAuth2Request($request->getMessage());
|
||||
if (!$oauth2_request->isValid()) return;
|
||||
//get auth code
|
||||
$oauth2_msg = new OAuth2Message(
|
||||
array(
|
||||
OAuth2Protocol::OAuth2Protocol_ClientId => $oauth2_request->getClientId(),
|
||||
OAuth2Protocol::OAuth2Protocol_Scope => $oauth2_request->getScope(),
|
||||
OAuth2Protocol::OAuth2Protocol_RedirectUri => $request->getParam(OpenIdProtocol::OpenIDProtocol_ReturnTo),
|
||||
OAuth2Protocol::OAuth2Protocol_State => $oauth2_request->getState(),
|
||||
OAuth2Protocol::OAuth2Protocol_ResponseType => OAuth2Protocol::OAuth2Protocol_ResponseType_Code
|
||||
)
|
||||
);
|
||||
// do oauth2 Authorization Code Grant 1st step (get auth code to exchange for an access token)
|
||||
// http://tools.ietf.org/html/rfc6749#section-4.1
|
||||
$oauth2_response = $this->oauth2_protocol->authorize(new OAuth2AuthorizationRequest($oauth2_msg));
|
||||
if ( get_class($oauth2_response) =='oauth2\\responses\\OAuth2AuthorizationResponse') {
|
||||
//add namespace
|
||||
$response->addParam(self::paramNamespace(),self::NamespaceUrl );
|
||||
$context->addSignParam(self::paramNamespace());
|
||||
|
||||
//add auth code
|
||||
$response->addParam(self::param(self::RequestToken), $oauth2_response->getAuthCode());
|
||||
$context->addSignParam(self::param(self::RequestToken));
|
||||
|
||||
//add requested scope
|
||||
$response->addParam(self::param(self::Scope), $oauth2_response->getScope());
|
||||
$context->addSignParam(self::param(self::Scope));
|
||||
|
||||
//add state
|
||||
$response->addParam(self::param(self::State), $oauth2_request->getState());
|
||||
$context->addSignParam(self::param(self::State));
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception $ex) {
|
||||
$this->log_service->error($ex);
|
||||
$this->checkpoint_service->trackException($ex);
|
||||
//http://step2.googlecode.com/svn/spec/openid_oauth_extension/latest/openid_oauth_extension.html#AuthResp
|
||||
/*
|
||||
* To note that the OAuth Authorization was declined or not valid, the Combined Provider SHALL only
|
||||
* respond with the parameter "openid.ns.oauth".
|
||||
*/
|
||||
//add namespace
|
||||
$response->addParam(self::paramNamespace(),self::NamespaceUrl );
|
||||
$context->addSignParam(self::paramNamespace());
|
||||
}
|
||||
}
|
||||
|
||||
public function getTrustedData(OpenIdRequest $request)
|
||||
{
|
||||
$data = array();
|
||||
try {
|
||||
$oauth2_request = new OpenIdOAuth2Request($request->getMessage());
|
||||
if ($oauth2_request->isValid()) {
|
||||
array_push($data,$oauth2_request->getScope());
|
||||
array_push($data,$oauth2_request->getClientId());
|
||||
}
|
||||
} catch (Exception $ex) {
|
||||
$this->log_service->error($ex);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace openid\extensions\implementations;
|
||||
|
||||
use openid\exceptions\InvalidOpenIdMessageException;
|
||||
use openid\helpers\OpenIdErrorMessages;
|
||||
use openid\OpenIdMessage;
|
||||
use openid\requests\OpenIdRequest;
|
||||
use oauth2\OAuth2Protocol;
|
||||
|
||||
class OpenIdOAuth2Request extends OpenIdRequest {
|
||||
|
||||
public function __construct(OpenIdMessage $message)
|
||||
{
|
||||
parent::__construct($message);
|
||||
}
|
||||
|
||||
public function isValid()
|
||||
{
|
||||
//check identifier
|
||||
if (isset($this->message[OpenIdOAuth2Extension::paramNamespace('_')])
|
||||
&& $this->message[OpenIdOAuth2Extension::paramNamespace('_')] == OpenIdOAuth2Extension::NamespaceUrl
|
||||
) {
|
||||
if(is_null($this->getClientId()))
|
||||
throw new InvalidOpenIdMessageException(sprintf(OpenIdErrorMessages::OAuth2MissingRequiredParam,'client_id'));
|
||||
if(is_null($this->getScope()))
|
||||
throw new InvalidOpenIdMessageException(sprintf(OpenIdErrorMessages::OAuth2MissingRequiredParam,'scope'));
|
||||
if(is_null($this->getState()))
|
||||
throw new InvalidOpenIdMessageException(sprintf(OpenIdErrorMessages::OAuth2MissingRequiredParam,'state'));
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getClientId(){
|
||||
return isset($this->message[OpenIdOAuth2Extension::param(OAuth2Protocol::OAuth2Protocol_ClientId, '_')])?
|
||||
$this->message[OpenIdOAuth2Extension::param(OAuth2Protocol::OAuth2Protocol_ClientId, '_')]:null;
|
||||
}
|
||||
|
||||
public function getScope(){
|
||||
return isset($this->message[OpenIdOAuth2Extension::param(OAuth2Protocol::OAuth2Protocol_Scope, '_')])?
|
||||
$this->message[OpenIdOAuth2Extension::param(OAuth2Protocol::OAuth2Protocol_Scope, '_')]:null;
|
||||
}
|
||||
|
||||
public function getState(){
|
||||
return isset($this->message[OpenIdOAuth2Extension::param(OAuth2Protocol::OAuth2Protocol_State, '_')])?
|
||||
$this->message[OpenIdOAuth2Extension::param(OAuth2Protocol::OAuth2Protocol_State, '_')]:null;
|
||||
}
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by JetBrains PhpStorm.
|
||||
* User: smarcet
|
||||
* Date: 10/16/13
|
||||
* Time: 2:43 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
|
||||
namespace openid\extensions\implementations;
|
||||
|
||||
use openid\extensions\OpenIdExtension;
|
||||
use openid\OpenIdProtocol;
|
||||
use openid\requests\contexts\RequestContext;
|
||||
use openid\requests\OpenIdRequest;
|
||||
use openid\responses\contexts\ResponseContext;
|
||||
use openid\responses\OpenIdResponse;
|
||||
|
||||
/**
|
||||
* Class OpenIdOAuthExtension
|
||||
* Implements
|
||||
* http://step2.googlecode.com/svn/spec/openid_oauth_extension/latest/openid_oauth_extension.html
|
||||
* @package openid\extensions\implementations
|
||||
*/
|
||||
class OpenIdOAuthExtension extends OpenIdExtension
|
||||
{
|
||||
|
||||
const Prefix = "oauth";
|
||||
|
||||
public static function param($param, $separator = '.')
|
||||
{
|
||||
return OpenIdProtocol::OpenIdPrefix . $separator . self::Prefix . $separator . $param;
|
||||
}
|
||||
|
||||
public static function paramNamespace($separator = '.')
|
||||
{
|
||||
return OpenIdProtocol::OpenIdPrefix . $separator . OpenIdProtocol::OpenIDProtocol_NS . $separator . self::Prefix;
|
||||
}
|
||||
|
||||
public function parseRequest(OpenIdRequest $request, RequestContext $context)
|
||||
{
|
||||
// TODO: Implement parseRequest() method.
|
||||
}
|
||||
|
||||
public function prepareResponse(OpenIdRequest $request, OpenIdResponse $response, ResponseContext $context)
|
||||
{
|
||||
// TODO: Implement prepareResponse() method.
|
||||
}
|
||||
|
||||
public function getTrustedData(OpenIdRequest $request)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected function populateProperties()
|
||||
{
|
||||
// TODO: Implement populateProperties() method.
|
||||
}
|
||||
}
|
|
@ -1,11 +1,4 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by JetBrains PhpStorm.
|
||||
* User: smarcet
|
||||
* Date: 10/16/13
|
||||
* Time: 2:42 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
|
||||
namespace openid\extensions\implementations;
|
||||
|
||||
|
@ -19,6 +12,7 @@ use openid\responses\OpenIdResponse;
|
|||
use openid\services\OpenIdServiceCatalog;
|
||||
use utils\services\Registry;
|
||||
use utils\services\UtilsServiceCatalog;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class OpenIdSREGExtension
|
||||
|
@ -81,8 +75,8 @@ class OpenIdSREGExtension extends OpenIdExtension
|
|||
|
||||
$partial_view = new PartialView($this->view, $view_data);
|
||||
$context->addPartialView($partial_view);
|
||||
} catch (\Exception $ex) {
|
||||
$this->log->error($ex);
|
||||
} catch (Exception $ex) {
|
||||
$this->log_service->error($ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,8 +110,8 @@ class OpenIdSREGExtension extends OpenIdExtension
|
|||
$response->addParam(self::param($attr), $user->getLanguage());
|
||||
}
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
$this->log->error($ex);
|
||||
} catch (Exception $ex) {
|
||||
$this->log_service->error($ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,8 +138,8 @@ class OpenIdSREGExtension extends OpenIdExtension
|
|||
array_push($data, $key);
|
||||
}
|
||||
}
|
||||
} catch (\Exception $ex) {
|
||||
$this->log->error($ex);
|
||||
} catch (Exception $ex) {
|
||||
$this->log_service->error($ex);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ use openid\services\IServerExtensionsService;
|
|||
use openid\services\ITrustedSitesService;
|
||||
use utils\services\IAuthService;
|
||||
use utils\services\ILogService;
|
||||
use utils\services\ICheckPointService;
|
||||
|
||||
/**
|
||||
* Class OpenIdAuthenticationRequestHandler
|
||||
|
@ -61,9 +62,10 @@ class OpenIdAuthenticationRequestHandler extends OpenIdMessageHandler
|
|||
IServerConfigurationService $server_configuration_service,
|
||||
INonceService $nonce_service,
|
||||
ILogService $log,
|
||||
ICheckPointService $checkpoint_service,
|
||||
$successor)
|
||||
{
|
||||
parent::__construct($successor, $log);
|
||||
parent::__construct($successor, $log,$checkpoint_service);
|
||||
$this->auth_service = $authService;
|
||||
$this->memento_service = $memento_service;
|
||||
$this->auth_strategy = $auth_strategy;
|
||||
|
@ -110,33 +112,33 @@ class OpenIdAuthenticationRequestHandler extends OpenIdMessageHandler
|
|||
}
|
||||
} catch (InvalidAssociationTypeException $inv_assoc_type) {
|
||||
$this->checkpoint_service->trackException($inv_assoc_type);
|
||||
$this->log->warning($inv_assoc_type);
|
||||
$this->log_service->warning($inv_assoc_type);
|
||||
if(!is_null($this->current_request))
|
||||
$this->log->error_msg("current request: ".$this->current_request->toString());
|
||||
$this->log_service->error_msg("current request: ".$this->current_request->toString());
|
||||
return new OpenIdIndirectGenericErrorResponse($inv_assoc_type->getMessage(), null, null, $this->current_request);
|
||||
} catch (OpenIdInvalidRealmException $inv_realm_ex) {
|
||||
$this->checkpoint_service->trackException($inv_realm_ex);
|
||||
$this->log->error($inv_realm_ex);
|
||||
$this->log_service->error($inv_realm_ex);
|
||||
if(!is_null($this->current_request))
|
||||
$this->log->error_msg("current request: ".$this->current_request->toString());
|
||||
$this->log_service->error_msg("current request: ".$this->current_request->toString());
|
||||
return new OpenIdIndirectGenericErrorResponse($inv_realm_ex->getMessage(), null, null, $this->current_request);
|
||||
} catch (ReplayAttackException $replay_ex) {
|
||||
$this->checkpoint_service->trackException($replay_ex);
|
||||
$this->log->error($replay_ex);
|
||||
$this->log_service->error($replay_ex);
|
||||
if(!is_null($this->current_request))
|
||||
$this->log->error_msg("current request: ".$this->current_request->toString());
|
||||
$this->log_service->error_msg("current request: ".$this->current_request->toString());
|
||||
return new OpenIdIndirectGenericErrorResponse($replay_ex->getMessage(), null, null, $this->current_request);
|
||||
} catch (InvalidOpenIdMessageException $inv_msg_ex) {
|
||||
$this->checkpoint_service->trackException($inv_msg_ex);
|
||||
$this->log->error($inv_msg_ex);
|
||||
$this->log_service->error($inv_msg_ex);
|
||||
if(!is_null($this->current_request))
|
||||
$this->log->error_msg("current request: ".$this->current_request->toString());
|
||||
$this->log_service->error_msg("current request: ".$this->current_request->toString());
|
||||
return new OpenIdIndirectGenericErrorResponse($inv_msg_ex->getMessage(), null, null, $this->current_request);
|
||||
} catch (Exception $ex) {
|
||||
$this->checkpoint_service->trackException($ex);
|
||||
$this->log->error($ex);
|
||||
$this->log_service->error($ex);
|
||||
if(!is_null($this->current_request))
|
||||
$this->log->error_msg("current request: ".$this->current_request->toString());
|
||||
$this->log_service->error_msg("current request: ".$this->current_request->toString());
|
||||
return new OpenIdIndirectGenericErrorResponse("Server Error", null, null, $this->current_request);
|
||||
}
|
||||
}
|
||||
|
@ -147,66 +149,66 @@ class OpenIdAuthenticationRequestHandler extends OpenIdMessageHandler
|
|||
*/
|
||||
private function doSetupMode()
|
||||
{
|
||||
if (!$this->auth_service->isUserLogged()) {
|
||||
|
||||
if (!$this->auth_service->isUserLogged())
|
||||
return $this->doLogin();
|
||||
} else {
|
||||
//user already logged
|
||||
$currentUser = $this->auth_service->getCurrentUser();
|
||||
if (!$this->current_request->isIdentitySelectByOP()) {
|
||||
$current_claimed_id = $this->current_request->getClaimedId();
|
||||
$current_identity = $this->current_request->getIdentity();
|
||||
|
||||
// check is claimed identity match with current one
|
||||
// if not logs out and do re login
|
||||
$current_user = $this->auth_service->getCurrentUser();
|
||||
//user already logged
|
||||
$currentUser = $this->auth_service->getCurrentUser();
|
||||
|
||||
if (is_null($current_user))
|
||||
throw new \Exception("User not set!");
|
||||
if (!$this->current_request->isIdentitySelectByOP()) {
|
||||
|
||||
$current_owned_identity = $this->server_configuration_service->getUserIdentityEndpointURL($current_user->getIdentifier());
|
||||
$current_claimed_id = $this->current_request->getClaimedId();
|
||||
$current_identity = $this->current_request->getIdentity();
|
||||
// check is claimed identity match with current one
|
||||
// if not logs out and do re login
|
||||
$current_user = $this->auth_service->getCurrentUser();
|
||||
if (is_null($current_user))
|
||||
throw new Exception("User not set!");
|
||||
|
||||
if ($current_claimed_id != $current_owned_identity && $current_identity != $current_owned_identity) {
|
||||
$this->log->warning_msg(sprintf(OpenIdErrorMessages::AlreadyExistSessionMessage, $current_owned_identity, $current_identity));
|
||||
$this->auth_service->logout();
|
||||
return $this->doLogin();
|
||||
}
|
||||
$current_owned_identity = $this->server_configuration_service->getUserIdentityEndpointURL($current_user->getIdentifier());
|
||||
|
||||
if ($current_claimed_id != $current_owned_identity && $current_identity != $current_owned_identity) {
|
||||
$this->log_service->warning_msg(sprintf(OpenIdErrorMessages::AlreadyExistSessionMessage, $current_owned_identity, $current_identity));
|
||||
$this->auth_service->logout();
|
||||
return $this->doLogin();
|
||||
}
|
||||
}
|
||||
|
||||
$authorization_response = $this->auth_service->getUserAuthorizationResponse();
|
||||
$authorization_response = $this->auth_service->getUserAuthorizationResponse();
|
||||
if ($authorization_response !== IAuthService::AuthorizationResponse_None)
|
||||
return $this->checkAuthorizationResponse($authorization_response);
|
||||
|
||||
if ($authorization_response == IAuthService::AuthorizationResponse_None) {
|
||||
$this->current_request_context->cleanTrustedData();
|
||||
foreach ($this->extensions as $ext) {
|
||||
$data = $ext->getTrustedData($this->current_request);
|
||||
$this->current_request_context->setTrustedData($data);
|
||||
// $authorization_response is none ...
|
||||
$this->current_request_context->cleanTrustedData();
|
||||
foreach ($this->extensions as $ext) {
|
||||
$data = $ext->getTrustedData($this->current_request);
|
||||
$this->current_request_context->setTrustedData($data);
|
||||
}
|
||||
|
||||
$requested_data = $this->current_request_context->getTrustedData();
|
||||
$sites = $this->trusted_sites_service->getTrustedSites($currentUser, $this->current_request->getRealm(), $requested_data);
|
||||
//check trusted sites
|
||||
if (is_null($sites) || count($sites) === 0)
|
||||
return $this->doConsentProcess();
|
||||
//there are trusted sites ... check the former authorization decision
|
||||
$site = $sites[0];
|
||||
$policy = $site->getAuthorizationPolicy();
|
||||
switch ($policy) {
|
||||
case IAuthService::AuthorizationResponse_AllowForever:
|
||||
{
|
||||
//save former user choice on session
|
||||
$this->auth_service->setUserAuthorizationResponse($policy);
|
||||
return $this->doAssertion();
|
||||
}
|
||||
$requested_data = $this->current_request_context->getTrustedData();
|
||||
$sites = $this->trusted_sites_service->getTrustedSites($currentUser, $this->current_request->getRealm(), $requested_data);
|
||||
|
||||
if (!is_null($sites) && count($sites) > 0) {
|
||||
$site = $sites[0];
|
||||
$policy = $site->getAuthorizationPolicy();
|
||||
switch ($policy) {
|
||||
case IAuthService::AuthorizationResponse_AllowForever:
|
||||
{
|
||||
return $this->doAssertion();
|
||||
}
|
||||
break;
|
||||
case IAuthService::AuthorizationResponse_DenyForever:
|
||||
// black listed site
|
||||
return new OpenIdIndirectGenericErrorResponse(sprintf(OpenIdErrorMessages::RealmNotAllowedByUserMessage, $site->getRealm()), null, null, $this->current_request);
|
||||
break;
|
||||
default:
|
||||
throw new \Exception("Invalid Realm Policy");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return $this->doConsentProcess();
|
||||
}
|
||||
|
||||
} else {
|
||||
return $this->checkAuthorizationResponse($authorization_response);
|
||||
}
|
||||
break;
|
||||
case IAuthService::AuthorizationResponse_DenyForever:
|
||||
// black listed site
|
||||
return new OpenIdIndirectGenericErrorResponse(sprintf(OpenIdErrorMessages::RealmNotAllowedByUserMessage, $site->getRealm()), null, null, $this->current_request);
|
||||
break;
|
||||
default:
|
||||
throw new Exception("Invalid Realm Policy");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,33 +248,30 @@ class OpenIdAuthenticationRequestHandler extends OpenIdMessageHandler
|
|||
$context->addSignParam(OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity));
|
||||
|
||||
$op_endpoint = $this->server_configuration_service->getOPEndpointURL();
|
||||
$identity = $this->server_configuration_service->getUserIdentityEndpointURL($currentUser->getIdentifier());
|
||||
$nonce = $this->nonce_service->generateNonce();
|
||||
$realm = $this->current_request->getRealm();
|
||||
$response = new OpenIdPositiveAssertionResponse($op_endpoint, $identity, $identity, $this->current_request->getReturnTo(), $nonce->getRawFormat(), $realm);
|
||||
$identity = $this->server_configuration_service->getUserIdentityEndpointURL($currentUser->getIdentifier());
|
||||
$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);
|
||||
}
|
||||
|
||||
//check former assoc handle...
|
||||
$assoc_handle = $this->current_request->getAssocHandle();
|
||||
$association = $this->association_service->getAssociation($assoc_handle);
|
||||
|
||||
if (empty($assoc_handle) || is_null($association)) {
|
||||
if (is_null($assoc_handle = $this->current_request->getAssocHandle()) || is_null($association = $this->association_service->getAssociation($assoc_handle))) {
|
||||
// if not present or if it already void then enter on dumb mode
|
||||
$new_secret = OpenIdCryptoHelper::generateSecret(OpenIdProtocol::SignatureAlgorithmHMAC_SHA256);
|
||||
$new_handle = AssocHandleGenerator::generate();
|
||||
$lifetime = $this->server_configuration_service->getConfigValue("Private.Association.Lifetime");
|
||||
$issued = gmdate("Y-m-d H:i:s", time());
|
||||
//create private association ...
|
||||
$this->association_service->addAssociation($new_handle, $new_secret, OpenIdProtocol::SignatureAlgorithmHMAC_SHA256, $lifetime, $issued, IAssociation::TypePrivate, $realm);
|
||||
$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);
|
||||
}
|
||||
$association = $this->association_service->getAssociation($new_handle);
|
||||
} else {
|
||||
if ($association->getType() != IAssociation::TypeSession)
|
||||
throw new InvalidAssociationTypeException(OpenIdErrorMessages::InvalidAssociationTypeMessage);
|
||||
|
@ -288,7 +287,9 @@ class OpenIdAuthenticationRequestHandler extends OpenIdMessageHandler
|
|||
* so associate $nonce with signature and realm
|
||||
*/
|
||||
$this->nonce_service->associateNonce($nonce, $response->getSig(), $realm);
|
||||
//do cleaning ...
|
||||
$this->memento_service->clearCurrentRequest();
|
||||
$this->auth_service->clearUserAuthorizationResponse();
|
||||
return $response;
|
||||
}
|
||||
|
||||
|
@ -333,16 +334,22 @@ class OpenIdAuthenticationRequestHandler extends OpenIdMessageHandler
|
|||
break;
|
||||
case IAuthService::AuthorizationResponse_DenyOnce:
|
||||
{
|
||||
$this->memento_service->clearCurrentRequest();
|
||||
$this->auth_service->clearUserAuthorizationResponse();
|
||||
return new OpenIdNonImmediateNegativeAssertion($this->current_request->getReturnTo());
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case IAuthService::AuthorizationResponse_DenyForever:
|
||||
{
|
||||
$this->memento_service->clearCurrentRequest();
|
||||
$this->auth_service->clearUserAuthorizationResponse();
|
||||
$this->trusted_sites_service->addTrustedSite($currentUser, $this->current_request->getRealm(), IAuthService::AuthorizationResponse_DenyForever);
|
||||
return new OpenIdNonImmediateNegativeAssertion($this->current_request->getReturnTo());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$this->memento_service->clearCurrentRequest();
|
||||
$this->auth_service->clearUserAuthorizationResponse();
|
||||
throw new \Exception("Invalid Authorization response!");
|
||||
break;
|
||||
}
|
||||
|
@ -384,6 +391,8 @@ class OpenIdAuthenticationRequestHandler extends OpenIdMessageHandler
|
|||
break;
|
||||
case IAuthService::AuthorizationResponse_AllowForever:
|
||||
{
|
||||
//save former user choice on session
|
||||
$this->auth_service->setUserAuthorizationResponse($policy);
|
||||
return $this->doAssertion();
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -18,22 +18,32 @@ use openid\responses\OpenIdDirectGenericErrorResponse;
|
|||
use openid\services\IAssociationService;
|
||||
use openid\services\INonceService;
|
||||
use utils\services\ILogService;
|
||||
use utils\services\ICheckPointService;
|
||||
|
||||
/**
|
||||
* Class OpenIdCheckAuthenticationRequestHandler
|
||||
* Implements http://openid.net/specs/openid-authentication-2_0.html#check_auth
|
||||
* Verifying Directly with the OpenID Provider
|
||||
* To have the signature verification performed by the OP, the Relying Party sends a direct request to the OP.
|
||||
* To verify the signature, the OP uses a private association that was generated when it issued
|
||||
* the positive assertion.
|
||||
* @package openid\handlers
|
||||
*/
|
||||
class OpenIdCheckAuthenticationRequestHandler extends OpenIdMessageHandler
|
||||
{
|
||||
|
||||
|
||||
private $association_service;
|
||||
private $nonce_service;
|
||||
|
||||
public function __construct(IAssociationService $association_service,
|
||||
INonceService $nonce_service,
|
||||
ILogService $log,
|
||||
ILogService $log_service,
|
||||
ICheckPointService $checkpoint_service,
|
||||
$successor)
|
||||
{
|
||||
parent::__construct($successor, $log);
|
||||
parent::__construct($successor, $log_service, $checkpoint_service);
|
||||
$this->association_service = $association_service;
|
||||
$this->nonce_service = $nonce_service;
|
||||
$this->nonce_service = $nonce_service;
|
||||
}
|
||||
|
||||
protected function internalHandle(OpenIdMessage $message)
|
||||
|
@ -44,9 +54,7 @@ class OpenIdCheckAuthenticationRequestHandler extends OpenIdMessageHandler
|
|||
|
||||
if (!$this->current_request->isValid())
|
||||
throw new InvalidOpenIdMessageException(OpenIdErrorMessages::InvalidOpenIdCheckAuthenticationRequestMessage);
|
||||
$claimed_nonce = new OpenIdNonce($this->current_request->getNonce());
|
||||
|
||||
$this->nonce_service->lockNonce($claimed_nonce);
|
||||
|
||||
/**
|
||||
* For verifying signatures an OP MUST only use private associations and MUST NOT
|
||||
|
@ -60,14 +68,17 @@ class OpenIdCheckAuthenticationRequestHandler extends OpenIdMessageHandler
|
|||
*/
|
||||
|
||||
$claimed_assoc = $this->current_request->getAssocHandle();
|
||||
$stored_assoc = $this->association_service->getAssociation($claimed_assoc);
|
||||
$claimed_realm = $this->current_request->getRealm();
|
||||
$stored_assoc = $this->association_service->getAssociation($claimed_assoc, $claimed_realm);
|
||||
|
||||
if (is_null($stored_assoc) || $stored_assoc->getType() != IAssociation::TypePrivate)
|
||||
throw new InvalidAssociationTypeException(OpenIdErrorMessages::InvalidAssociationTypeMessage);
|
||||
|
||||
$claimed_nonce = new OpenIdNonce($this->current_request->getNonce());
|
||||
|
||||
$claimed_realm = $this->current_request->getRealm();
|
||||
$claimed_sig = $this->current_request->getSig();
|
||||
$this->nonce_service->lockNonce($claimed_nonce);
|
||||
|
||||
$claimed_sig = $this->current_request->getSig();
|
||||
$claimed_invalidate_handle = $this->current_request->getInvalidateHandle();
|
||||
|
||||
if (!is_null($claimed_invalidate_handle) && !empty($claimed_invalidate_handle)) {
|
||||
|
@ -82,46 +93,42 @@ class OpenIdCheckAuthenticationRequestHandler extends OpenIdMessageHandler
|
|||
$res = OpenIdSignatureBuilder::verify($this->current_request, $stored_assoc->getMacFunction(), $stored_assoc->getSecret(), $claimed_sig);
|
||||
//delete association
|
||||
$this->association_service->deleteAssociation($claimed_assoc);
|
||||
$is_valid = 'false';
|
||||
if ($res) {
|
||||
//assertion is valid
|
||||
$is_valid = 'true';
|
||||
}
|
||||
$is_valid = $res ? 'true':'false';
|
||||
return new OpenIdCheckAuthenticationResponse($is_valid, $claimed_invalidate_handle);
|
||||
|
||||
} catch (InvalidAssociationTypeException $inv_assoc_ex) {
|
||||
$this->checkpoint_service->trackException($inv_assoc_ex);
|
||||
$this->log->warning($inv_assoc_ex);
|
||||
$this->log_service->warning($inv_assoc_ex);
|
||||
$response = new OpenIdDirectGenericErrorResponse($inv_assoc_ex->getMessage());
|
||||
if(!is_null($this->current_request))
|
||||
$this->log->error_msg("current request: ".$this->current_request->toString());
|
||||
$this->log_service->error_msg("current request: ".$this->current_request->toString());
|
||||
return $response;
|
||||
} catch (ReplayAttackException $replay_ex) {
|
||||
$this->checkpoint_service->trackException($replay_ex);
|
||||
$this->log->warning($replay_ex);
|
||||
$this->log_service->warning($replay_ex);
|
||||
$response = new OpenIdDirectGenericErrorResponse($replay_ex->getMessage());
|
||||
if(!is_null($this->current_request))
|
||||
$this->log->error_msg("current request: ".$this->current_request->toString());
|
||||
$this->log_service->error_msg("current request: ".$this->current_request->toString());
|
||||
return $response;
|
||||
} catch (InvalidNonce $inv_nonce_ex) {
|
||||
$this->checkpoint_service->trackException($inv_nonce_ex);
|
||||
$this->log->error($inv_nonce_ex);
|
||||
$this->log_service->error($inv_nonce_ex);
|
||||
$response = new OpenIdDirectGenericErrorResponse($inv_nonce_ex->getMessage());
|
||||
if(!is_null($this->current_request))
|
||||
$this->log->error_msg("current request: ".$this->current_request->toString());
|
||||
$this->log_service->error_msg("current request: ".$this->current_request->toString());
|
||||
return $response;
|
||||
} catch (InvalidOpenIdMessageException $inv_msg_ex) {
|
||||
$this->checkpoint_service->trackException($inv_msg_ex);
|
||||
$this->log->error($inv_msg_ex);
|
||||
$this->log_service->error($inv_msg_ex);
|
||||
$response = new OpenIdDirectGenericErrorResponse($inv_msg_ex->getMessage());
|
||||
if(!is_null($this->current_request))
|
||||
$this->log->error_msg("current request: ".$this->current_request->toString());
|
||||
$this->log_service->error_msg("current request: ".$this->current_request->toString());
|
||||
return $response;
|
||||
} catch (Exception $ex) {
|
||||
$this->checkpoint_service->trackException($ex);
|
||||
$this->log->error($ex);
|
||||
$this->log_service->error($ex);
|
||||
if(!is_null($this->current_request))
|
||||
$this->log->error_msg("current request: ".$this->current_request->toString());
|
||||
$this->log_service->error_msg("current request: ".$this->current_request->toString());
|
||||
return new OpenIdDirectGenericErrorResponse("Server Error");
|
||||
}
|
||||
}
|
||||
|
@ -131,6 +138,4 @@ class OpenIdCheckAuthenticationRequestHandler extends OpenIdMessageHandler
|
|||
$res = OpenIdCheckAuthenticationRequest::IsOpenIdCheckAuthenticationRequest($message);
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,21 +1,12 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by JetBrains PhpStorm.
|
||||
* User: smarcet
|
||||
* Date: 10/14/13
|
||||
* Time: 5:41 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
|
||||
namespace openid\handlers;
|
||||
|
||||
use openid\exceptions\InvalidOpenIdMessageException;
|
||||
use openid\helpers\OpenIdErrorMessages;
|
||||
use openid\OpenIdMessage;
|
||||
use openid\services\OpenIdServiceCatalog;
|
||||
use utils\services\ILogService;
|
||||
use utils\services\Registry;
|
||||
use utils\services\UtilsServiceCatalog;
|
||||
use utils\services\ICheckPointService;
|
||||
|
||||
/**
|
||||
* Class OpenIdMessageHandler
|
||||
|
@ -28,14 +19,14 @@ abstract class OpenIdMessageHandler
|
|||
|
||||
protected $successor;
|
||||
protected $current_request;
|
||||
protected $log;
|
||||
protected $log_service;
|
||||
protected $checkpoint_service;
|
||||
|
||||
public function __construct($successor, ILogService $log)
|
||||
public function __construct($successor, ILogService $log_service, ICheckPointService $checkpoint_service)
|
||||
{
|
||||
$this->successor = $successor;
|
||||
$this->log = $log;
|
||||
$this->checkpoint_service = Registry::getInstance()->get(UtilsServiceCatalog::CheckPointService);
|
||||
$this->log_service = $log_service;
|
||||
$this->checkpoint_service = $checkpoint_service;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -53,8 +44,8 @@ abstract class OpenIdMessageHandler
|
|||
} else if (isset($this->successor) && !is_null($this->successor)) {
|
||||
return $this->successor->HandleMessage($message);
|
||||
}
|
||||
$this->log->warning_msg(sprintf(OpenIdErrorMessages::UnhandledMessage, $message->toString()));
|
||||
$ex = new InvalidOpenIdMessageException(sprintf(OpenIdErrorMessages::UnhandledMessage, $message->toString()));
|
||||
$this->log_service->warning_msg(sprintf(OpenIdErrorMessages::UnhandledMessage, $message->toString()));
|
||||
$ex = new InvalidOpenIdMessageException(sprintf(OpenIdErrorMessages::UnhandledMessage, $message->toString()));
|
||||
$this->checkpoint_service->trackException($ex);
|
||||
throw $ex;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,4 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by JetBrains PhpStorm.
|
||||
* User: smarcet
|
||||
* Date: 10/14/13
|
||||
* Time: 5:43 PM
|
||||
* To change this template use File | Settings | File Templates.
|
||||
*/
|
||||
|
||||
namespace openid\handlers;
|
||||
|
||||
|
@ -20,7 +13,7 @@ use openid\requests\OpenIdAssociationSessionRequest;
|
|||
use openid\responses\OpenIdAssociationSessionUnsuccessfulResponse;
|
||||
use openid\responses\OpenIdDirectGenericErrorResponse;
|
||||
use utils\services\ILogService;
|
||||
|
||||
use utils\services\ICheckPointService;
|
||||
/**
|
||||
* Class OpenIdSessionAssociationRequestHandler
|
||||
* Implements http://openid.net/specs/openid-authentication-2_0.html#associations
|
||||
|
@ -29,9 +22,9 @@ use utils\services\ILogService;
|
|||
class OpenIdSessionAssociationRequestHandler extends OpenIdMessageHandler
|
||||
{
|
||||
|
||||
public function __construct(ILogService $log, $successor)
|
||||
public function __construct(ILogService $log,ICheckPointService $checkpoint_service, $successor)
|
||||
{
|
||||
parent::__construct($successor, $log);
|
||||
parent::__construct($successor, $log,$checkpoint_service);
|
||||
}
|
||||
|
||||
protected function internalHandle(OpenIdMessage $message)
|
||||
|
@ -49,30 +42,30 @@ class OpenIdSessionAssociationRequestHandler extends OpenIdMessageHandler
|
|||
} catch (InvalidSessionTypeException $inv_session_ex) {
|
||||
$this->checkpoint_service->trackException($inv_session_ex);
|
||||
$response = new OpenIdAssociationSessionUnsuccessfulResponse($inv_session_ex->getMessage());
|
||||
$this->log->error($inv_session_ex);
|
||||
$this->log_service->error($inv_session_ex);
|
||||
if(!is_null($this->current_request))
|
||||
$this->log->error_msg("current request: ".$this->current_request->toString());
|
||||
$this->log_service->error_msg("current request: ".$this->current_request->toString());
|
||||
return $response;
|
||||
} catch (InvalidAssociationTypeException $inv_assoc_ex) {
|
||||
$this->checkpoint_service->trackException($inv_assoc_ex);
|
||||
$response = new OpenIdAssociationSessionUnsuccessfulResponse($inv_assoc_ex->getMessage());
|
||||
$this->log->error($inv_assoc_ex);
|
||||
$this->log_service->error($inv_assoc_ex);
|
||||
if(!is_null($this->current_request))
|
||||
$this->log->error_msg("current request: ".$this->current_request->toString());
|
||||
$this->log_service->error_msg("current request: ".$this->current_request->toString());
|
||||
return $response;
|
||||
} catch (InvalidOpenIdMessageException $inv_msg_ex) {
|
||||
$response = new OpenIdDirectGenericErrorResponse($inv_msg_ex->getMessage());
|
||||
$this->checkpoint_service->trackException($inv_msg_ex);
|
||||
$this->log->error($inv_msg_ex);
|
||||
$this->log_service->error($inv_msg_ex);
|
||||
if(!is_null($this->current_request))
|
||||
$this->log->error_msg("current request: ".$this->current_request->toString());
|
||||
$this->log_service->error_msg("current request: ".$this->current_request->toString());
|
||||
return $response;
|
||||
} catch (Exception $ex) {
|
||||
$this->checkpoint_service->trackException($ex);
|
||||
$response = new OpenIdDirectGenericErrorResponse('Server Error');
|
||||
$this->log->error($ex);
|
||||
$this->log_service->error($ex);
|
||||
if(!is_null($this->current_request))
|
||||
$this->log->error_msg("current request: ".$this->current_request->toString());
|
||||
$this->log_service->error_msg("current request: ".$this->current_request->toString());
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: smarcet
|
||||
* Date: 10/28/13
|
||||
* Time: 6:17 PM
|
||||
*/
|
||||
|
||||
namespace openid\handlers\factories;
|
||||
|
||||
|
@ -20,9 +14,9 @@ class SessionAssociationRequestFactory
|
|||
|
||||
public static function buildRequest(OpenIdMessage $message)
|
||||
{
|
||||
if (OpenIdDHAssociationSessionRequest::IsOpenIdAssociationSessionRequest($message))
|
||||
if (OpenIdDHAssociationSessionRequest::IsOpenIdDHAssociationSessionRequest($message))
|
||||
return new OpenIdDHAssociationSessionRequest($message);
|
||||
return OpenIdAssociationSessionRequest($message);
|
||||
return new OpenIdAssociationSessionRequest($message);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -31,7 +25,7 @@ class SessionAssociationRequestFactory
|
|||
*/
|
||||
public static function buildSessionAssociationStrategy(OpenIdMessage $message)
|
||||
{
|
||||
if (OpenIdDHAssociationSessionRequest::IsOpenIdAssociationSessionRequest($message))
|
||||
if (OpenIdDHAssociationSessionRequest::IsOpenIdDHAssociationSessionRequest($message))
|
||||
return new SessionAssociationDHStrategy(new OpenIdDHAssociationSessionRequest($message));
|
||||
if (OpenIdAssociationSessionRequest::IsOpenIdAssociationSessionRequest($message))
|
||||
return new SessionAssociationUnencryptedStrategy(new OpenIdAssociationSessionRequest($message));
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: smarcet
|
||||
* Date: 10/28/13
|
||||
* Time: 6:23 PM
|
||||
*/
|
||||
|
||||
namespace openid\handlers\strategies\implementations;
|
||||
|
||||
|
@ -78,7 +72,6 @@ class SessionAssociationDHStrategy implements ISessionAssociationStrategy
|
|||
} catch (RuntimeException $exDH2) {
|
||||
$response = new OpenIdDirectGenericErrorResponse($exDH2->getMessage());
|
||||
$this->log->error($exDH2);
|
||||
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: smarcet
|
||||
* Date: 10/28/13
|
||||
* Time: 6:57 PM
|
||||
*/
|
||||
|
||||
namespace openid\handlers\strategies\implementations;
|
||||
|
||||
|
@ -28,14 +22,14 @@ class SessionAssociationUnencryptedStrategy implements ISessionAssociationStrate
|
|||
private $association_service;
|
||||
private $server_configuration_service;
|
||||
private $current_request;
|
||||
private $log;
|
||||
private $log_service;
|
||||
|
||||
public function __construct(OpenIdAssociationSessionRequest $request)
|
||||
{
|
||||
$this->current_request = $request;
|
||||
$this->association_service = Registry::getInstance()->get(OpenIdServiceCatalog::AssociationService);
|
||||
$this->server_configuration_service = Registry::getInstance()->get(OpenIdServiceCatalog:: ServerConfigurationService);
|
||||
$this->log = Registry::getInstance()->get(UtilsServiceCatalog:: LogService);
|
||||
$this->current_request = $request;
|
||||
$this->association_service = Registry::getInstance()->get(OpenIdServiceCatalog::AssociationService);
|
||||
$this->server_configuration_service = Registry::getInstance()->get(OpenIdServiceCatalog:: ServerConfigurationService);
|
||||
$this->log_service = Registry::getInstance()->get(UtilsServiceCatalog:: LogService);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -52,22 +46,22 @@ class SessionAssociationUnencryptedStrategy implements ISessionAssociationStrate
|
|||
|
||||
$assoc_handle = AssocHandleGenerator::generate();
|
||||
|
||||
$expires_in = $this->server_configuration_service->getSessionAssociationLifetime();
|
||||
$expires_in = $this->server_configuration_service->getConfigValue("Session.Association.Lifetime");
|
||||
|
||||
$response = new OpenIdUnencryptedAssociationSessionResponse($assoc_handle, $session_type, $assoc_type, $expires_in, $HMAC_secret_handle);
|
||||
$issued = gmdate("Y-m-d H:i:s", time());
|
||||
$this->association_service->addAssociation($assoc_handle, $HMAC_secret_handle, $assoc_type, $expires_in, $issued, IAssociation::TypeSession, null);
|
||||
|
||||
} catch (InvalidDHParam $exDH) {
|
||||
$response = new OpenIdDirectGenericErrorResponse($exDH->getMessage());
|
||||
$this->log->error($exDH);
|
||||
$this->log_service->error($exDH);
|
||||
} catch (InvalidArgumentException $exDH1) {
|
||||
$response = new OpenIdDirectGenericErrorResponse($exDH1->getMessage());
|
||||
$this->log->error($exDH1);
|
||||
$this->log_service->error($exDH1);
|
||||
|
||||
} catch (RuntimeException $exDH2) {
|
||||
$response = new OpenIdDirectGenericErrorResponse($exDH2->getMessage());
|
||||
$this->log->error($exDH2);
|
||||
|
||||
$this->log_service->error($exDH2);
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ use Zend\Math\Rand;
|
|||
class AssocHandleGenerator
|
||||
{
|
||||
|
||||
const PrintableNonWhitespaceCharacters = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~';
|
||||
const PrintableNonWhitespaceCharacters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.-_~';
|
||||
|
||||
/**
|
||||
* @param int $len
|
||||
|
|
|
@ -59,7 +59,7 @@ class OpenIdCryptoHelper
|
|||
} else if ($func == OpenIdProtocol::SignatureAlgorithmHMAC_SHA256) {
|
||||
$macLen = 32; /* 256 bit */
|
||||
} else {
|
||||
return false;
|
||||
$macLen = 20;/* 160 bit */
|
||||
}
|
||||
$bytes = self::randomBytes($macLen);
|
||||
return $bytes;
|
||||
|
|
|
@ -35,4 +35,5 @@ class OpenIdErrorMessages
|
|||
const InvalidMacFunctionMessage = "Invalid mac function %s";
|
||||
const InvalidPrivateAssociationMessage = "Private Association %s was not emit for requested realm %s";
|
||||
const AlreadyExistSessionMessage = "There is a current session with identity %s, but user wants to use a different identity %s";
|
||||
const OAuth2MissingRequiredParam = 'OAuth2 OpenId Extension: missing required field %s';
|
||||
}
|
|
@ -29,6 +29,7 @@ class OpenIdSignatureBuilder
|
|||
$res = false;
|
||||
$signed = $request->getSigned();
|
||||
$claimed_signed = explode(',', $signed);
|
||||
ksort($claimed_signed);
|
||||
$data = '';
|
||||
foreach ($claimed_signed as $key) {
|
||||
$key_php = str_ireplace('.', '_', $key);
|
||||
|
|
|
@ -34,4 +34,6 @@ interface IAssociation
|
|||
|
||||
public function IsExpired();
|
||||
|
||||
public function getRemainingLifetime();
|
||||
|
||||
}
|
|
@ -34,21 +34,21 @@ class OpenIdAuthenticationRequest extends OpenIdRequest
|
|||
public function isValid()
|
||||
{
|
||||
try{
|
||||
$return_to = $this->getReturnTo();
|
||||
$claimed_id = $this->getClaimedId();
|
||||
$identity = $this->getIdentity();
|
||||
$mode = $this->getMode();
|
||||
$realm = $this->getRealm();
|
||||
$valid_realm = OpenIdUriHelper::checkRealm($realm, $return_to);
|
||||
$valid_id = $this->isValidIdentifier($claimed_id, $identity);
|
||||
$return_to = $this->getReturnTo();
|
||||
$claimed_id = $this->getClaimedId();
|
||||
$identity = $this->getIdentity();
|
||||
$mode = $this->getMode();
|
||||
$realm = $this->getRealm();
|
||||
$valid_realm = OpenIdUriHelper::checkRealm($realm, $return_to);
|
||||
$valid_id = $this->isValidIdentifier($claimed_id, $identity);
|
||||
|
||||
return !empty($return_to)
|
||||
&& !empty($realm)
|
||||
&& $valid_realm
|
||||
&& !empty($claimed_id)
|
||||
&& !empty($identity)
|
||||
&& $valid_id
|
||||
&& !empty($mode) && ($mode == OpenIdProtocol::ImmediateMode || $mode == OpenIdProtocol::SetupMode);
|
||||
return !empty($return_to)
|
||||
&& !empty($realm)
|
||||
&& $valid_realm
|
||||
&& !empty($claimed_id)
|
||||
&& !empty($identity)
|
||||
&& $valid_id
|
||||
&& !empty($mode) && ($mode == OpenIdProtocol::ImmediateMode || $mode == OpenIdProtocol::SetupMode);
|
||||
}
|
||||
catch(Exception $ex){
|
||||
$log = Registry::getInstance()->get(UtilsServiceCatalog::LogService);
|
||||
|
|
|
@ -24,14 +24,16 @@ class OpenIdCheckAuthenticationRequest extends OpenIdAuthenticationRequest
|
|||
|
||||
public function isValid()
|
||||
{
|
||||
$mode = $this->getMode();
|
||||
$claimed_assoc = $this->getAssocHandle();
|
||||
$claimed_nonce = $this->getNonce();
|
||||
$claimed_sig = $this->getSig();
|
||||
$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();
|
||||
$claimed_identity = $this->getClaimedId();
|
||||
$claimed_realm = $this->getRealm();
|
||||
$claimed_returnTo = $this->getReturnTo();
|
||||
$signed = $this->getSigned();
|
||||
|
||||
$server_configuration_service = Registry::getInstance()->get("openid\\services\\IServerConfigurationService");
|
||||
if (
|
||||
!is_null($mode) && !empty($mode) && $mode == OpenIdProtocol::CheckAuthenticationMode
|
||||
|
@ -39,6 +41,7 @@ class OpenIdCheckAuthenticationRequest extends OpenIdAuthenticationRequest
|
|||
&& !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($signed) && !empty($signed)
|
||||
&& !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)
|
||||
|
|
|
@ -36,7 +36,7 @@ class OpenIdDHAssociationSessionRequest extends OpenIdAssociationSessionRequest
|
|||
public static function IsOpenIdDHAssociationSessionRequest(OpenIdMessage $message)
|
||||
{
|
||||
if (OpenIdAssociationSessionRequest::IsOpenIdAssociationSessionRequest($message)) {
|
||||
$session_type = $message->getParam(OpenIdProtocol::OpenIDProtocol_AssocType);
|
||||
$session_type = $message->getParam(OpenIdProtocol::OpenIDProtocol_SessionType);
|
||||
if ($session_type == OpenIdProtocol::AssociationSessionTypeDHSHA1 || $session_type == OpenIdProtocol::AssociationSessionTypeDHSHA256)
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,6 @@ class OpenIdUnencryptedAssociationSessionResponse extends OpenIdAssociationSessi
|
|||
public function __construct($assoc_handle, $session_type, $assoc_type, $expires_in, $secret)
|
||||
{
|
||||
parent::__construct($assoc_handle, $session_type, $assoc_type, $expires_in);
|
||||
$this[OpenIdProtocol::OpenIdProtocol_MacKey] = base64_decode($secret);
|
||||
$this[OpenIdProtocol::OpenIdProtocol_MacKey] = base64_encode($secret);
|
||||
}
|
||||
}
|
|
@ -4,9 +4,14 @@ namespace openid\services;
|
|||
|
||||
use openid\model\IAssociation;
|
||||
|
||||
/**
|
||||
* Interface IAssociationService
|
||||
* @package openid\services
|
||||
*/
|
||||
interface IAssociationService
|
||||
{
|
||||
/**
|
||||
/** gets a given association by handle, and if association exists and its type is private, then lock it
|
||||
* to prevent subsequent usage ( private association could be used once)
|
||||
* @param $handle
|
||||
* @param null $realm
|
||||
* @return null|IAssociation
|
||||
|
@ -22,8 +27,9 @@ interface IAssociationService
|
|||
* @param $lifetime
|
||||
* @param $issued
|
||||
* @param $type
|
||||
* @param $realm
|
||||
* @return mixed
|
||||
* @param null $realm
|
||||
* @return IAssociation
|
||||
* @throws \openid\exceptions\ReplayAttackException
|
||||
*/
|
||||
public function addAssociation($handle, $secret, $mac_function, $lifetime, $issued, $type, $realm);
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@ interface IAuthService
|
|||
|
||||
public function setUserAuthorizationResponse($auth_response);
|
||||
|
||||
public function clearUserAuthorizationResponse();
|
||||
|
||||
public function logout();
|
||||
|
||||
public function getUserByOpenId($openid);
|
||||
|
|
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
namespace utils\services;
|
||||
|
||||
/**
|
||||
* Interface ICacheService
|
||||
* @package utils\services
|
||||
*/
|
||||
interface ICacheService {
|
||||
|
||||
/**
|
||||
* Determine if a key exists
|
||||
* @param $key
|
||||
* @return bool
|
||||
*/
|
||||
public function exists($key);
|
||||
|
||||
/**
|
||||
* Delete a key
|
||||
* @param $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function delete($key);
|
||||
|
||||
/**
|
||||
* Delete a key
|
||||
* @param array $keys
|
||||
* @return mixed
|
||||
*/
|
||||
public function deleteArray(array $keys);
|
||||
|
||||
/**
|
||||
* retrieves a hash
|
||||
* @param $name
|
||||
* @param array $values
|
||||
* @return array
|
||||
*/
|
||||
public function getHash($name,array $values);
|
||||
|
||||
/**
|
||||
* save a hash, with an optional time to live
|
||||
* @param $name
|
||||
* @param array $values
|
||||
* @param int $ttl
|
||||
* @return mixed
|
||||
*/
|
||||
public function storeHash($name,array $values, $ttl=0);
|
||||
|
||||
/**
|
||||
* @param $counter_name
|
||||
* @param int $ttl
|
||||
* @return mixed
|
||||
*/
|
||||
public function incCounter($counter_name, $ttl=0);
|
||||
|
||||
/**
|
||||
* @param $counter_name
|
||||
* @return mixed
|
||||
*/
|
||||
public function incCounterIfExists($counter_name);
|
||||
|
||||
public function addMemberSet($set_name,$member);
|
||||
|
||||
public function deleteMemberSet($set_name,$member);
|
||||
|
||||
public function getSet($set_name);
|
||||
|
||||
public function getSingleValue($key);
|
||||
|
||||
public function setSingleValue($key, $value, $ttl=0);
|
||||
|
||||
/**
|
||||
* adds a single value if given keys does not exists, with an optional
|
||||
* time to live
|
||||
* @param $key
|
||||
* @param $value
|
||||
* @param int $ttl
|
||||
* @return mixed
|
||||
*/
|
||||
public function addSingleValue($key, $value, $ttl = 0);
|
||||
|
||||
/**
|
||||
* Set time to live to a given key
|
||||
* @param $key
|
||||
* @param $ttl
|
||||
* @return mixed
|
||||
*/
|
||||
public function setKeyExpiration($key, $ttl);
|
||||
}
|
|
@ -9,4 +9,5 @@ class UtilsServiceCatalog {
|
|||
const AuthenticationService = 'utils\\services\\IAuthService';
|
||||
const LockManagerService = 'utils\\services\\ILockManagerService';
|
||||
const ServerConfigurationService = 'utils\\services\\IServerConfigurationService';
|
||||
const CacheService = 'utils\\services\\ICacheService';
|
||||
}
|
|
@ -7,6 +7,6 @@ class UserAction extends Eloquent
|
|||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo("OpenIdUser");
|
||||
return $this->belongsTo("User");
|
||||
}
|
||||
}
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
class AccessToken extends Eloquent {
|
||||
|
||||
protected $fillable = array('value', 'from_ip', 'associated_authorization_code','lifetime','scope','audience','created_at','updated_at','client_id','refresh_token_id');
|
||||
|
||||
protected $table = 'oauth2_access_token';
|
||||
|
||||
public function refresh_token()
|
||||
|
|
|
@ -29,7 +29,7 @@ class Client extends Eloquent implements IClient {
|
|||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('auth\OpenIdUser');
|
||||
return $this->belongsTo('auth\User');
|
||||
}
|
||||
|
||||
public function resource_server()
|
||||
|
@ -134,7 +134,10 @@ class Client extends Eloquent implements IClient {
|
|||
|
||||
public function getApplicationLogo()
|
||||
{
|
||||
return $this->app_logo;
|
||||
$app_logo = $this->app_logo;
|
||||
if(is_null($app_logo) || empty($app_logo))
|
||||
$app_logo = asset('img/oauth2.default.logo.png');
|
||||
return $app_logo;
|
||||
}
|
||||
|
||||
public function getApplicationDescription()
|
||||
|
|
|
@ -4,6 +4,8 @@ class RefreshToken extends Eloquent {
|
|||
|
||||
protected $table = 'oauth2_refresh_token';
|
||||
|
||||
protected $fillable = array('value', 'from_ip', 'lifetime','scope','audience','void','created_at','updated_at','client_id');
|
||||
|
||||
public function access_tokens()
|
||||
{
|
||||
return $this->hasMany('AccessToken');
|
||||
|
|
|
@ -72,4 +72,16 @@ class OpenIdAssociation extends Eloquent implements IAssociation
|
|||
{
|
||||
// TODO: Implement setRealm() method.
|
||||
}
|
||||
|
||||
public function getRemainingLifetime()
|
||||
{
|
||||
$created_at = new DateTime($this->issued);
|
||||
$created_at->add(new DateInterval('PT' . $this->lifetime . 'S'));
|
||||
$now = new DateTime(gmdate("Y-m-d H:i:s", time()));
|
||||
//check validity...
|
||||
if ($now > $created_at)
|
||||
return -1;
|
||||
$seconds = abs($created_at->getTimestamp() - $now->getTimestamp());;
|
||||
return $seconds;
|
||||
}
|
||||
}
|
|
@ -25,7 +25,7 @@ class OpenIdTrustedSite extends Eloquent implements ITrustedSite
|
|||
|
||||
public function getData()
|
||||
{
|
||||
$res = $this->data;
|
||||
$res = is_null($this->data)?'[]':$this->data;
|
||||
return json_decode($res);
|
||||
}
|
||||
|
||||
|
@ -36,7 +36,7 @@ class OpenIdTrustedSite extends Eloquent implements ITrustedSite
|
|||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo('auth\OpenIdUser');
|
||||
return $this->belongsTo('auth\User');
|
||||
}
|
||||
|
||||
public function getAuthorizationPolicy()
|
||||
|
|
|
@ -1,27 +1,35 @@
|
|||
<?php
|
||||
|
||||
namespace services;
|
||||
|
||||
use BannedIP;
|
||||
use DB;
|
||||
use Log;
|
||||
use utils\services\ICacheService;
|
||||
use utils\services\ILockManagerService;
|
||||
use utils\services\ISecurityPolicy;
|
||||
use utils\services\ISecurityPolicyCounterMeasure;
|
||||
use utils\services\IServerConfigurationService;
|
||||
use utils\services\ILockManagerService;
|
||||
use Log;
|
||||
use BannedIP;
|
||||
use DB;
|
||||
|
||||
abstract class AbstractBlacklistSecurityPolicy implements ISecurityPolicy {
|
||||
abstract class AbstractBlacklistSecurityPolicy implements ISecurityPolicy
|
||||
{
|
||||
|
||||
protected $server_configuration_service;
|
||||
protected $redis;
|
||||
protected $counter_measure;
|
||||
protected $lock_manager_service;
|
||||
protected $cache_service;
|
||||
|
||||
public function __construct(IServerConfigurationService $server_configuration_service, ILockManagerService $lock_manager_service)
|
||||
public function __construct(IServerConfigurationService $server_configuration_service, ILockManagerService $lock_manager_service, ICacheService $cache_service)
|
||||
{
|
||||
|
||||
$this->redis = \RedisLV4::connection();
|
||||
$this->server_configuration_service = $server_configuration_service;
|
||||
$this->lock_manager_service = $lock_manager_service;
|
||||
$this->lock_manager_service = $lock_manager_service;
|
||||
$this->cache_service = $cache_service;
|
||||
}
|
||||
|
||||
public function setCounterMeasure(ISecurityPolicyCounterMeasure $counter_measure)
|
||||
{
|
||||
$this->counter_measure = $counter_measure;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -33,23 +41,20 @@ abstract class AbstractBlacklistSecurityPolicy implements ISecurityPolicy {
|
|||
{
|
||||
try {
|
||||
$remote_address = IPHelper::getUserIp();
|
||||
//try to create on redis
|
||||
$success = $this->redis->setnx($remote_address, $initial_hits);
|
||||
if ($success) { // if we created the set expiration on redis
|
||||
$this->redis->expire($remote_address, intval($this->server_configuration_service->getConfigValue("BlacklistSecurityPolicy.BannedIpLifeTimeSeconds")));
|
||||
}
|
||||
//try to create on cache
|
||||
$this->cache_service->addSingleValue($remote_address, $initial_hits, intval($this->server_configuration_service->getConfigValue("BlacklistSecurityPolicy.BannedIpLifeTimeSeconds")));
|
||||
|
||||
Log::warning(sprintf("AbstractBlacklistSecurityPolicy: Banning ip %s by Exception %s", $remote_address, $exception_type));
|
||||
//try to create on db
|
||||
|
||||
DB::transaction(function () use($remote_address,$exception_type,$initial_hits) {
|
||||
DB::transaction(function () use ($remote_address, $exception_type, $initial_hits) {
|
||||
$banned_ip = BannedIP::where("ip", "=", $remote_address)->first();
|
||||
if (!$banned_ip) {
|
||||
$banned_ip = new BannedIP();
|
||||
$banned_ip = new BannedIP();
|
||||
$banned_ip->ip = $remote_address;
|
||||
}
|
||||
$banned_ip->exception_type = $exception_type;
|
||||
$banned_ip->hits = $initial_hits;
|
||||
$banned_ip->hits = $initial_hits;
|
||||
$banned_ip->Save();
|
||||
});
|
||||
|
||||
|
@ -58,9 +63,4 @@ abstract class AbstractBlacklistSecurityPolicy implements ISecurityPolicy {
|
|||
}
|
||||
}
|
||||
|
||||
public function setCounterMeasure(ISecurityPolicyCounterMeasure $counter_measure)
|
||||
{
|
||||
$this->counter_measure = $counter_measure;
|
||||
}
|
||||
|
||||
}
|
|
@ -9,6 +9,7 @@ use Exception;
|
|||
use Log;
|
||||
use UserExceptionTrail;
|
||||
use utils\exceptions\UnacquiredLockException;
|
||||
use utils\services\ICacheService;
|
||||
use utils\services\ILockManagerService;
|
||||
use utils\services\IServerConfigurationService;
|
||||
|
||||
|
@ -22,9 +23,9 @@ class BlacklistSecurityPolicy extends AbstractBlacklistSecurityPolicy
|
|||
|
||||
private $exception_dictionary = array();
|
||||
|
||||
public function __construct(IServerConfigurationService $server_configuration_service, ILockManagerService $lock_manager_service)
|
||||
public function __construct(IServerConfigurationService $server_configuration_service, ILockManagerService $lock_manager_service, ICacheService $cache_service)
|
||||
{
|
||||
parent::__construct($server_configuration_service, $lock_manager_service);
|
||||
parent::__construct($server_configuration_service, $lock_manager_service, $cache_service);
|
||||
// here we configure on which exceptions are we interested and the max occurrence attempts and initial delay on tar pit for
|
||||
// offending IP address
|
||||
$this->exception_dictionary = array(
|
||||
|
@ -34,6 +35,7 @@ class BlacklistSecurityPolicy extends AbstractBlacklistSecurityPolicy
|
|||
'openid\exceptions\OpenIdInvalidRealmException' => array('BlacklistSecurityPolicy.MaxOpenIdInvalidRealmExceptionAttempts','BlacklistSecurityPolicy.OpenIdInvalidRealmExceptionInitialDelay'),
|
||||
'openid\exceptions\InvalidOpenIdMessageMode' => array('BlacklistSecurityPolicy.MaxInvalidOpenIdMessageModeAttempts','BlacklistSecurityPolicy.InvalidOpenIdMessageModeInitialDelay'),
|
||||
'openid\exceptions\InvalidOpenIdAuthenticationRequestMode' => array('BlacklistSecurityPolicy.MaxInvalidOpenIdAuthenticationRequestModeAttempts','BlacklistSecurityPolicy.InvalidOpenIdAuthenticationRequestModeInitialDelay'),
|
||||
'openid\exceptions\InvalidAssociation' => array('BlacklistSecurityPolicy.MaxInvalidAssociationAttempts','BlacklistSecurityPolicy.InvalidAssociationInitialDelay'),
|
||||
'auth\exceptions\AuthenticationException' => array('BlacklistSecurityPolicy.MaxAuthenticationExceptionAttempts','BlacklistSecurityPolicy.AuthenticationExceptionInitialDelay'),
|
||||
'oauth2\exceptions\ReplayAttackException' => array(null,'BlacklistSecurityPolicy.OAuth2.AuthCodeReplayAttackInitialDelay'),
|
||||
'oauth2\exceptions\InvalidAuthorizationCodeException' => array('BlacklistSecurityPolicy.OAuth2.MaxInvalidAuthorizationCodeAttempts','BlacklistSecurityPolicy.OAuth2.InvalidAuthorizationCodeInitialDelay'),
|
||||
|
@ -49,58 +51,44 @@ class BlacklistSecurityPolicy extends AbstractBlacklistSecurityPolicy
|
|||
{
|
||||
$res = true;
|
||||
$remote_address = IPHelper::getUserIp();
|
||||
|
||||
try {
|
||||
//check if banned ip is on redis ...
|
||||
if ($this->redis->exists($remote_address)) {
|
||||
$this->redis->incr($remote_address);
|
||||
$res = false;
|
||||
} else {
|
||||
//check on db
|
||||
$banned_ip = BannedIP::where("ip", "=", $remote_address)->first();
|
||||
//if exists ?
|
||||
if ($banned_ip) {
|
||||
//set lock
|
||||
$this->lock_manager_service->acquireLock("lock.ip." . $remote_address);
|
||||
|
||||
try {
|
||||
|
||||
$issued = $banned_ip->created_at;
|
||||
$utc_now = gmdate("Y-m-d H:i:s", time());
|
||||
$utc_now = DateTime::createFromFormat("Y-m-d H:i:s", $utc_now);
|
||||
|
||||
//get time lived on seconds
|
||||
$time_lived_seconds = abs($utc_now->getTimestamp() - $issued->getTimestamp());
|
||||
|
||||
if ($time_lived_seconds >= intval($this->server_configuration_service->getConfigValue("BlacklistSecurityPolicy.BannedIpLifeTimeSeconds"))) {
|
||||
//void banned ip
|
||||
$banned_ip->delete();
|
||||
} else {
|
||||
$banned_ip->hits = $banned_ip->hits + 1;
|
||||
$banned_ip->Save();
|
||||
//add ip back to redis
|
||||
$success = $this->redis->setnx($banned_ip->ip, $banned_ip->hits);
|
||||
if ($success) {
|
||||
//set remaining time to live
|
||||
$this->redis->expire($remote_address, intval($this->server_configuration_service->getConfigValue("BlacklistSecurityPolicy.BannedIpLifeTimeSeconds") - $time_lived_seconds));
|
||||
}
|
||||
$res = false;
|
||||
//release lock
|
||||
|
||||
}
|
||||
} catch (Exception $ex) {
|
||||
//release lock
|
||||
|
||||
Log::error($ex);
|
||||
$res = false;
|
||||
//check if banned ip is on cache ...
|
||||
if ($this->cache_service->incCounterIfExists($remote_address)){
|
||||
$this->counter_measure->trigger();
|
||||
return false;
|
||||
}
|
||||
//check on db
|
||||
if (!is_null($banned_ip = BannedIP::where("ip", "=", $remote_address)->first())) {
|
||||
// banned ip exists on DB, set lock
|
||||
$this->lock_manager_service->acquireLock("lock.ip." . $remote_address);
|
||||
try {
|
||||
//check lifetime
|
||||
$issued = $banned_ip->created_at;
|
||||
$utc_now = gmdate("Y-m-d H:i:s", time());
|
||||
$utc_now = DateTime::createFromFormat("Y-m-d H:i:s", $utc_now);
|
||||
//get time lived on seconds
|
||||
$time_lived_seconds = abs($utc_now->getTimestamp() - $issued->getTimestamp());
|
||||
if ($time_lived_seconds >= intval($this->server_configuration_service->getConfigValue("BlacklistSecurityPolicy.BannedIpLifeTimeSeconds"))) {
|
||||
//void banned ip
|
||||
$banned_ip->delete();
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->lock_manager_service->releaseLock("lock.ip." . $remote_address);
|
||||
$banned_ip->hits = $banned_ip->hits + 1;
|
||||
$banned_ip->Save();
|
||||
//save ip on cache
|
||||
$this->cache_service->addSingleValue($banned_ip->ip, $banned_ip->hits,intval($this->server_configuration_service->getConfigValue("BlacklistSecurityPolicy.BannedIpLifeTimeSeconds") - $time_lived_seconds));
|
||||
}
|
||||
}
|
||||
if (!$res)
|
||||
catch (Exception $ex) {
|
||||
Log::error($ex);
|
||||
}
|
||||
//release lock
|
||||
$this->lock_manager_service->releaseLock("lock.ip." . $remote_address);
|
||||
$this->counter_measure->trigger();
|
||||
} catch (UnacquiredLockException $ex1) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (UnacquiredLockException $ex1) {
|
||||
Log::error($ex1);
|
||||
$res = false;
|
||||
} catch (Exception $ex) {
|
||||
|
|
|
@ -4,22 +4,24 @@ namespace services;
|
|||
|
||||
use Exception;
|
||||
use Log;
|
||||
use utils\services\ICacheService;
|
||||
use utils\services\ISecurityPolicyCounterMeasure;
|
||||
|
||||
class DelayCounterMeasure implements \utils\services\ISecurityPolicyCounterMeasure
|
||||
class DelayCounterMeasure implements ISecurityPolicyCounterMeasure
|
||||
{
|
||||
private $redis;
|
||||
private $cache_service;
|
||||
|
||||
public function __construct(){
|
||||
$this->redis = \RedisLV4::connection();
|
||||
public function __construct(ICacheService $cache_service){
|
||||
$this->cache_service = $cache_service;
|
||||
}
|
||||
|
||||
public function trigger(array $params = array())
|
||||
{
|
||||
try {
|
||||
$remote_address = IPHelper::getUserIp();
|
||||
if ($this->redis->exists($remote_address)) {
|
||||
if ($this->cache_service->exists($remote_address)) {
|
||||
Log::warning(sprintf("DelayCounterMeasure: attempt from banned ip %s",$remote_address));
|
||||
$hits = $this->redis->get($remote_address);
|
||||
$hits = intval($this->cache_service->getSingleValue($remote_address));
|
||||
sleep(2 ^ $hits);
|
||||
}
|
||||
} catch (Exception $ex) {
|
||||
|
|
|
@ -2,20 +2,21 @@
|
|||
|
||||
namespace services;
|
||||
|
||||
use utils\services\ICacheService;
|
||||
use utils\services\ILockManagerService;
|
||||
use utils\exceptions\UnacquiredLockException;
|
||||
|
||||
class LockManagerService implements ILockManagerService {
|
||||
|
||||
private $redis;
|
||||
private $cache_service;
|
||||
|
||||
public function __construct(){
|
||||
$this->redis = \RedisLV4::connection();
|
||||
public function __construct(ICacheService $cache_service){
|
||||
$this->cache_service = $cache_service;
|
||||
}
|
||||
|
||||
public function acquireLock($name,$lifetime=3600)
|
||||
{
|
||||
$success = $this->redis->setnx($name , time()+$lifetime+1);
|
||||
$success = $this->cache_service->addSingleValue($name,time()+$lifetime+1,time()+$lifetime+1);
|
||||
if (!$success) { // only one time we could use this handle
|
||||
throw new UnacquiredLockException(sprintf("lock name %s",$name));
|
||||
}
|
||||
|
@ -23,6 +24,6 @@ class LockManagerService implements ILockManagerService {
|
|||
|
||||
public function releaseLock($name)
|
||||
{
|
||||
$this->redis->del($name);
|
||||
$this->cache_service->delete($name);
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace services;
|
||||
|
||||
use auth\OpenIdUser;
|
||||
use auth\User;
|
||||
use Exception;
|
||||
use Log;
|
||||
use openid\services\OpenIdServiceCatalog;
|
||||
|
@ -21,7 +21,7 @@ class LockUserCounterMeasure implements ISecurityPolicyCounterMeasure
|
|||
$server_configuration = Registry::getInstance()->get(OpenIdServiceCatalog::ServerConfigurationService);
|
||||
$user_service = Registry::getInstance()->get(OpenIdServiceCatalog::UserService);
|
||||
|
||||
$user = OpenIdUser::where('external_id', '=', $user_identifier)->first();
|
||||
$user = User::where('external_id', '=', $user_identifier)->first();
|
||||
if(is_null($user))
|
||||
return;
|
||||
//apply lock policy
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
<?php
|
||||
|
||||
namespace services;
|
||||
|
||||
use utils\services\ICacheService;
|
||||
|
||||
/**
|
||||
* Class RedisCacheService
|
||||
* Cache Service Implementation Based on REDIS
|
||||
* http://redis.io
|
||||
* @package services
|
||||
*/
|
||||
class RedisCacheService implements ICacheService {
|
||||
|
||||
//services
|
||||
private $redis;
|
||||
|
||||
public function __construct(){
|
||||
$this->redis = \RedisLV4::connection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function delete($key)
|
||||
{
|
||||
$res = 0;
|
||||
if ($this->redis->exists($key)) {
|
||||
$res = $this->redis->del($key);
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function deleteArray(array $keys){
|
||||
if(count($keys)>0)
|
||||
$this->redis->del($keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @return bool
|
||||
*/
|
||||
public function exists($key){
|
||||
$res = $this->redis->exists($key);
|
||||
return $res>0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param array $values
|
||||
* @return mixed
|
||||
*/
|
||||
public function getHash($name, array $values)
|
||||
{
|
||||
$res = array();
|
||||
if($this->redis->exists($name)){
|
||||
$cache_values = $this->redis->hmget($name,$values);
|
||||
for($i=0;$i<count($cache_values);$i++)
|
||||
$res[$values[$i]] = $cache_values[$i];
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function storeHash($name,array $values, $ttl=0){
|
||||
$res = false;
|
||||
//stores in REDIS
|
||||
if(!$this->redis->exists($name)){
|
||||
$this->redis->hmset($name, $values);
|
||||
$res = true;
|
||||
//sets expiration time
|
||||
if($ttl>0) $this->redis->expire($name, $ttl);
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function incCounter($counter_name, $ttl = 0)
|
||||
{
|
||||
if($this->redis->setnx($counter_name,1))
|
||||
$this->redis->expire($counter_name, $ttl);
|
||||
else
|
||||
$this->redis->incr($counter_name);
|
||||
}
|
||||
|
||||
public function incCounterIfExists($counter_name){
|
||||
$res = false;
|
||||
if ($this->redis->exists($counter_name)) {
|
||||
$this->redis->incr($counter_name);
|
||||
$res = true;
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function addMemberSet($set_name, $member){
|
||||
return $this->redis->sadd($set_name, $member);
|
||||
}
|
||||
|
||||
public function deleteMemberSet($set_name,$member){
|
||||
return $this->redis->srem($set_name,$member);
|
||||
}
|
||||
|
||||
public function getSet($set_name){
|
||||
return $this->redis->smembers($set_name);
|
||||
}
|
||||
|
||||
public function getSingleValue($key){
|
||||
return $this->redis->get($key);
|
||||
}
|
||||
|
||||
public function setSingleValue($key,$value,$ttl = 0){
|
||||
if($ttl>0)
|
||||
return $this->redis->setex($key , $ttl, $value);
|
||||
else
|
||||
return $this->redis->set($key ,$value);
|
||||
}
|
||||
|
||||
public function addSingleValue($key, $value, $ttl = 0){
|
||||
$res = $this->redis->setnx($key , $value);
|
||||
if($res>0 && $ttl>0)
|
||||
$this->redis->expire($key,$ttl);
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function setKeyExpiration($key, $ttl){
|
||||
$this->redis->expire($key, intval($ttl));
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ namespace services;
|
|||
use Exception;
|
||||
use openid\services\IServerConfigurationService as IOpenIdServerConfigurationService;
|
||||
use ServerConfiguration;
|
||||
use utils\services\ICacheService;
|
||||
use utils\services\IServerConfigurationService;
|
||||
|
||||
class ServerConfigurationService implements IOpenIdServerConfigurationService,IServerConfigurationService
|
||||
|
@ -16,28 +17,15 @@ class ServerConfigurationService implements IOpenIdServerConfigurationService,IS
|
|||
const DefaultMaxFailedLoginAttempts = 10;
|
||||
const DefaultMaxFailedLoginAttempts2ShowCaptcha = 3;
|
||||
const DefaultNonceLifetime = 360;
|
||||
private $private_association_lifetime;
|
||||
private $session_association_lifetime;
|
||||
private $max_failed_login_attempts;
|
||||
private $max_failed_login_attempts_2_show_captcha;
|
||||
private $nonce_lifetime;
|
||||
private $assets_url;
|
||||
private $redis;
|
||||
|
||||
private $default_config_params;
|
||||
|
||||
public function __construct()
|
||||
private $cache_service;
|
||||
|
||||
public function __construct(ICacheService $cache_service)
|
||||
{
|
||||
//todo: remove all specific methods per key and use getConfigValue
|
||||
$this->private_association_lifetime = null;
|
||||
$this->session_association_lifetime = null;
|
||||
$this->max_failed_login_attempts = null;
|
||||
$this->max_failed_login_attempts_2_show_captcha = null;
|
||||
$this->nonce_lifetime = null;
|
||||
$this->assets_url = null;
|
||||
|
||||
|
||||
$this->redis = \RedisLV4::connection();
|
||||
|
||||
$this->cache_service = $cache_service;
|
||||
//default config values
|
||||
$this->default_config_params = array();
|
||||
$this->default_config_params["Private.Association.Lifetime"] = 240;
|
||||
|
@ -62,6 +50,8 @@ class ServerConfigurationService implements IOpenIdServerConfigurationService,IS
|
|||
$this->default_config_params["BlacklistSecurityPolicy.InvalidOpenIdAuthenticationRequestModeInitialDelay"] = 10;
|
||||
$this->default_config_params["BlacklistSecurityPolicy.MaxAuthenticationExceptionAttempts"] = 10;
|
||||
$this->default_config_params["BlacklistSecurityPolicy.AuthenticationExceptionInitialDelay"] = 20;
|
||||
$this->default_config_params["BlacklistSecurityPolicy.MaxInvalidAssociationAttempts"] = 10;
|
||||
$this->default_config_params["BlacklistSecurityPolicy.InvalidAssociationInitialDelay"] = 20;
|
||||
|
||||
|
||||
$this->default_config_params["BlacklistSecurityPolicy.OAuth2.MaxAuthCodeReplayAttackAttempts"] = 3;
|
||||
|
@ -93,8 +83,8 @@ class ServerConfigurationService implements IOpenIdServerConfigurationService,IS
|
|||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* get config value from redis and if not in redis check for it on table server_configuration
|
||||
/**
|
||||
* get config value from cache and if not in cache check for it on table server_configuration
|
||||
* @param $key
|
||||
* @return mixed
|
||||
*/
|
||||
|
@ -103,25 +93,24 @@ class ServerConfigurationService implements IOpenIdServerConfigurationService,IS
|
|||
$res = null;
|
||||
try {
|
||||
|
||||
if (!$this->redis->exists($key)) {
|
||||
$conf = ServerConfiguration::where('key', '=', $key)->first();
|
||||
if ($conf)
|
||||
$this->redis->setnx($key, $conf->value);
|
||||
if (!$this->cache_service->exists($key)) {
|
||||
|
||||
if (!is_null($conf = ServerConfiguration::where('key', '=', $key)->first()))
|
||||
$this->cache_service->addSingleValue($key, $conf->value);
|
||||
else
|
||||
if (isset($this->default_config_params[$key]))
|
||||
$this->redis->setnx($key, $this->default_config_params[$key]);
|
||||
$this->cache_service->addSingleValue($key, $this->default_config_params[$key]);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
$res = $this->redis->get($key);
|
||||
$res = $this->cache_service->getSingleValue($key);
|
||||
|
||||
} catch (Exception $ex) {
|
||||
Log::error($ex);
|
||||
if (isset($this->default_config_params[$key])) {
|
||||
$res = $this->default_config_params[$key];
|
||||
}
|
||||
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,19 @@ class ServicesProvider extends ServiceProvider
|
|||
|
||||
public function boot()
|
||||
{
|
||||
|
||||
$this->app->singleton(UtilsServiceCatalog::CacheService, 'services\\RedisCacheService');
|
||||
|
||||
$this->app['serverconfigurationservice'] = $this->app->share(function ($app) {
|
||||
return new ServerConfigurationService($this->app->make(UtilsServiceCatalog::CacheService));
|
||||
});
|
||||
|
||||
// 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');
|
||||
});
|
||||
|
||||
//register on boot bc we rely on Illuminate\Redis\ServiceProvider\RedisServiceProvider
|
||||
$this->app->singleton(OpenIdServiceCatalog::MementoService, 'services\\MementoRequestService');
|
||||
$this->app->singleton(OpenIdServiceCatalog::AuthenticationStrategy, 'services\\AuthenticationStrategy');
|
||||
|
@ -26,6 +39,7 @@ class ServicesProvider extends ServiceProvider
|
|||
$this->app->singleton(UtilsServiceCatalog::LockManagerService, 'services\\LockManagerService');
|
||||
$this->app->singleton(UtilsServiceCatalog::ServerConfigurationService, 'services\\ServerConfigurationService');
|
||||
|
||||
|
||||
$this->app->singleton("services\\DelayCounterMeasure", 'services\\DelayCounterMeasure');
|
||||
$this->app->singleton("services\\LockUserCounterMeasure", 'services\\LockUserCounterMeasure');
|
||||
$this->app->singleton("services\\oauth2\\RevokeAuthorizationCodeRelatedTokens", 'services\\oauth2\\RevokeAuthorizationCodeRelatedTokens');
|
||||
|
@ -63,6 +77,7 @@ class ServicesProvider extends ServiceProvider
|
|||
return $checkpoint_service;
|
||||
});
|
||||
|
||||
Registry::getInstance()->set(UtilsServiceCatalog::CheckPointService, $this->app->make(UtilsServiceCatalog::CheckPointService));
|
||||
Registry::getInstance()->set(OpenIdServiceCatalog::MementoService, $this->app->make(OpenIdServiceCatalog::MementoService));
|
||||
Registry::getInstance()->set(OpenIdServiceCatalog::AuthenticationStrategy, $this->app->make(OpenIdServiceCatalog::AuthenticationStrategy));
|
||||
Registry::getInstance()->set(OpenIdServiceCatalog::ServerExtensionsService, $this->app->make(OpenIdServiceCatalog::ServerExtensionsService));
|
||||
|
@ -75,6 +90,7 @@ class ServicesProvider extends ServiceProvider
|
|||
Registry::getInstance()->set(UtilsServiceCatalog::LogService, $this->app->make(UtilsServiceCatalog::LogService));
|
||||
Registry::getInstance()->set(UtilsServiceCatalog::CheckPointService, $this->app->make(UtilsServiceCatalog::CheckPointService));
|
||||
Registry::getInstance()->set(UtilsServiceCatalog::ServerConfigurationService, $this->app->make(UtilsServiceCatalog::ServerConfigurationService));
|
||||
Registry::getInstance()->set(UtilsServiceCatalog::CacheService, $this->app->make(UtilsServiceCatalog::CacheService));
|
||||
|
||||
$this->app->singleton(OAuth2ServiceCatalog::MementoService, 'services\\oauth2\\MementoOAuth2AuthenticationRequestService');
|
||||
$this->app->singleton(OAuth2ServiceCatalog::ClientService, 'services\\oauth2\\ClientService');
|
||||
|
@ -94,15 +110,7 @@ class ServicesProvider extends ServiceProvider
|
|||
public function register()
|
||||
{
|
||||
|
||||
$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');
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace services;
|
||||
|
||||
use auth\OpenIdUser;
|
||||
use auth\User;
|
||||
use Exception;
|
||||
use openid\model\IOpenIdUser;
|
||||
use UserAction;
|
||||
|
@ -17,7 +17,7 @@ class UserActionService implements IUserActionService
|
|||
$action->from_ip = $ip;
|
||||
$action->user_action = $user_action;
|
||||
$action->realm = $realm;
|
||||
$user = OpenIdUser::find($user->getId());
|
||||
$user = User::find($user->getId());
|
||||
if ($user) {
|
||||
$user->actions()->save($action);
|
||||
return true;
|
||||
|
|
|
@ -2,10 +2,11 @@
|
|||
|
||||
namespace services;
|
||||
|
||||
use auth\OpenIdUser;
|
||||
use auth\User;
|
||||
use Log;
|
||||
use openid\services\IUserService;
|
||||
use Exception;
|
||||
use DB;
|
||||
|
||||
class UserService implements IUserService
|
||||
{
|
||||
|
@ -13,9 +14,9 @@ class UserService implements IUserService
|
|||
public function associateUser($id, $proposed_username)
|
||||
{
|
||||
try {
|
||||
$user = OpenIdUser::where('id', '=', $id)->first();
|
||||
$user = User::where('id', '=', $id)->first();
|
||||
if (!is_null($user)) {
|
||||
\DB::transaction(function () use ($id, $proposed_username) {
|
||||
DB::transaction(function () use ($id, $proposed_username) {
|
||||
$done = false;
|
||||
$fragment_nbr = 1;
|
||||
$aux_proposed_username = $proposed_username;
|
||||
|
@ -45,10 +46,10 @@ class UserService implements IUserService
|
|||
public function updateLastLoginDate($identifier)
|
||||
{
|
||||
try {
|
||||
$user = OpenIdUser::where('id', '=', $identifier)->first();
|
||||
$user = User::where('id', '=', $identifier)->first();
|
||||
if (!is_null($user)) {
|
||||
\DB::transaction(function () use ($identifier) {
|
||||
\DB::table('openid_users')->where('id', '=', $identifier)->update(array('last_login_date' => gmdate("Y-m-d H:i:s", time())));
|
||||
DB::transaction(function () use ($identifier) {
|
||||
DB::table('openid_users')->where('id', '=', $identifier)->update(array('last_login_date' => gmdate("Y-m-d H:i:s", time())));
|
||||
});
|
||||
}
|
||||
} catch (Exception $ex) {
|
||||
|
@ -59,12 +60,12 @@ class UserService implements IUserService
|
|||
public function updateFailedLoginAttempts($identifier)
|
||||
{
|
||||
try {
|
||||
$user = OpenIdUser::where('id', '=', $identifier)->first();
|
||||
$user = User::where('id', '=', $identifier)->first();
|
||||
if (!is_null($user)) {
|
||||
$attempts = $user->login_failed_attempt;
|
||||
++$attempts;
|
||||
\DB::transaction(function () use ($identifier, $attempts) {
|
||||
\DB::table('openid_users')->where('id', '=', $identifier)->update(array('login_failed_attempt' => $attempts));
|
||||
DB::transaction(function () use ($identifier, $attempts) {
|
||||
DB::table('openid_users')->where('id', '=', $identifier)->update(array('login_failed_attempt' => $attempts));
|
||||
});
|
||||
}
|
||||
} catch (Exception $ex) {
|
||||
|
@ -75,10 +76,10 @@ class UserService implements IUserService
|
|||
public function lockUser($identifier)
|
||||
{
|
||||
try {
|
||||
$user = OpenIdUser::where('id', '=', $identifier)->first();
|
||||
$user = User::where('id', '=', $identifier)->first();
|
||||
if (!is_null($user)) {
|
||||
\DB::transaction(function () use ($identifier) {
|
||||
\DB::table('openid_users')->where('id', '=', $identifier)->update(array('lock' => 1));
|
||||
DB::transaction(function () use ($identifier) {
|
||||
DB::table('openid_users')->where('id', '=', $identifier)->update(array('lock' => 1));
|
||||
});
|
||||
Log::warning(sprintf("User %d locked ", $identifier));
|
||||
}
|
||||
|
@ -89,10 +90,10 @@ class UserService implements IUserService
|
|||
|
||||
public function unlockUser($identifier)
|
||||
{
|
||||
$user = OpenIdUser::where('id', '=', $identifier)->first();
|
||||
$user = User::where('id', '=', $identifier)->first();
|
||||
if (!is_null($user)) {
|
||||
\DB::transaction(function () use ($identifier) {
|
||||
\DB::table('openid_users')->where('id', '=', $identifier)->update(array('lock' => 0));
|
||||
DB::transaction(function () use ($identifier) {
|
||||
DB::table('openid_users')->where('id', '=', $identifier)->update(array('lock' => 0));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -100,10 +101,10 @@ class UserService implements IUserService
|
|||
public function activateUser($identifier)
|
||||
{
|
||||
try {
|
||||
$user = OpenIdUser::where('id', '=', $identifier)->first();
|
||||
$user = User::where('id', '=', $identifier)->first();
|
||||
if (!is_null($user)) {
|
||||
\DB::transaction(function () use ($identifier) {
|
||||
\DB::table('openid_users')->where('id', '=', $identifier)->update(array('active' => 1));
|
||||
DB::transaction(function () use ($identifier) {
|
||||
DB::table('openid_users')->where('id', '=', $identifier)->update(array('active' => 1));
|
||||
});
|
||||
}
|
||||
} catch (Exception $ex) {
|
||||
|
@ -114,10 +115,10 @@ class UserService implements IUserService
|
|||
public function deActivateUser($identifier)
|
||||
{
|
||||
try {
|
||||
$user = OpenIdUser::where('id', '=', $identifier)->first();
|
||||
$user = User::where('id', '=', $identifier)->first();
|
||||
if (!is_null($user)) {
|
||||
\DB::transaction(function () use ($identifier) {
|
||||
\DB::table('openid_users')->where('id', '=', $identifier)->update(array('active' => 0));
|
||||
DB::transaction(function () use ($identifier) {
|
||||
DB::table('openid_users')->where('id', '=', $identifier)->update(array('active' => 0));
|
||||
});
|
||||
}
|
||||
} catch (Exception $ex) {
|
||||
|
@ -128,7 +129,7 @@ class UserService implements IUserService
|
|||
public function saveProfileInfo($identifier, $show_pic, $show_full_name, $show_email)
|
||||
{
|
||||
try {
|
||||
$user = OpenIdUser::where('id', '=', $identifier)->first();
|
||||
$user = User::where('id', '=', $identifier)->first();
|
||||
if (!is_null($user)) {
|
||||
$user->public_profile_show_photo = $show_pic;
|
||||
$user->public_profile_show_fullname = $show_full_name;
|
||||
|
|
|
@ -5,15 +5,16 @@ namespace services\oauth2;
|
|||
use Exception;
|
||||
use DB;
|
||||
use Log;
|
||||
use utils\services\ICacheService;
|
||||
use utils\services\IServerConfigurationService;
|
||||
use services\AbstractBlacklistSecurityPolicy;
|
||||
use utils\services\ILockManagerService;
|
||||
|
||||
class AuthorizationCodeRedeemPolicy extends AbstractBlacklistSecurityPolicy {
|
||||
|
||||
public function __construct(IServerConfigurationService $server_configuration_service, ILockManagerService $lock_manager_service)
|
||||
public function __construct(IServerConfigurationService $server_configuration_service, ILockManagerService $lock_manager_service, ICacheService $cache_service)
|
||||
{
|
||||
parent::__construct($server_configuration_service,$lock_manager_service);
|
||||
parent::__construct($server_configuration_service,$lock_manager_service,$cache_service);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,7 +18,7 @@ class MementoOAuth2AuthenticationRequestService implements IMementoOAuth2Authent
|
|||
*/
|
||||
public function saveCurrentAuthorizationRequest()
|
||||
{
|
||||
$input = Input::all();
|
||||
$input = Input::all();
|
||||
$oauth2_params = array();
|
||||
foreach ($input as $key => $value) {
|
||||
if (array_key_exists($key, OAuth2AuthorizationRequest::$params) === true) {
|
||||
|
@ -72,7 +72,21 @@ class MementoOAuth2AuthenticationRequestService implements IMementoOAuth2Authent
|
|||
|
||||
public function clearCurrentRequest()
|
||||
{
|
||||
// TODO: Implement clearCurrentRequest() method.
|
||||
$old_data = Input::old();
|
||||
$oauth2_params = array();
|
||||
|
||||
foreach ($old_data as $key => $value) {
|
||||
if (array_key_exists($key, OAuth2AuthorizationRequest::$params) === true){
|
||||
array_push($oauth2_params, $key);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($oauth2_params) > 0) {
|
||||
foreach ($oauth2_params as $oauth2_param) {
|
||||
Session::forget($oauth2_param);
|
||||
Session::remove($oauth2_param);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -29,13 +29,13 @@ use Zend\Crypt\Hash;
|
|||
|
||||
use DateInterval;
|
||||
use DateTime;
|
||||
use utils\services\ICacheService;
|
||||
|
||||
/**
|
||||
* Class TokenService
|
||||
* Provides all Tokens related operations (create, get and revoke)
|
||||
* @package services\oauth2
|
||||
*/
|
||||
|
||||
class TokenService implements ITokenService
|
||||
{
|
||||
const ClientAccessTokenPrefixList = '.atokens';
|
||||
|
@ -50,19 +50,19 @@ class TokenService implements ITokenService
|
|||
const ClientRefreshTokensQty = '.rtokens.qty';
|
||||
const ClientRefreshTokensQtyLifetime = 86400;
|
||||
|
||||
|
||||
//services
|
||||
private $redis;
|
||||
|
||||
private $client_service;
|
||||
private $lock_manager_service;
|
||||
private $configuration_service;
|
||||
private $cache_service;
|
||||
|
||||
public function __construct(IClientService $client_service, ILockManagerService $lock_manager_service, IServerConfigurationService $configuration_service)
|
||||
public function __construct(IClientService $client_service, ILockManagerService $lock_manager_service, IServerConfigurationService $configuration_service, ICacheService $cache_service)
|
||||
{
|
||||
$this->redis = \RedisLV4::connection();
|
||||
$this->client_service = $client_service;
|
||||
$this->lock_manager_service = $lock_manager_service;
|
||||
$this->configuration_service = $configuration_service;
|
||||
$this->cache_service = $cache_service;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -76,34 +76,25 @@ class TokenService implements ITokenService
|
|||
public function createAuthorizationCode($client_id, $scope, $audience = '', $redirect_uri = null)
|
||||
{
|
||||
//create model
|
||||
$code = AuthorizationCode::create($client_id, $scope, $audience, $redirect_uri, $this->configuration_service->getConfigValue('OAuth2.AuthorizationCode.Lifetime'));
|
||||
|
||||
$value = $code->getValue();
|
||||
$code = AuthorizationCode::create($client_id, $scope, $audience, $redirect_uri, $this->configuration_service->getConfigValue('OAuth2.AuthorizationCode.Lifetime'));
|
||||
$value = $code->getValue();
|
||||
$hashed_value = Hash::compute('sha256', $value);
|
||||
//stores in REDIS
|
||||
$this->redis->hmset($hashed_value, array(
|
||||
'value' => $hashed_value,
|
||||
//stores on cache
|
||||
$this->cache_service->storeHash($hashed_value,
|
||||
array(
|
||||
'client_id' => $code->getClientId(),
|
||||
'scope' => $code->getScope(),
|
||||
'audience' => $code->getAudience(),
|
||||
'redirect_uri' => $code->getRedirectUri(),
|
||||
'issued' => $code->getIssued(),
|
||||
'lifetime' => $code->getLifetime(),
|
||||
'audience' => $code->getAudience()
|
||||
));
|
||||
//sets expiration time
|
||||
$this->redis->expire($hashed_value, $code->getLifetime());
|
||||
'from_ip' => $code->getFromIp()
|
||||
), $code->getLifetime());
|
||||
|
||||
//stores brand new auth code hash value on a set by client id...
|
||||
$this->redis->sadd($client_id . self::ClientAuthCodePrefixList, $hashed_value);
|
||||
|
||||
if($this->redis->setnx($client_id . self::ClientAuthCodeQty,1)){
|
||||
$this->redis->expire($client_id . self::ClientAuthCodeQty, self::ClientAuthCodeQtyLifetime);
|
||||
}
|
||||
else{
|
||||
$this->redis->incr($client_id . self::ClientAuthCodeQty);
|
||||
}
|
||||
|
||||
$this->cache_service->addMemberSet($client_id . self::ClientAuthCodePrefixList, $hashed_value);
|
||||
|
||||
$this->cache_service->incCounter($client_id . self::ClientAuthCodeQty,self::ClientAuthCodeQtyLifetime);
|
||||
return $code;
|
||||
}
|
||||
|
||||
|
@ -118,24 +109,23 @@ class TokenService implements ITokenService
|
|||
|
||||
$hashed_value = Hash::compute('sha256', $value);
|
||||
|
||||
if (!$this->redis->exists($hashed_value))
|
||||
if (!$this->cache_service->exists($hashed_value))
|
||||
throw new InvalidAuthorizationCodeException(sprintf("auth_code %s ", $value));
|
||||
|
||||
try {
|
||||
|
||||
$this->lock_manager_service->acquireLock('lock.get.authcode.' . $hashed_value);
|
||||
|
||||
$values = $this->redis->hmget($hashed_value, array(
|
||||
'value',
|
||||
'client_id',
|
||||
'scope',
|
||||
'redirect_uri',
|
||||
'issued',
|
||||
'lifetime',
|
||||
'audience'
|
||||
));
|
||||
$cache_values = $this->cache_service->getHash($hashed_value, array('client_id','scope','audience','redirect_uri','issued','lifetime','from_ip'));
|
||||
|
||||
$code = AuthorizationCode::load($value,
|
||||
$cache_values['client_id'],
|
||||
$cache_values['scope'],
|
||||
$cache_values['audience'],
|
||||
$cache_values['redirect_uri'],
|
||||
$cache_values['issued'],
|
||||
$cache_values['lifetime'],
|
||||
$cache_values['from_ip']);
|
||||
|
||||
$code = AuthorizationCode::load($values[0], $values[1], $values[2], $values[6], $values[3], $values[4], $values[5]);
|
||||
return $code;
|
||||
} catch (UnacquiredLockException $ex1) {
|
||||
throw new ReplayAttackException($value, sprintf("auth_code %s ", $value));
|
||||
|
@ -153,22 +143,23 @@ class TokenService implements ITokenService
|
|||
$access_token = AccessToken::create($auth_code, $this->configuration_service->getConfigValue('OAuth2.AccessToken.Lifetime'));
|
||||
|
||||
DB::transaction(function () use ($auth_code, $redirect_uri, &$access_token) {
|
||||
|
||||
$value = $access_token->getValue();
|
||||
$hashed_value = Hash::compute('sha256', $value);
|
||||
|
||||
$client_id = $access_token->getClientId();
|
||||
$client = $this->client_service->getClientById($client_id);
|
||||
$client_id = $access_token->getClientId();
|
||||
$client = $this->client_service->getClientById($client_id);
|
||||
|
||||
$access_token_db = new DBAccessToken (
|
||||
array(
|
||||
'value' => $hashed_value,
|
||||
'from_ip' => IPHelper::getUserIp(),
|
||||
'associated_authorization_code' => Hash::compute('sha256', $access_token->getAuthCode()),
|
||||
'associated_authorization_code' => Hash::compute('sha256', $auth_code->getValue()),
|
||||
'lifetime' => $access_token->getLifetime(),
|
||||
'scope' => $access_token->getScope(),
|
||||
'audience' => $access_token->getAudience()
|
||||
)
|
||||
);
|
||||
|
||||
$access_token_db->client()->associate($client);
|
||||
$access_token_db->save();
|
||||
//check if use refresh tokens...
|
||||
|
@ -176,20 +167,13 @@ class TokenService implements ITokenService
|
|||
$this->createRefreshToken($access_token);
|
||||
}
|
||||
|
||||
$this->storesAccessTokenOnRedis($access_token);
|
||||
$this->storesAccessTokenOnCache($access_token);
|
||||
|
||||
//stores brand new access token hash value on a set by client id...
|
||||
$this->redis->sadd($client_id . self::ClientAccessTokenPrefixList, $hashed_value);
|
||||
|
||||
if($this->redis->setnx($client_id . self::ClientAccessTokensQty,1)){
|
||||
$this->redis->expire($client_id . self::ClientAccessTokensQty, self::ClientAccessTokensQtyLifetime);
|
||||
}
|
||||
else{
|
||||
$this->redis->incr($client_id . self::ClientAccessTokensQty);
|
||||
}
|
||||
$this->cache_service->addMemberSet($client_id . self::ClientAccessTokenPrefixList, $hashed_value);
|
||||
|
||||
$this->cache_service->incCounter($client_id . self::ClientAccessTokensQty,self::ClientAccessTokensQtyLifetime);
|
||||
});
|
||||
|
||||
return $access_token;
|
||||
}
|
||||
|
||||
|
@ -199,7 +183,7 @@ class TokenService implements ITokenService
|
|||
$value = $access_token->getValue();
|
||||
$hashed_value = Hash::compute('sha256', $value);
|
||||
|
||||
$this->storesAccessTokenOnRedis($access_token);
|
||||
$this->storesAccessTokenOnCache($access_token);
|
||||
|
||||
$client_id = $access_token->getClientId();
|
||||
$client = $this->client_service->getClientById($client_id);
|
||||
|
@ -218,17 +202,10 @@ class TokenService implements ITokenService
|
|||
$access_token_db->client()->associate($client);
|
||||
$access_token_db->Save();
|
||||
|
||||
|
||||
|
||||
//stores brand new access token hash value on a set by client id...
|
||||
$this->redis->sadd($client_id . self::ClientAccessTokenPrefixList, $hashed_value);
|
||||
$this->cache_service->addMemberSet($client_id . self::ClientAccessTokenPrefixList, $hashed_value);
|
||||
|
||||
if($this->redis->setnx($client_id . self::ClientAccessTokensQty,1)){
|
||||
$this->redis->expire($client_id . self::ClientAccessTokensQty, self::ClientAccessTokensQtyLifetime);
|
||||
}
|
||||
else{
|
||||
$this->redis->incr($client_id . self::ClientAccessTokensQty);
|
||||
}
|
||||
$this->cache_service->incCounter($client_id . self::ClientAccessTokensQty,self::ClientAccessTokensQtyLifetime);
|
||||
|
||||
return $access_token;
|
||||
}
|
||||
|
@ -270,7 +247,7 @@ class TokenService implements ITokenService
|
|||
$value = $access_token->getValue();
|
||||
$hashed_value = Hash::compute('sha256', $value);
|
||||
|
||||
$this->storesAccessTokenOnRedis($access_token);
|
||||
$this->storesAccessTokenOnCache($access_token);
|
||||
|
||||
//get current client
|
||||
$client_id = $access_token->getClientId();
|
||||
|
@ -294,14 +271,9 @@ class TokenService implements ITokenService
|
|||
$access_token_db->Save();
|
||||
|
||||
//stores brand new access token hash value on a set by client id...
|
||||
$this->redis->sadd($client_id . self::ClientAccessTokenPrefixList, $hashed_value);
|
||||
$this->cache_service->addMemberSet($client_id . self::ClientAccessTokenPrefixList, $hashed_value);
|
||||
|
||||
if($this->redis->setnx($client_id . self::ClientAccessTokensQty,1)){
|
||||
$this->redis->expire($client_id . self::ClientAccessTokensQty, self::ClientAccessTokensQtyLifetime);
|
||||
}
|
||||
else{
|
||||
$this->redis->incr($client_id . self::ClientAccessTokensQty);
|
||||
}
|
||||
$this->cache_service->incCounter($client_id . self::ClientAccessTokensQty,self::ClientAccessTokensQtyLifetime);
|
||||
});
|
||||
return $access_token;
|
||||
}
|
||||
|
@ -310,51 +282,49 @@ class TokenService implements ITokenService
|
|||
* @param AccessToken $access_token
|
||||
* @throws \oauth2\exceptions\InvalidAccessTokenException
|
||||
*/
|
||||
private function storesAccessTokenOnRedis(AccessToken $access_token)
|
||||
private function storesAccessTokenOnCache(AccessToken $access_token)
|
||||
{
|
||||
//stores in REDIS
|
||||
|
||||
$value = $access_token->getValue();
|
||||
$value = $access_token->getValue();
|
||||
$hashed_value = Hash::compute('sha256', $value);
|
||||
|
||||
if ($this->redis->exists($hashed_value))
|
||||
if ($this->cache_service->exists($hashed_value))
|
||||
throw new InvalidAccessTokenException;
|
||||
|
||||
$auth_code = !is_null($access_token->getAuthCode()) ? Hash::compute('sha256', $access_token->getAuthCode()):'';
|
||||
$refresh_token_value = !is_null($access_token->getRefreshToken()) ? Hash::compute('sha256', $access_token->getRefreshToken()->getValue()):'';
|
||||
|
||||
$this->redis->hmset($hashed_value, array(
|
||||
'value' => $hashed_value,
|
||||
$this->cache_service->storeHash($hashed_value, array(
|
||||
'client_id' => $access_token->getClientId(),
|
||||
'scope' => $access_token->getScope(),
|
||||
'auth_code' => Hash::compute('sha256', $access_token->getAuthCode()),
|
||||
'auth_code' => $auth_code,
|
||||
'issued' => $access_token->getIssued(),
|
||||
'lifetime' => $access_token->getLifetime(),
|
||||
'audience' => $access_token->getAudience(),
|
||||
'from_ip' => IPHelper::getUserIp(),
|
||||
'refresh_token' => $refresh_token_value
|
||||
'refresh_token' => $refresh_token_value,
|
||||
$access_token->getLifetime()
|
||||
));
|
||||
|
||||
$this->redis->expire($hashed_value, $access_token->getLifetime());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param DBAccessToken $access_token
|
||||
* @throws \oauth2\exceptions\InvalidAccessTokenException
|
||||
*/
|
||||
private function storesDBAccessTokenOnRedis(DBAccessToken $access_token)
|
||||
private function storesDBAccessTokenOnCache(DBAccessToken $access_token)
|
||||
{
|
||||
//stores in REDIS
|
||||
//stores in Cache
|
||||
|
||||
if ($this->redis->exists($access_token->value))
|
||||
if ($this->cache_service->exists($access_token->value))
|
||||
throw new InvalidAccessTokenException;
|
||||
|
||||
$refresh_token_value = '';
|
||||
$refresh_token_db = $access_token->refresh_token()->first();
|
||||
$refresh_token_db = $access_token->refresh_token()->first();
|
||||
if(!is_null($refresh_token_db))
|
||||
$refresh_token_value = $refresh_token_db->value;
|
||||
|
||||
$this->redis->hmset($access_token->value, array(
|
||||
'value' => $access_token->value,
|
||||
$this->cache_service->storeHash($access_token->value, array(
|
||||
'client_id' => $access_token->client_id,
|
||||
'scope' => $access_token->scope,
|
||||
'auth_code' => $access_token->associated_authorization_code,
|
||||
|
@ -363,9 +333,9 @@ class TokenService implements ITokenService
|
|||
'from_ip' => $access_token->from_ip,
|
||||
'audience' => $access_token->audience,
|
||||
'refresh_token' => $refresh_token_value
|
||||
));
|
||||
)
|
||||
,$access_token->lifetime);
|
||||
|
||||
$this->redis->expire($access_token->value, $access_token->lifetime);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -380,7 +350,7 @@ class TokenService implements ITokenService
|
|||
$hashed_value = Hash::compute('sha256', $value);
|
||||
|
||||
try {
|
||||
if (!$this->redis->exists($hashed_value)) {
|
||||
if (!$this->cache_service->exists($hashed_value)) {
|
||||
//check on DB...
|
||||
$access_token_db = DBAccessToken::where('value', '=', $hashed_value)->first();
|
||||
if (is_null($access_token_db))
|
||||
|
@ -399,14 +369,13 @@ class TokenService implements ITokenService
|
|||
$access_token_db->delete();
|
||||
throw new InvalidGrantTypeException(sprintf('Access token %s is expired!', $value));
|
||||
}
|
||||
//reload on redis
|
||||
$this->storesDBAccessTokenOnRedis($access_token_db);
|
||||
//reload on cache
|
||||
$this->storesDBAccessTokenOnCache($access_token_db);
|
||||
//release lock
|
||||
$this->lock_manager_service->releaseLock($lock_name);
|
||||
}
|
||||
|
||||
$values = $this->redis->hmget($hashed_value, array(
|
||||
'value',
|
||||
$cache_values = $this->cache_service->getHash($hashed_value, array(
|
||||
'client_id',
|
||||
'scope',
|
||||
'auth_code',
|
||||
|
@ -417,9 +386,21 @@ class TokenService implements ITokenService
|
|||
'refresh_token'
|
||||
));
|
||||
|
||||
$code = AuthorizationCode::load($values[3], $values[1], $values[2], $values[7]);
|
||||
$access_token = AccessToken::load($values[0], $code, $values[4], $values[5], $values[6], $values[7]);
|
||||
$refresh_token_value = $values[8];
|
||||
// reload auth code ...
|
||||
$auth_code = AuthorizationCode::load(
|
||||
$cache_values['auth_code'],
|
||||
$cache_values['client_id'],
|
||||
$cache_values['scope'],
|
||||
$cache_values['audience'],
|
||||
null,
|
||||
null,
|
||||
$this->configuration_service->getConfigValue('OAuth2.AuthorizationCode.Lifetime'),
|
||||
$cache_values['from_ip'],
|
||||
true
|
||||
);
|
||||
// reload access token ...
|
||||
$access_token = AccessToken::load($value, $auth_code, $cache_values['issued'],$cache_values['lifetime']);
|
||||
$refresh_token_value = $cache_values['refresh_token'];
|
||||
|
||||
if(!empty($refresh_token_value)){
|
||||
$refresh_token = $this->getRefreshToken($refresh_token_value,true);
|
||||
|
@ -459,38 +440,35 @@ class TokenService implements ITokenService
|
|||
public function createRefreshToken(AccessToken &$access_token)
|
||||
{
|
||||
$refresh_token = RefreshToken::create($access_token, $this->configuration_service->getConfigValue('OAuth2.RefreshToken.Lifetime'));
|
||||
$value = $refresh_token->getValue();
|
||||
//hash the given value, bc tokens values are stored hashed on DB
|
||||
$hashed_value = Hash::compute('sha256', $value);
|
||||
|
||||
$client_id = $refresh_token->getClientId();
|
||||
$client = $this->client_service->getClientById($client_id);
|
||||
//stores in DB
|
||||
$refresh_token_db = new DBRefreshToken (
|
||||
array(
|
||||
'value' => $hashed_value,
|
||||
'lifetime' => $refresh_token->getLifetime(),
|
||||
'scope' => $refresh_token->getScope(),
|
||||
'from_ip' => IPHelper::getUserIp(),
|
||||
'audience' => $access_token->getAudience(),
|
||||
)
|
||||
);
|
||||
DB::transaction(function () use (&$refresh_token, &$access_token) {
|
||||
$value = $refresh_token->getValue();
|
||||
//hash the given value, bc tokens values are stored hashed on DB
|
||||
$hashed_value = Hash::compute('sha256', $value);
|
||||
$client_id = $refresh_token->getClientId();
|
||||
$client = $this->client_service->getClientById($client_id);
|
||||
//stores in DB
|
||||
$refresh_token_db = new DBRefreshToken (
|
||||
array(
|
||||
'value' => $hashed_value,
|
||||
'lifetime' => $refresh_token->getLifetime(),
|
||||
'scope' => $refresh_token->getScope(),
|
||||
'from_ip' => IPHelper::getUserIp(),
|
||||
'audience' => $access_token->getAudience(),
|
||||
)
|
||||
);
|
||||
|
||||
$refresh_token_db->client()->associate($client);
|
||||
$refresh_token_db->Save();
|
||||
//associate current access token to refresh token on DB
|
||||
$access_token_db = DBAccessToken::where('value','=',Hash::compute('sha256',$access_token->getValue()))->first();
|
||||
$access_token_db->refresh_token()->associate($refresh_token_db);
|
||||
$access_token_db->Save();
|
||||
$refresh_token_db->client()->associate($client);
|
||||
$refresh_token_db->Save();
|
||||
//associate current access token to refresh token on DB
|
||||
$access_token_db = DBAccessToken::where('value','=',Hash::compute('sha256',$access_token->getValue()))->first();
|
||||
$access_token_db->refresh_token()->associate($refresh_token_db);
|
||||
$access_token_db->Save();
|
||||
|
||||
$access_token->setRefreshToken($refresh_token);
|
||||
$access_token->setRefreshToken($refresh_token);
|
||||
|
||||
if($this->redis->setnx($client_id . self::ClientRefreshTokensQty,1)){
|
||||
$this->redis->expire($client_id . self::ClientRefreshTokensQty, self::ClientRefreshTokensQtyLifetime);
|
||||
}
|
||||
else{
|
||||
$this->redis->incr($client_id . self::ClientRefreshTokensQty);
|
||||
}
|
||||
$this->cache_service->incCounter($client_id . self::ClientRefreshTokensQty,self::ClientRefreshTokensQtyLifetime);
|
||||
});
|
||||
|
||||
return $refresh_token;
|
||||
}
|
||||
|
@ -535,7 +513,8 @@ class TokenService implements ITokenService
|
|||
'client_id' => $client->client_id,
|
||||
'audience' => $refresh_token_db->audience,
|
||||
'from_ip' => $refresh_token_db->from_ip,
|
||||
'issued' => $refresh_token_db->created_at
|
||||
'issued' => $refresh_token_db->created_at,
|
||||
'is_hashed' => $is_hashed
|
||||
), $refresh_token_db->lifetime);
|
||||
|
||||
return $refresh_token;
|
||||
|
@ -551,13 +530,23 @@ class TokenService implements ITokenService
|
|||
$auth_code_hashed_value = Hash::compute('sha256', $auth_code);
|
||||
|
||||
DB::transaction(function () use ($auth_code_hashed_value) {
|
||||
//get related access tokens
|
||||
$db_access_tokens = DBAccessToken::where('associated_authorization_code', '=', $auth_code_hashed_value)->get();
|
||||
|
||||
foreach ($db_access_tokens as $db_access_token) {
|
||||
|
||||
$client = $db_access_tokens->client()->first();
|
||||
$access_token_value = $db_access_token->value;
|
||||
$refresh_token_db = $db_access_token->refresh_token()->first();
|
||||
if(!is_null($refresh_token_db))
|
||||
|
||||
if(!is_null($refresh_token_db)){
|
||||
$refresh_token_db->delete();
|
||||
$this->redis->del($access_token_value);
|
||||
}
|
||||
//remove auth code from client list on cache
|
||||
$this->cache_service->deleteMemberSet($client->client_id . self::ClientAuthCodePrefixList, $auth_code_hashed_value);
|
||||
//remove access token from client list on cache
|
||||
$this->cache_service->deleteMemberSet($client->client_id . self::ClientAccessTokenPrefixList,$access_token_value);
|
||||
$this->cache_service->delete($access_token_value);
|
||||
$db_access_token->delete();
|
||||
}
|
||||
});
|
||||
|
@ -576,13 +565,14 @@ class TokenService implements ITokenService
|
|||
DB::transaction(function () use ($value, $is_hashed, &$res) {
|
||||
//hash the given value, bc tokens values are stored hashed on DB
|
||||
$hashed_value = !$is_hashed?Hash::compute('sha256', $value):$value;
|
||||
//delete from redis
|
||||
if ($this->redis->exists($hashed_value)) {
|
||||
$res = $this->redis->del($hashed_value);
|
||||
}
|
||||
//check on DB... and delete it
|
||||
$res = DBAccessToken::where('value', '=', $hashed_value)->delete();
|
||||
|
||||
$access_token_db = DBAccessToken::where('value', '=', $hashed_value)->first();
|
||||
$client = $access_token_db->client()->first();
|
||||
//delete from cache
|
||||
$res = $this->cache_service->delete($hashed_value);
|
||||
$res = $this->cache_service->deleteMemberSet($client->client_id . self::ClientAccessTokenPrefixList, $access_token_db->value);
|
||||
//check on DB... and delete it
|
||||
$res = $access_token_db->delete();
|
||||
});
|
||||
return $res > 0;
|
||||
}
|
||||
|
@ -594,24 +584,21 @@ class TokenService implements ITokenService
|
|||
public function revokeClientRelatedTokens($client_id)
|
||||
{
|
||||
//get client auth codes
|
||||
$auth_codes = $this->redis->smembers($client_id . self::ClientAuthCodePrefixList);
|
||||
$auth_codes = $this->cache_service->getSet($client_id . self::ClientAuthCodePrefixList);
|
||||
//get client access tokens
|
||||
$access_tokens = $this->redis->smembers($client_id . self::ClientAccessTokenPrefixList);
|
||||
$access_tokens = $this->cache_service->getSet($client_id . self::ClientAccessTokenPrefixList);
|
||||
|
||||
DB::transaction(function () use ($client_id, $auth_codes, $access_tokens) {
|
||||
|
||||
if(count($auth_codes)>0)
|
||||
$this->redis->del($auth_codes);
|
||||
|
||||
if(count($access_tokens)>0)
|
||||
$this->redis->del($access_tokens);
|
||||
$this->cache_service->deleteArray($auth_codes);
|
||||
$this->cache_service->deleteArray($access_tokens);
|
||||
|
||||
DBAccessToken::where('client_id','=',$client_id)->delete();
|
||||
DBRefreshToken::where('client_id','=',$client_id)->delete();
|
||||
|
||||
//delete client list (auth codes and access tokens)
|
||||
$this->redis->del($client_id . self::ClientAuthCodePrefixList);
|
||||
$this->redis->del($client_id . self::ClientAccessTokenPrefixList);
|
||||
$this->cache_service->delete($client_id . self::ClientAuthCodePrefixList);
|
||||
$this->cache_service->delete($client_id . self::ClientAccessTokenPrefixList);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -620,8 +607,7 @@ class TokenService implements ITokenService
|
|||
* Mark a given refresh token as void
|
||||
* @param $value
|
||||
* @param bool $is_hashed
|
||||
* @param bool $revoke_related_access_token
|
||||
* @return mixed
|
||||
* @return bool
|
||||
*/
|
||||
public function invalidateRefreshToken($value, $is_hashed = false)
|
||||
{
|
||||
|
@ -661,9 +647,9 @@ class TokenService implements ITokenService
|
|||
if(!is_null($refresh_token_db)){
|
||||
$access_tokens_db = DBAccessToken::where('refresh_token_id','=',$refresh_token_db->id)->get();
|
||||
foreach($access_tokens_db as $access_token_db){
|
||||
$res = $this->redis->del(array($access_token_db->value));
|
||||
$res = $this->cache_service->delete($access_token_db->value);
|
||||
$client = $access_token_db->client()->first();
|
||||
$res = $this->redis->srem($client->client_id . self::ClientAccessTokenPrefixList, $access_token_db->value);
|
||||
$res = $this->cache_service->deleteMemberSet($client->client_id . self::ClientAccessTokenPrefixList, $access_token_db->value);
|
||||
$access_token_db->delete();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,94 +2,102 @@
|
|||
|
||||
namespace services;
|
||||
|
||||
use DateInterval;
|
||||
use DateTime;
|
||||
use Log;
|
||||
use openid\exceptions\OpenIdInvalidRealmException;
|
||||
use openid\exceptions\ReplayAttackException;
|
||||
use openid\exceptions\InvalidAssociation;
|
||||
|
||||
use openid\helpers\OpenIdErrorMessages;
|
||||
use openid\model\IAssociation;
|
||||
use openid\services\IAssociationService;
|
||||
use OpenIdAssociation;
|
||||
use utils\exceptions\UnacquiredLockException;
|
||||
use utils\services\ILockManagerService;
|
||||
|
||||
use utils\services\ICacheService;
|
||||
/**
|
||||
* Class AssociationService
|
||||
* @package services
|
||||
*/
|
||||
class AssociationService implements IAssociationService
|
||||
{
|
||||
|
||||
private $redis;
|
||||
private $lock_manager_service;
|
||||
private $cache_service;
|
||||
|
||||
public function __construct(ILockManagerService $lock_manager_service)
|
||||
public function __construct(ILockManagerService $lock_manager_service, ICacheService $cache_service)
|
||||
{
|
||||
$this->redis = \RedisLV4::connection();
|
||||
$this->lock_manager_service = $lock_manager_service;
|
||||
$this->cache_service = $cache_service;
|
||||
}
|
||||
|
||||
/**
|
||||
* gets a given association by handle, and if association exists and its type is private, then lock it
|
||||
* to prevent subsequent usage ( private association could be used once)
|
||||
* @param $handle
|
||||
* @param null $realm
|
||||
* @return null|IAssociation
|
||||
* @return null|IAssociation|OpenIdAssociation
|
||||
* @throws \openid\exceptions\ReplayAttackException
|
||||
* @throws \openid\exceptions\InvalidAssociation
|
||||
* @throws \openid\exceptions\OpenIdInvalidRealmException
|
||||
*/
|
||||
public function getAssociation($handle, $realm = null)
|
||||
{
|
||||
//todo: refactor this code !!!
|
||||
|
||||
$lock_name = 'lock.get.assoc.' . $handle;
|
||||
|
||||
try {
|
||||
// check if association is on redis cache
|
||||
if ($this->redis->exists($handle)) {
|
||||
|
||||
//get hash from redis
|
||||
$values = $this->redis->hmget($handle, array(
|
||||
"type",
|
||||
"mac_function",
|
||||
"issued",
|
||||
"lifetime",
|
||||
"secret",
|
||||
"realm"));
|
||||
|
||||
if ($values[0] == IAssociation::TypePrivate) {
|
||||
// only one time we could use this handle
|
||||
$this->lock_manager_service->acquireLock($lock_name);
|
||||
if (is_null($realm) || empty($realm) || $values[5] != $realm) {
|
||||
throw new OpenIdInvalidRealmException(sprintf(OpenIdErrorMessages::InvalidPrivateAssociationMessage, $handle, $realm));
|
||||
}
|
||||
}
|
||||
|
||||
$assoc = new OpenIdAssociation();
|
||||
$assoc->type = $values[0];
|
||||
$assoc->mac_function = $values[1];
|
||||
$assoc->issued = $values[2];
|
||||
$assoc->lifetime = $values[3];
|
||||
$assoc->secret = \hex2bin($values[4]);
|
||||
$realm = $values[5];
|
||||
if (!empty($realm))
|
||||
$assoc->realm = $realm;
|
||||
return $assoc;
|
||||
}
|
||||
// if not , check on db
|
||||
$assoc = OpenIdAssociation::where('identifier', '=', $handle)->first();
|
||||
|
||||
if (!is_null($assoc)) {
|
||||
$issued_date = new DateTime($assoc->issued);
|
||||
if ($assoc->type == IAssociation::TypePrivate) {
|
||||
// only one time we could use this handle
|
||||
$this->lock_manager_service->acquireLock($lock_name);
|
||||
if (is_null($realm) || empty($realm) || $assoc->realm != $realm) {
|
||||
throw new OpenIdInvalidRealmException(sprintf(OpenIdErrorMessages::InvalidPrivateAssociationMessage, $handle, $realm));
|
||||
}
|
||||
}
|
||||
$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) {
|
||||
// check if association is on cache
|
||||
if (!$this->cache_service->exists($handle)) {
|
||||
// if not , check on db
|
||||
$assoc = OpenIdAssociation::where('identifier', '=', $handle)->first();
|
||||
if(is_null($assoc))
|
||||
throw new InvalidAssociation(sprintf('openid association %s does not exists!',$handle));
|
||||
//check association lifetime ...
|
||||
$remaining_lifetime = $assoc->getRemainingLifetime();
|
||||
if ($remaining_lifetime < 0) {
|
||||
$this->deleteAssociation($handle);
|
||||
$assoc = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
//repopulate cache
|
||||
$this->cache_service->storeHash($handle, array(
|
||||
"type" => $assoc->type,
|
||||
"mac_function" => $assoc->mac_function,
|
||||
"issued" => $assoc->issued,
|
||||
"lifetime" => $assoc->lifetime,
|
||||
"secret" => \bin2hex($assoc->secret),
|
||||
"realm" => $assoc->realm),
|
||||
$remaining_lifetime);
|
||||
}
|
||||
|
||||
//get hash from cache
|
||||
$cache_values = $this->cache_service->getHash($handle, array(
|
||||
"type",
|
||||
"mac_function",
|
||||
"issued",
|
||||
"lifetime",
|
||||
"secret",
|
||||
"realm"));
|
||||
|
||||
if ($cache_values['type'] == IAssociation::TypePrivate) {
|
||||
if (is_null($realm) || empty($realm) || $cache_values['realm'] != $realm) {
|
||||
throw new OpenIdInvalidRealmException(sprintf(OpenIdErrorMessages::InvalidPrivateAssociationMessage, $handle, $realm));
|
||||
}
|
||||
// only one time we could use this handle
|
||||
$this->lock_manager_service->acquireLock($lock_name);
|
||||
}
|
||||
|
||||
$assoc = new OpenIdAssociation();
|
||||
$assoc->type = $cache_values['type'];
|
||||
$assoc->mac_function = $cache_values['mac_function'];
|
||||
$assoc->issued = $cache_values['issued'];
|
||||
$assoc->lifetime = $cache_values['lifetime'];
|
||||
$assoc->secret = \hex2bin($cache_values['secret']);
|
||||
$realm = $cache_values['realm'];
|
||||
if (!empty($realm))
|
||||
$assoc->realm = $realm;
|
||||
return $assoc;
|
||||
|
||||
} catch (UnacquiredLockException $ex1) {
|
||||
throw new ReplayAttackException(sprintf(OpenIdErrorMessages::ReplayAttackPrivateAssociationAlreadyUsed, $handle));
|
||||
}
|
||||
|
@ -101,7 +109,7 @@ class AssociationService implements IAssociationService
|
|||
*/
|
||||
public function deleteAssociation($handle)
|
||||
{
|
||||
$this->redis->del($handle);
|
||||
$this->cache_service->delete($handle);
|
||||
$assoc = OpenIdAssociation::where('identifier', '=', $handle)->first();
|
||||
if (!is_null($assoc)) {
|
||||
$assoc->delete();
|
||||
|
@ -111,44 +119,53 @@ class AssociationService implements IAssociationService
|
|||
}
|
||||
|
||||
/**
|
||||
* @param IAssociation $association
|
||||
* @return bool
|
||||
* @param $handle
|
||||
* @param $secret
|
||||
* @param $mac_function
|
||||
* @param $lifetime
|
||||
* @param $issued
|
||||
* @param $type
|
||||
* @param null $realm
|
||||
* @return IAssociation
|
||||
* @throws \openid\exceptions\ReplayAttackException
|
||||
*/
|
||||
public function addAssociation($handle, $secret, $mac_function, $lifetime, $issued, $type, $realm = null)
|
||||
{
|
||||
|
||||
$assoc = new OpenIdAssociation();
|
||||
try {
|
||||
$lock_name = 'lock.add.assoc.' . $handle;
|
||||
$this->lock_manager_service->acquireLock($lock_name);
|
||||
|
||||
$assoc = new OpenIdAssociation();
|
||||
$assoc->identifier = $handle;
|
||||
$assoc->secret = $secret;
|
||||
$assoc->type = $type;
|
||||
$assoc->mac_function = $mac_function;
|
||||
$assoc->lifetime = $lifetime;
|
||||
$assoc->issued = $issued;
|
||||
|
||||
if (!is_null($realm))
|
||||
$assoc->realm = $realm;
|
||||
|
||||
if ($type == IAssociation::TypeSession) {
|
||||
$assoc->identifier = $handle;
|
||||
$assoc->secret = $secret;
|
||||
$assoc->type = $type;
|
||||
$assoc->mac_function = $mac_function;
|
||||
$assoc->lifetime = $lifetime;
|
||||
$assoc->issued = $issued;
|
||||
if (!is_null($realm))
|
||||
$assoc->realm = $realm;
|
||||
$assoc->Save();
|
||||
}
|
||||
|
||||
if (is_null($realm))
|
||||
$realm = '';
|
||||
|
||||
$this->redis->hmset($handle, array(
|
||||
"type" => $type,
|
||||
$this->cache_service->storeHash($handle, array(
|
||||
"type" => $type,
|
||||
"mac_function" => $mac_function,
|
||||
"issued" => $issued,
|
||||
"lifetime" => $lifetime,
|
||||
"secret" => \bin2hex($secret),
|
||||
"realm" => $realm));
|
||||
"issued" => $issued,
|
||||
"lifetime" => $lifetime,
|
||||
"secret" => \bin2hex($secret),
|
||||
"realm" => $realm),$lifetime);
|
||||
|
||||
|
||||
$this->redis->expire($handle, $lifetime);
|
||||
} catch (UnacquiredLockException $ex1) {
|
||||
throw new ReplayAttackException(sprintf(OpenIdErrorMessages::ReplayAttackPrivateAssociationAlreadyUsed, $handle));
|
||||
}
|
||||
return $assoc;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -64,13 +64,15 @@ class MementoRequestService implements IMementoOpenIdRequestService
|
|||
|
||||
public function clearCurrentRequest()
|
||||
{
|
||||
$old_data = Input::old();
|
||||
$old_data = Input::old();
|
||||
$openid_params = array();
|
||||
|
||||
foreach ($old_data as $key => $value) {
|
||||
if (stristr($key, "openid") !== false) {
|
||||
array_push($openid_params, $key);
|
||||
}
|
||||
}
|
||||
|
||||
if (count($openid_params) > 0) {
|
||||
foreach ($openid_params as $open_id_param) {
|
||||
Session::forget($open_id_param);
|
||||
|
|
|
@ -10,17 +10,19 @@ use openid\model\OpenIdNonce;
|
|||
use openid\services\INonceService;
|
||||
use utils\exceptions\UnacquiredLockException;
|
||||
use utils\services\ILockManagerService;
|
||||
|
||||
use utils\services\ICacheService;
|
||||
|
||||
class NonceService implements INonceService
|
||||
{
|
||||
|
||||
private $redis;
|
||||
|
||||
public function __construct(ILockManagerService $lock_manager_service)
|
||||
private $cache_service;
|
||||
private $lock_manager_service;
|
||||
|
||||
public function __construct(ILockManagerService $lock_manager_service,ICacheService $cache_service)
|
||||
{
|
||||
$this->redis = \RedisLV4::connection();
|
||||
$this->lock_manager_service = $lock_manager_service;
|
||||
$this->cache_service = $cache_service;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -67,15 +69,15 @@ class NonceService implements INonceService
|
|||
$key = $raw_nonce . $signature;
|
||||
|
||||
try {
|
||||
if ($this->redis->exists($key) == 0)
|
||||
throw new ReplayAttackException(sprintf(OpenIdErrorMessages::ReplayAttackNonceAlreadyUsed, $nonce));
|
||||
$old_realm = $this->redis->get($key);
|
||||
if (!$this->cache_service->exists($key))
|
||||
throw new ReplayAttackException(sprintf(OpenIdErrorMessages::ReplayAttackNonceAlreadyUsed, $nonce->getRawFormat()));
|
||||
$old_realm = $this->cache_service->getSingleValue($key);
|
||||
if ($realm != $old_realm) {
|
||||
throw new ReplayAttackException(sprintf(OpenIdErrorMessages::ReplayAttackNonceAlreadyEmittedForAnotherRealm, $realm));
|
||||
}
|
||||
$this->redis->del($key);
|
||||
$this->cache_service->delete($key);
|
||||
} catch (ReplayAttackException $ex) {
|
||||
$this->redis->del($key);
|
||||
$this->cache_service->delete($key);
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
@ -90,7 +92,7 @@ class NonceService implements INonceService
|
|||
try {
|
||||
$raw_nonce = $nonce->getRawFormat();
|
||||
$lifetime = \ServerConfigurationService::getConfigValue("Nonce.Lifetime");
|
||||
$this->redis->setex($raw_nonce . $signature, $lifetime, $realm);
|
||||
$this->cache_service->setSingleValue($raw_nonce . $signature, $realm, $lifetime );
|
||||
} catch (Exception $ex) {
|
||||
Log::error($ex);
|
||||
}
|
||||
|
|
|
@ -8,29 +8,30 @@ use openid\services\ITrustedSitesService;
|
|||
use OpenIdTrustedSite;
|
||||
use utils\services\IAuthService;
|
||||
use utils\services\ILogService;
|
||||
use Exception;
|
||||
|
||||
class TrustedSitesService implements ITrustedSitesService
|
||||
{
|
||||
private $log;
|
||||
private $log_service;
|
||||
|
||||
public function __construct(ILogService $log)
|
||||
public function __construct(ILogService $log_service)
|
||||
{
|
||||
$this->log = $log;
|
||||
$this->log_service = $log_service;
|
||||
}
|
||||
|
||||
public function addTrustedSite(IOpenIdUser $user, $realm, $policy, $data = array())
|
||||
{
|
||||
$res = false;
|
||||
try {
|
||||
$site = new OpenIdTrustedSite;
|
||||
$site->realm = $realm;
|
||||
$site->policy = $policy;
|
||||
$site = new OpenIdTrustedSite;
|
||||
$site->realm = $realm;
|
||||
$site->policy = $policy;
|
||||
$site->user_id = $user->getId();
|
||||
$site->data = json_encode($data);
|
||||
$site->data = json_encode($data);
|
||||
$site->Save();
|
||||
$res = true;
|
||||
} catch (\Exception $ex) {
|
||||
$this->log->error($ex);
|
||||
} catch (Exception $ex) {
|
||||
$this->log_service->error($ex);
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
@ -40,8 +41,8 @@ class TrustedSitesService implements ITrustedSitesService
|
|||
try {
|
||||
$site = OpenIdTrustedSite::where("id", "=", $id)->first();
|
||||
if (!is_null($site)) $site->delete();
|
||||
} catch (\Exception $ex) {
|
||||
$this->log->error($ex);
|
||||
} catch (Exception $ex) {
|
||||
$this->log_service->error($ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,8 +73,8 @@ class TrustedSitesService implements ITrustedSitesService
|
|||
}
|
||||
$sites = $query->get();
|
||||
|
||||
} catch (\Exception $ex) {
|
||||
$this->log->error($ex);
|
||||
} catch (Exception $ex) {
|
||||
$this->log_service->error($ex);
|
||||
}
|
||||
|
||||
$res = array();
|
||||
|
@ -136,8 +137,8 @@ class TrustedSitesService implements ITrustedSitesService
|
|||
$sites = null;
|
||||
try {
|
||||
$sites = OpenIdTrustedSite::where("user_id", "=", $user->getId())->get();
|
||||
} catch (\Exception $ex) {
|
||||
$this->log->error($ex);
|
||||
} catch (Exception $ex) {
|
||||
$this->log_service->error($ex);
|
||||
}
|
||||
return $sites;
|
||||
}
|
||||
|
|
|
@ -45,8 +45,7 @@ class OAuth2ConsentStrategy implements IConsentStrategy {
|
|||
$data['redirect_to'] = $request->getRedirectUri();
|
||||
|
||||
$app_logo = $client->getApplicationLogo();
|
||||
if(is_null($app_logo) || empty($app_logo))
|
||||
$app_logo = asset('img/oauth2.default.logo.png');
|
||||
|
||||
$data['app_logo'] = $app_logo;
|
||||
$data['app_description'] = $client->getApplicationDescription();
|
||||
$data['dev_info_email'] = $client->getDeveloperEmail();
|
||||
|
|
|
@ -6,12 +6,12 @@ use openid\OpenIdProtocol;
|
|||
use openid\requests\OpenIdDHAssociationSessionRequest;
|
||||
use Zend\Crypt\PublicKey\DiffieHellman;
|
||||
|
||||
/**
|
||||
* Class DiffieHellmanTest
|
||||
*/
|
||||
class DiffieHellmanTest extends TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function testDefaultDHParams()
|
||||
{
|
||||
$g = OpenIdDHAssociationSessionRequest::DH_G;
|
||||
|
@ -33,44 +33,4 @@ class DiffieHellmanTest extends TestCase
|
|||
$this->assertTrue(strlen($handler) == 32);
|
||||
}
|
||||
|
||||
public function testAssociationMessage()
|
||||
{
|
||||
|
||||
$g = pack('H*', OpenIdDHAssociationSessionRequest::DH_G);
|
||||
$g = OpenIdCryptoHelper::convert($g, DiffieHellman::FORMAT_BINARY, DiffieHellman::FORMAT_NUMBER);
|
||||
$p = pack('H*', OpenIdDHAssociationSessionRequest::DH_P);
|
||||
$p = OpenIdCryptoHelper::convert($p, DiffieHellman::FORMAT_BINARY, DiffieHellman::FORMAT_NUMBER);
|
||||
$dh = new DiffieHellman($p, $g);
|
||||
$dh->generateKeys();
|
||||
|
||||
$rp_public_key = $dh->getPublicKey(DiffieHellman::FORMAT_BTWOC);
|
||||
$dh->computeSecretKey($rp_public_key, DiffieHellman::FORMAT_BTWOC);
|
||||
$rp_public_key = base64_encode($rp_public_key);
|
||||
$shared_secret = $dh->getSharedSecretKey();
|
||||
|
||||
$params = array(
|
||||
"openid.ns" => "http://specs.openid.net/auth/2.0",
|
||||
"openid.assoc_type" => OpenIdProtocol::SignatureAlgorithmHMAC_SHA256,
|
||||
"openid.dh_consumer_public" => $rp_public_key,
|
||||
"openid.mode" => 'associate',
|
||||
"openid.session_type" => OpenIdProtocol::AssociationSessionTypeDHSHA256,
|
||||
);
|
||||
|
||||
|
||||
$response = $this->action("POST", "OpenIdProviderController@op_endpoint", $params);
|
||||
$body = $response->getContent();
|
||||
$lines = explode("\n", $body);
|
||||
$params = array();
|
||||
foreach ($lines as $line) {
|
||||
if (empty($line)) continue;
|
||||
$param = explode(":", $line, 2);
|
||||
$params[$param[0]] = $param[1];
|
||||
}
|
||||
$this->assertResponseStatus(200);
|
||||
$this->assertTrue(isset($params[OpenIdProtocol::OpenIDProtocol_NS]) && $params[OpenIdProtocol::OpenIDProtocol_NS] == OpenIdProtocol::OpenID2MessageType);
|
||||
$this->assertTrue(isset($params[OpenIdProtocol::OpenIDProtocol_AssocType]) && $params[OpenIdProtocol::OpenIDProtocol_AssocType] == OpenIdProtocol::SignatureAlgorithmHMAC_SHA256);
|
||||
$this->assertTrue(isset($params[OpenIdProtocol::OpenIDProtocol_SessionType]) && $params[OpenIdProtocol::OpenIDProtocol_SessionType] == OpenIdProtocol::AssociationSessionTypeDHSHA256);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,11 +1,12 @@
|
|||
<?php
|
||||
|
||||
use auth\OpenIdUser;
|
||||
use auth\User;
|
||||
use oauth2\OAuth2Protocol;
|
||||
use utils\services\IAuthService;
|
||||
|
||||
/**
|
||||
* Class OAuth2ProtocolTest
|
||||
* Test Suite for OAuth2 Protocol
|
||||
*/
|
||||
class OAuth2ProtocolTest extends TestCase
|
||||
{
|
||||
|
@ -34,7 +35,7 @@ class OAuth2ProtocolTest extends TestCase
|
|||
'scope' => sprintf('%s/api/resource-server/read',$this->current_realm),
|
||||
);
|
||||
|
||||
$user = OpenIdUser::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
$user = User::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
|
||||
Auth::login($user);
|
||||
|
||||
|
@ -69,7 +70,7 @@ class OAuth2ProtocolTest extends TestCase
|
|||
'scope' => sprintf('%s/api/resource-server/read',$this->current_realm),
|
||||
);
|
||||
|
||||
$user = OpenIdUser::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
$user = User::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
|
||||
Auth::login($user);
|
||||
|
||||
|
@ -135,7 +136,7 @@ class OAuth2ProtocolTest extends TestCase
|
|||
$client_secret = 'ITc/6Y5N7kOtGKhg';
|
||||
|
||||
//do login and consent ...
|
||||
$user = OpenIdUser::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
$user = User::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
|
||||
Auth::login($user);
|
||||
|
||||
|
@ -232,7 +233,7 @@ class OAuth2ProtocolTest extends TestCase
|
|||
$client_secret = 'ITc/6Y5N7kOtGKhg';
|
||||
|
||||
//do login and consent ...
|
||||
$user = OpenIdUser::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
$user = User::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
|
||||
Auth::login($user);
|
||||
|
||||
|
@ -333,7 +334,7 @@ class OAuth2ProtocolTest extends TestCase
|
|||
$client_secret = 'ITc/6Y5N7kOtGKhg';
|
||||
|
||||
//do login and consent ...
|
||||
$user = OpenIdUser::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
$user = User::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
|
||||
Auth::login($user);
|
||||
|
||||
|
@ -438,7 +439,7 @@ class OAuth2ProtocolTest extends TestCase
|
|||
$client_id = 'Jiz87D8/Vcvr6fvQbH4HyNgwKlfSyQ3x.openstack.client';
|
||||
|
||||
//do login and consent ...
|
||||
$user = OpenIdUser::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
$user = User::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
|
||||
Auth::login($user);
|
||||
|
||||
|
@ -480,7 +481,7 @@ class OAuth2ProtocolTest extends TestCase
|
|||
$client_id = 'Jiz87D8/Vcvr6fvQbH4HyNgwKlfSyQ3x.openstack.client';
|
||||
|
||||
//do login and consent ...
|
||||
$user = OpenIdUser::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
$user = User::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
|
||||
Auth::login($user);
|
||||
|
||||
|
@ -537,7 +538,7 @@ class OAuth2ProtocolTest extends TestCase
|
|||
$client_id = 'Jiz87D8/Vcvr6fvQbH4HyNgwKlfSyQ3x.openstack.client';
|
||||
|
||||
//do login and consent ...
|
||||
$user = OpenIdUser::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
$user = User::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
|
||||
Auth::login($user);
|
||||
|
||||
|
@ -595,7 +596,7 @@ class OAuth2ProtocolTest extends TestCase
|
|||
$client_id = 'Jiz87D8/Vcvr6fvQbH4HyNgwKlfSyQ3x.openstack.client';
|
||||
|
||||
//do login and consent ...
|
||||
$user = OpenIdUser::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
$user = User::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
|
||||
Auth::login($user);
|
||||
|
||||
|
@ -653,7 +654,7 @@ class OAuth2ProtocolTest extends TestCase
|
|||
$client_id = 'Jiz87D8/Vcvr6fvQbH4HyNgwKlfSyQ3x.openstack.client';
|
||||
|
||||
//do login and consent ...
|
||||
$user = OpenIdUser::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
$user = User::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
|
||||
Auth::login($user);
|
||||
|
||||
|
|
|
@ -1,105 +1,731 @@
|
|||
<?php
|
||||
|
||||
use openid\OpenIdProtocol;
|
||||
use auth\User;
|
||||
use utils\services\IAuthService;
|
||||
|
||||
use openid\extensions\implementations\OpenIdOAuth2Extension;
|
||||
use openid\extensions\implementations\OpenIdSREGExtension;
|
||||
|
||||
use openid\helpers\OpenIdCryptoHelper;
|
||||
use Zend\Crypt\PublicKey\DiffieHellman;
|
||||
|
||||
/**
|
||||
* Class OpenIdProtocolTest
|
||||
* Test Suite for OpenId Protocol
|
||||
*/
|
||||
class OpenIdProtocolTest extends TestCase
|
||||
{
|
||||
private $current_realm;
|
||||
private $g;
|
||||
private $private;
|
||||
private $public;
|
||||
private $mod;
|
||||
private $oauth2_client_id;
|
||||
private $oauth2_client_secret;
|
||||
|
||||
public function testCheckId_immediate_Invalid()
|
||||
public function __construct(){
|
||||
//DH openid values
|
||||
$this->g = '2';
|
||||
$this->private = '84009535308644335779530519631942543663544485189066558731295758689838227409144125540638118058012144795574289866857191302071807568041343083679600155026066530597177004145874642611724010339353151653679189142289183802715816551715563883085859667759854344959305451172754264893136955464706052993052626766687910313992';
|
||||
$this->public = '93500922748114712465435925279613158240858799671601934136793652488458659380414896628304484614933937038790006320444306607890979422427297815641372302594684991758687126229761033142429422299990743006497200988301031430937819368909849994628108111270360657896230712920491471398605159969300956278883668998797148755353';
|
||||
$this->mod = '155172898181473697471232257763715539915724801966915404479707795314057629378541917580651227423698188993727816152646631438561595825688188889951272158842675419950341258706556549803580104870537681476726513255747040765857479291291572334510643245094715007229621094194349783925984760375594985848253359305585439638443';
|
||||
$this->oauth2_client_id = 'Jiz87D8/Vcvr6fvQbH4HyNgwTlfSyQ3x.openstack.client';
|
||||
$this->oauth2_client_secret = 'ITc/6Y5N7kOtGKhg';
|
||||
}
|
||||
|
||||
protected function prepareForTests()
|
||||
{
|
||||
parent::prepareForTests();
|
||||
Route::enableFilters();
|
||||
$this->current_realm = Config::get('app.url');
|
||||
}
|
||||
|
||||
/**
|
||||
* parse openid response from an url
|
||||
* @param $url
|
||||
* @return array
|
||||
*/
|
||||
private function parseOpenIdResponse($url){
|
||||
$url_parts = @parse_url($url);
|
||||
$openid_response = array();
|
||||
$query_params = explode('&', $url_parts['query']);
|
||||
foreach ($query_params as $param) {
|
||||
$aux = explode('=', $param, 2);
|
||||
$openid_response[$aux[0]] = @urldecode($aux[1]);
|
||||
}
|
||||
return $openid_response;
|
||||
}
|
||||
|
||||
private function getOpenIdResponseLineBreak($content){
|
||||
$params = explode("\n",$content);
|
||||
$res = array();
|
||||
foreach($params as $param){
|
||||
if(empty($param)) continue;
|
||||
$openid_param = explode(':',$param,2);
|
||||
$res[$openid_param[0]] = $openid_param[1];
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exact copies of all fields from the authentication response, except for "openid.mode".
|
||||
* @param $openid_response
|
||||
* @return array
|
||||
*/
|
||||
private function prepareCheckAuthenticationParams($openid_response){
|
||||
$params = array(
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::ImmediateMode,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm) => "*.uk", //invalid realm
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo) => "http://dev.openstack.org/login",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity) => "https://dev.openstackid.com/sebastian.marcet",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId) => "https://dev.openstackid.com/sebastian.marcet",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::CheckAuthenticationMode,
|
||||
);
|
||||
|
||||
$encode = array(
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo) =>OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo),
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId) =>OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId),
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_OpEndpoint) =>OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_OpEndpoint),
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm) =>OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm),
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity) =>OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity),
|
||||
);
|
||||
|
||||
foreach($openid_response as $key => $value){
|
||||
if(!array_key_exists($key,$params))
|
||||
$params[$key] = array_key_exists($key,$encode)? @urldecode($value):$value;
|
||||
}
|
||||
return $params;
|
||||
}
|
||||
|
||||
// test for session associations
|
||||
|
||||
public function testAssociationSessionRequestDiffieHellmanSha1(){
|
||||
|
||||
$b64_public = base64_encode(OpenIdCryptoHelper::convert($this->public,DiffieHellman::FORMAT_NUMBER,DiffieHellman::FORMAT_BTWOC));
|
||||
|
||||
$this->assertTrue($b64_public === 'AIUmVPMheb/hEupD5m6veEEstnBVteyZPy+mlYX7ygxygLG/XuHFa8q4lZERJ9u1DNFOpXHRDq5RbjsaUYRDOtyrbkGbeKo5tPqjsynjXtoMAItxkxCU4jpQLvH85P+u7DeA0h3kKNHFa90ijZTIGSSDRF5wW9N+QPCUCt4G4xWZ');
|
||||
|
||||
$params = array(
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::AssociateMode,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_AssocType) => OpenIdProtocol::SignatureAlgorithmHMAC_SHA1,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_SessionType) => OpenIdProtocol::AssociationSessionTypeDHSHA1,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIdProtocol_DHConsumerPublic) => $b64_public,
|
||||
);
|
||||
|
||||
$response = $this->action("POST", "OpenIdProviderController@op_endpoint", $params);
|
||||
$status = $response->getStatusCode();
|
||||
$content = $response->getContent();
|
||||
$target_url = $response->getTargetUrl();
|
||||
|
||||
$url = explode('?', $target_url, 2);
|
||||
$openid_response = array();
|
||||
$query_params = explode('&', $url[1]);
|
||||
foreach ($query_params as $param) {
|
||||
$aux = explode('=', $param, 2);
|
||||
$openid_response[$aux[0]] = $aux[1];
|
||||
}
|
||||
$this->assertResponseStatus(200);
|
||||
|
||||
$openid_response = $this->getOpenIdResponseLineBreak($response->getContent());
|
||||
|
||||
$this->assertTrue(isset($openid_response['ns']));
|
||||
$this->assertTrue($openid_response['ns'] === OpenIdProtocol::OpenID2MessageType);
|
||||
$this->assertTrue(isset($openid_response['assoc_type']));
|
||||
$this->assertTrue($openid_response['assoc_type'] === OpenIdProtocol::SignatureAlgorithmHMAC_SHA1);
|
||||
$this->assertTrue(isset($openid_response['session_type']));
|
||||
$this->assertTrue($openid_response['session_type'] === OpenIdProtocol::AssociationSessionTypeDHSHA1);
|
||||
$this->assertTrue(isset($openid_response['assoc_handle']));
|
||||
$this->assertTrue(isset($openid_response['dh_server_public']));
|
||||
$this->assertTrue(isset($openid_response['enc_mac_key']));
|
||||
$this->assertTrue(isset($openid_response['expires_in']));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Error)]));
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS)]));
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo)]));
|
||||
$this->assertTrue($status == 302);
|
||||
}
|
||||
|
||||
public function testCheckId_immediate()
|
||||
{
|
||||
public function testAssociationSessionRequestDiffieHellmanSha256(){
|
||||
|
||||
$b64_public = base64_encode(OpenIdCryptoHelper::convert($this->public,DiffieHellman::FORMAT_NUMBER,DiffieHellman::FORMAT_BTWOC));
|
||||
|
||||
$this->assertTrue($b64_public === 'AIUmVPMheb/hEupD5m6veEEstnBVteyZPy+mlYX7ygxygLG/XuHFa8q4lZERJ9u1DNFOpXHRDq5RbjsaUYRDOtyrbkGbeKo5tPqjsynjXtoMAItxkxCU4jpQLvH85P+u7DeA0h3kKNHFa90ijZTIGSSDRF5wW9N+QPCUCt4G4xWZ');
|
||||
|
||||
$params = array(
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::ImmediateMode,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm) => "http://dev.openstack.org",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo) => "http://dev.openstack.org/login",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity) => "https://dev.openstackid.com/sebastian.marcet",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId) => "https://dev.openstackid.com/sebastian.marcet",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::AssociateMode,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_AssocType) => OpenIdProtocol::SignatureAlgorithmHMAC_SHA256,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_SessionType) => OpenIdProtocol::AssociationSessionTypeDHSHA256,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIdProtocol_DHConsumerPublic) => $b64_public,
|
||||
);
|
||||
|
||||
$response = $this->action("POST", "OpenIdProviderController@op_endpoint", $params);
|
||||
$status = $response->getStatusCode();
|
||||
$content = $response->getContent();
|
||||
$target_url = $response->getTargetUrl();
|
||||
|
||||
$url = explode('?', $target_url, 2);
|
||||
$openid_response = array();
|
||||
$query_params = explode('&', $url[1]);
|
||||
foreach ($query_params as $param) {
|
||||
$aux = explode('=', $param, 2);
|
||||
$openid_response[$aux[0]] = $aux[1];
|
||||
}
|
||||
$this->assertResponseStatus(200);
|
||||
|
||||
$openid_response = $this->getOpenIdResponseLineBreak($response->getContent());
|
||||
|
||||
$this->assertTrue(isset($openid_response['ns']));
|
||||
$this->assertTrue($openid_response['ns'] === OpenIdProtocol::OpenID2MessageType);
|
||||
$this->assertTrue(isset($openid_response['assoc_type']));
|
||||
$this->assertTrue($openid_response['assoc_type'] === OpenIdProtocol::SignatureAlgorithmHMAC_SHA256);
|
||||
$this->assertTrue(isset($openid_response['session_type']));
|
||||
$this->assertTrue($openid_response['session_type'] === OpenIdProtocol::AssociationSessionTypeDHSHA256);
|
||||
$this->assertTrue(isset($openid_response['assoc_handle']));
|
||||
$this->assertTrue(isset($openid_response['dh_server_public']));
|
||||
$this->assertTrue(isset($openid_response['enc_mac_key']));
|
||||
$this->assertTrue(isset($openid_response['expires_in']));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode)]));
|
||||
$mode = $openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode)];
|
||||
$this->assertTrue($mode == OpenIdProtocol::SetupNeededMode);
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS)]));
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo)]));
|
||||
$this->assertTrue($status == 302);
|
||||
}
|
||||
|
||||
|
||||
public function testCheckSetup()
|
||||
{
|
||||
public function testAssociationSessionRequestNoEncryption(){
|
||||
|
||||
$params = array(
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::SetupMode,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm) => "http://drupal-openid.local/",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo) => "http://drupal-openid.local/openid/authenticate?destination=%3Cfront%3E",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity) => "http://specs.openid.net/auth/2.0/identifier_select",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::AssociateMode,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_AssocType) => OpenIdProtocol::AssociationSessionTypeNoEncryption,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_SessionType) => OpenIdProtocol::AssociationSessionTypeNoEncryption,
|
||||
);
|
||||
|
||||
$response = $this->action("POST", "OpenIdProviderController@op_endpoint", $params);
|
||||
|
||||
$this->assertResponseStatus(200);
|
||||
|
||||
$openid_response = $this->getOpenIdResponseLineBreak($response->getContent());
|
||||
|
||||
$this->assertTrue(isset($openid_response['ns']));
|
||||
$this->assertTrue($openid_response['ns'] === OpenIdProtocol::OpenID2MessageType);
|
||||
$this->assertTrue(isset($openid_response['assoc_type']));
|
||||
$this->assertTrue($openid_response['assoc_type'] === OpenIdProtocol::AssociationSessionTypeNoEncryption);
|
||||
$this->assertTrue(isset($openid_response['session_type']));
|
||||
$this->assertTrue($openid_response['session_type'] === OpenIdProtocol::AssociationSessionTypeNoEncryption);
|
||||
$this->assertTrue(isset($openid_response['assoc_handle']) && ! empty($openid_response['assoc_handle']));
|
||||
$this->assertTrue(isset($openid_response['expires_in']));
|
||||
$this->assertTrue(isset($openid_response['mac_key']) && !empty($openid_response['mac_key']));
|
||||
|
||||
}
|
||||
|
||||
// test for authentication
|
||||
|
||||
public function testAuthenticationSetupModePrivateAssociation(){
|
||||
//set login info
|
||||
$user = User::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
Auth::login($user);
|
||||
Session::set("openid.authorization.response", IAuthService::AuthorizationResponse_AllowOnce);
|
||||
|
||||
|
||||
$params = array(
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::SetupMode,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm) => "https://www.test.com/",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo) => "https://www.test.com/oauth2",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity) => "http://specs.openid.net/auth/2.0/identifier_select",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId) => "http://specs.openid.net/auth/2.0/identifier_select",
|
||||
);
|
||||
|
||||
$response = $this->action("POST", "OpenIdProviderController@op_endpoint", $params);
|
||||
$status = $response->getStatusCode();
|
||||
$content = $response->getContent();
|
||||
$target_url = $response->getTargetUrl();
|
||||
|
||||
$url = explode('?', $target_url, 2);
|
||||
$openid_response = array();
|
||||
$query_params = explode('&', $url[1]);
|
||||
foreach ($query_params as $param) {
|
||||
$aux = explode('=', $param, 2);
|
||||
$openid_response[$aux[0]] = $aux[1];
|
||||
}
|
||||
$this->assertResponseStatus(302);
|
||||
|
||||
$openid_response = $this->parseOpenIdResponse($response->getTargetUrl());
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode)]));
|
||||
$mode = $openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode)];
|
||||
$this->assertTrue($mode == OpenIdProtocol::SetupNeededMode);
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS)]));
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo)]));
|
||||
$this->assertTrue($status == 302);
|
||||
|
||||
//http://openid.net/specs/openid-authentication-2_0.html#check_auth
|
||||
$response = $this->action("POST", "OpenIdProviderController@op_endpoint", $this->prepareCheckAuthenticationParams($openid_response));
|
||||
$openid_response = $this->getOpenIdResponseLineBreak($response->getContent());
|
||||
$this->assertResponseStatus(200);
|
||||
$this->assertTrue($openid_response['is_valid'] === 'true');
|
||||
}
|
||||
|
||||
|
||||
public function testAuthenticationSetupModeSessionAssociationDHSha256(){
|
||||
|
||||
$b64_public = base64_encode(OpenIdCryptoHelper::convert($this->public,DiffieHellman::FORMAT_NUMBER,DiffieHellman::FORMAT_BTWOC));
|
||||
|
||||
$this->assertTrue($b64_public === 'AIUmVPMheb/hEupD5m6veEEstnBVteyZPy+mlYX7ygxygLG/XuHFa8q4lZERJ9u1DNFOpXHRDq5RbjsaUYRDOtyrbkGbeKo5tPqjsynjXtoMAItxkxCU4jpQLvH85P+u7DeA0h3kKNHFa90ijZTIGSSDRF5wW9N+QPCUCt4G4xWZ');
|
||||
|
||||
$params = array(
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::AssociateMode,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_AssocType) => OpenIdProtocol::SignatureAlgorithmHMAC_SHA256,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_SessionType) => OpenIdProtocol::AssociationSessionTypeDHSHA256,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIdProtocol_DHConsumerPublic) => $b64_public,
|
||||
);
|
||||
|
||||
$response = $this->action("POST", "OpenIdProviderController@op_endpoint", $params);
|
||||
|
||||
$this->assertResponseStatus(200);
|
||||
|
||||
$openid_response = $this->getOpenIdResponseLineBreak($response->getContent());
|
||||
|
||||
$this->assertTrue(isset($openid_response['ns']));
|
||||
$this->assertTrue($openid_response['ns'] === OpenIdProtocol::OpenID2MessageType);
|
||||
$this->assertTrue(isset($openid_response['assoc_type']));
|
||||
$this->assertTrue($openid_response['assoc_type'] === OpenIdProtocol::SignatureAlgorithmHMAC_SHA256);
|
||||
$this->assertTrue(isset($openid_response['session_type']));
|
||||
$this->assertTrue($openid_response['session_type'] === OpenIdProtocol::AssociationSessionTypeDHSHA256);
|
||||
$this->assertTrue(isset($openid_response['assoc_handle']));
|
||||
$this->assertTrue(isset($openid_response['dh_server_public']));
|
||||
$this->assertTrue(isset($openid_response['enc_mac_key']));
|
||||
$this->assertTrue(isset($openid_response['expires_in']));
|
||||
|
||||
//set login info
|
||||
$user = User::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
Auth::login($user);
|
||||
Session::set("openid.authorization.response", IAuthService::AuthorizationResponse_AllowOnce);
|
||||
|
||||
|
||||
$params = array(
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::SetupMode,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm) => "https://www.test.com/",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo) => "https://www.test.com/oauth2",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity) => "http://specs.openid.net/auth/2.0/identifier_select",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId) => "http://specs.openid.net/auth/2.0/identifier_select",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_AssocHandle) => $openid_response['assoc_handle'],
|
||||
);
|
||||
|
||||
$response = $this->action("POST", "OpenIdProviderController@op_endpoint", $params);
|
||||
|
||||
$this->assertResponseStatus(302);
|
||||
|
||||
$openid_response = $this->parseOpenIdResponse($response->getTargetUrl());
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Sig)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Sig)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Signed)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Signed)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_OpEndpoint)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_OpEndpoint)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId)]));
|
||||
}
|
||||
|
||||
|
||||
public function testAuthenticationCheckImmediateAuthenticationPrivateSession(){
|
||||
//set login info
|
||||
$user = User::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
Auth::login($user);
|
||||
Session::set("openid.authorization.response", IAuthService::AuthorizationResponse_AllowOnce);
|
||||
|
||||
|
||||
$params = array(
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::ImmediateMode,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm) => "https://www.test.com/",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo) => "https://www.test.com/oauth2",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity) => "http://specs.openid.net/auth/2.0/identifier_select",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId) => "http://specs.openid.net/auth/2.0/identifier_select",
|
||||
);
|
||||
|
||||
$response = $this->action("POST", "OpenIdProviderController@op_endpoint", $params);
|
||||
|
||||
$this->assertResponseStatus(302);
|
||||
|
||||
$openid_response = $this->parseOpenIdResponse($response->getTargetUrl());
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Sig)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Sig)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Signed)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Signed)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_OpEndpoint)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_OpEndpoint)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId)]));
|
||||
}
|
||||
|
||||
|
||||
//extension tests
|
||||
|
||||
|
||||
|
||||
public function testCheckSetupSREGExtension(){
|
||||
|
||||
//set login info
|
||||
$user = User::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
Auth::login($user);
|
||||
Session::set("openid.authorization.response", IAuthService::AuthorizationResponse_AllowForever);
|
||||
|
||||
|
||||
$sreg_required_params = array('email','fullname');
|
||||
|
||||
$params = array(
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::SetupMode,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm) => "https://www.test.com/",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo) => "https://www.test.com/oauth2",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity) => "http://specs.openid.net/auth/2.0/identifier_select",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId) => "http://specs.openid.net/auth/2.0/identifier_select",
|
||||
//sreg
|
||||
OpenIdSREGExtension::paramNamespace() => OpenIdSREGExtension::NamespaceUrl,
|
||||
OpenIdSREGExtension::param(OpenIdSREGExtension::Required) => implode(",",$sreg_required_params),
|
||||
|
||||
);
|
||||
|
||||
$response = $this->action("POST", "OpenIdProviderController@op_endpoint", $params);
|
||||
|
||||
$this->assertResponseStatus(302);
|
||||
|
||||
$openid_response = $this->parseOpenIdResponse($response->getTargetUrl());
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Sig)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Sig)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Signed)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Signed)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_OpEndpoint)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_OpEndpoint)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId)]));
|
||||
|
||||
|
||||
//sreg
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdSREGExtension::paramNamespace()]));
|
||||
$this->assertTrue($openid_response[OpenIdSREGExtension::paramNamespace()] === OpenIdSREGExtension::NamespaceUrl);
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdSREGExtension::param(OpenIdSREGExtension::FullName)]));
|
||||
$full_name = $openid_response[OpenIdSREGExtension::param(OpenIdSREGExtension::FullName)];
|
||||
$this->assertTrue(!empty($full_name) && $full_name ==='Sebastian Marcet');
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdSREGExtension::param(OpenIdSREGExtension::Email)]));
|
||||
$email = $openid_response[OpenIdSREGExtension::param(OpenIdSREGExtension::Email)];
|
||||
$this->assertTrue(!empty($email) && $email ==='smarcet@gmail.com');
|
||||
|
||||
//http://openid.net/specs/openid-authentication-2_0.html#check_auth
|
||||
$response = $this->action("POST", "OpenIdProviderController@op_endpoint", $this->prepareCheckAuthenticationParams($openid_response));
|
||||
$openid_response = $this->getOpenIdResponseLineBreak($response->getContent());
|
||||
$this->assertResponseStatus(200);
|
||||
$this->assertTrue($openid_response['is_valid'] === 'true');
|
||||
}
|
||||
|
||||
/**
|
||||
* test openid oauth2 extension
|
||||
* https://developers.google.com/accounts/docs/OpenID#oauth
|
||||
*/
|
||||
|
||||
public function testCheckSetupOAuth2Extension(){
|
||||
|
||||
//set login info
|
||||
$user = User::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
Auth::login($user);
|
||||
Session::set("openid.authorization.response", IAuthService::AuthorizationResponse_AllowForever);
|
||||
|
||||
$scope = array(
|
||||
sprintf('%s/api/resource-server/read',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/read.page',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/write',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/delete',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/update',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/update.status',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/regenerate.secret',$this->current_realm),
|
||||
);
|
||||
|
||||
$params = array(
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::SetupMode,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm) => "https://www.test.com/",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo) => "https://www.test.com/oauth2",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity) => "http://specs.openid.net/auth/2.0/identifier_select",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId) => "http://specs.openid.net/auth/2.0/identifier_select",
|
||||
//oauth2
|
||||
OpenIdOAuth2Extension::paramNamespace() => OpenIdOAuth2Extension::NamespaceUrl,
|
||||
OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::ClientId) => $this->oauth2_client_id,
|
||||
OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::Scope) => implode(' ',$scope),
|
||||
OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::State) => uniqid(),
|
||||
);
|
||||
|
||||
$response = $this->action("POST", "OpenIdProviderController@op_endpoint", $params);
|
||||
|
||||
$this->assertResponseStatus(302);
|
||||
|
||||
$openid_response = $this->parseOpenIdResponse($response->getTargetUrl());
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Sig)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Sig)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Signed)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Signed)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_OpEndpoint)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_OpEndpoint)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId)]));
|
||||
|
||||
|
||||
//oauth2
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdOAuth2Extension::paramNamespace()]));
|
||||
$this->assertTrue($openid_response[OpenIdOAuth2Extension::paramNamespace()] === OpenIdOAuth2Extension::NamespaceUrl);
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::RequestToken)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::RequestToken)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::Scope)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::Scope)]));
|
||||
|
||||
|
||||
//http://openid.net/specs/openid-authentication-2_0.html#check_auth
|
||||
$response = $this->action("POST", "OpenIdProviderController@op_endpoint", $this->prepareCheckAuthenticationParams($openid_response));
|
||||
$openid_response = $this->getOpenIdResponseLineBreak($response->getContent());
|
||||
$this->assertResponseStatus(200);
|
||||
$this->assertTrue($openid_response['is_valid'] === 'true');
|
||||
}
|
||||
|
||||
public function testCheckSetupOAuth2ExtensionWrongClientId(){
|
||||
|
||||
//set login info
|
||||
$user = User::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
Auth::login($user);
|
||||
Session::set("openid.authorization.response", IAuthService::AuthorizationResponse_AllowOnce);
|
||||
|
||||
$scope = array(
|
||||
sprintf('%s/api/resource-server/read',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/read.page',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/write',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/delete',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/update',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/update.status',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/regenerate.secret',$this->current_realm),
|
||||
);
|
||||
|
||||
$params = array(
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::SetupMode,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm) => "https://www.test.com/",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo) => "https://www.test.com/oauth2",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity) => "http://specs.openid.net/auth/2.0/identifier_select",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId) => "http://specs.openid.net/auth/2.0/identifier_select",
|
||||
//oauth2
|
||||
OpenIdOAuth2Extension::paramNamespace() => OpenIdOAuth2Extension::NamespaceUrl,
|
||||
OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::ClientId) => 'wrong_client_id',
|
||||
OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::Scope) => implode(' ',$scope),
|
||||
OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::State) => uniqid(),
|
||||
);
|
||||
|
||||
$response = $this->action("POST", "OpenIdProviderController@op_endpoint", $params);
|
||||
|
||||
$this->assertResponseStatus(302);
|
||||
|
||||
$openid_response = $this->parseOpenIdResponse($response->getTargetUrl());
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Sig)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Sig)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Signed)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Signed)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_OpEndpoint)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_OpEndpoint)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId)]));
|
||||
|
||||
//oauth 2
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdOAuth2Extension::paramNamespace()]));
|
||||
$this->assertTrue($openid_response[OpenIdOAuth2Extension::paramNamespace()] === OpenIdOAuth2Extension::NamespaceUrl);
|
||||
|
||||
$this->assertTrue(!isset($openid_response[OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::Scope)]));
|
||||
|
||||
$this->assertTrue(!isset($openid_response[OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::RequestToken)]));
|
||||
|
||||
|
||||
//http://openid.net/specs/openid-authentication-2_0.html#check_auth
|
||||
$response = $this->action("POST", "OpenIdProviderController@op_endpoint", $this->prepareCheckAuthenticationParams($openid_response));
|
||||
$openid_response = $this->getOpenIdResponseLineBreak($response->getContent());
|
||||
$this->assertResponseStatus(200);
|
||||
$this->assertTrue($openid_response['is_valid'] === 'true');
|
||||
}
|
||||
|
||||
public function testCheckSetupOAuth2ExtensionBadRequest(){
|
||||
|
||||
//set login info
|
||||
$user = User::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
Auth::login($user);
|
||||
Session::set("openid.authorization.response", IAuthService::AuthorizationResponse_AllowOnce);
|
||||
|
||||
$scope = array(
|
||||
sprintf('%s/api/resource-server/read',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/read.page',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/write',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/delete',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/update',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/update.status',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/regenerate.secret',$this->current_realm),
|
||||
);
|
||||
|
||||
$params = array(
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::SetupMode,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm) => "https://www.test.com/",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo) => "https://www.test.com/oauth2",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity) => "http://specs.openid.net/auth/2.0/identifier_select",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId) => "http://specs.openid.net/auth/2.0/identifier_select",
|
||||
//oauth2
|
||||
OpenIdOAuth2Extension::paramNamespace() => OpenIdOAuth2Extension::NamespaceUrl,
|
||||
//missing client id
|
||||
//OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::ClientId) => 'wrong_client_id',
|
||||
OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::Scope) => implode(' ',$scope),
|
||||
OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::State) => uniqid(),
|
||||
);
|
||||
|
||||
$response = $this->action("POST", "OpenIdProviderController@op_endpoint", $params);
|
||||
|
||||
$this->assertResponseStatus(302);
|
||||
|
||||
$openid_response = $this->parseOpenIdResponse($response->getTargetUrl());
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Sig)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Sig)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Signed)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Signed)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_OpEndpoint)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_OpEndpoint)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity)]));
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId)]));
|
||||
$this->assertTrue(!empty($openid_response[OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId)]));
|
||||
|
||||
//oauth 2
|
||||
|
||||
$this->assertTrue(isset($openid_response[OpenIdOAuth2Extension::paramNamespace()]));
|
||||
$this->assertTrue($openid_response[OpenIdOAuth2Extension::paramNamespace()] === OpenIdOAuth2Extension::NamespaceUrl);
|
||||
|
||||
$this->assertTrue(!isset($openid_response[OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::Scope)]));
|
||||
|
||||
$this->assertTrue(!isset($openid_response[OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::RequestToken)]));
|
||||
|
||||
|
||||
//http://openid.net/specs/openid-authentication-2_0.html#check_auth
|
||||
$response = $this->action("POST", "OpenIdProviderController@op_endpoint", $this->prepareCheckAuthenticationParams($openid_response));
|
||||
$openid_response = $this->getOpenIdResponseLineBreak($response->getContent());
|
||||
$this->assertResponseStatus(200);
|
||||
$this->assertTrue($openid_response['is_valid'] === 'true');
|
||||
}
|
||||
|
||||
public function testCheckSetupOAuth2ExtensionSubView(){
|
||||
|
||||
//set login info
|
||||
$user = User::where('external_id', '=', 'smarcet@gmail.com')->first();
|
||||
Auth::login($user);
|
||||
|
||||
$scope = array(
|
||||
sprintf('%s/api/resource-server/read',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/read.page',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/write',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/delete',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/update',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/update.status',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/regenerate.secret',$this->current_realm),
|
||||
);
|
||||
|
||||
$params = array(
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_NS) => OpenIdProtocol::OpenID2MessageType,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Mode) => OpenIdProtocol::SetupMode,
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Realm) => "https://www.test.com/",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ReturnTo) => "https://www.test.com/oauth2",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_Identity) => "http://specs.openid.net/auth/2.0/identifier_select",
|
||||
OpenIdProtocol::param(OpenIdProtocol::OpenIDProtocol_ClaimedId) => "http://specs.openid.net/auth/2.0/identifier_select",
|
||||
//oauth2
|
||||
OpenIdOAuth2Extension::paramNamespace() => OpenIdOAuth2Extension::NamespaceUrl,
|
||||
OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::ClientId) => $this->oauth2_client_id,
|
||||
OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::Scope) => implode(' ',$scope),
|
||||
OpenIdOAuth2Extension::param(OpenIdOAuth2Extension::State) => uniqid(),
|
||||
);
|
||||
|
||||
$response = $this->action("POST", "OpenIdProviderController@op_endpoint", $params);
|
||||
|
||||
$this->assertResponseStatus(302);
|
||||
|
||||
$content = $response->getContent();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
use oauth2\OAuth2Protocol;
|
||||
|
||||
/**
|
||||
* Class ResourceServerApiTest
|
||||
* Test Suite for OAuth2 Protected Resource Server Api
|
||||
*/
|
||||
class ResourceServerApiTest extends TestCase {
|
||||
|
||||
private $access_token;
|
||||
|
@ -17,7 +21,6 @@ class ResourceServerApiTest extends TestCase {
|
|||
$this->client_id = 'Jiz87D8/Vcvr6fvQbH4HyNgwTlfSyQ3x.openstack.client';
|
||||
$this->client_secret = 'ITc/6Y5N7kOtGKhg';
|
||||
|
||||
|
||||
$scope = array(
|
||||
sprintf('%s/api/resource-server/read',$this->current_realm),
|
||||
sprintf('%s/api/resource-server/read.page',$this->current_realm),
|
||||
|
@ -34,6 +37,8 @@ class ResourceServerApiTest extends TestCase {
|
|||
OAuth2Protocol::OAuth2Protocol_Scope => implode(' ',$scope)
|
||||
);
|
||||
|
||||
//get access token for api ...
|
||||
|
||||
$response = $this->action("POST", "OAuth2ProviderController@token",
|
||||
$params,
|
||||
array(),
|
||||
|
|
|
@ -2,14 +2,22 @@
|
|||
|
||||
class TestCase extends Illuminate\Foundation\Testing\TestCase {
|
||||
|
||||
private $redis;
|
||||
|
||||
public function __construct(){
|
||||
|
||||
}
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp(); // Don't forget this!
|
||||
|
||||
$this->redis = \RedisLV4::connection();
|
||||
$this->redis->flushall();
|
||||
$this->prepareForTests();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
/**
|
||||
* Migrates the database and set the mailer to 'pretend'.
|
||||
* This will cause the tests to run quickly.
|
||||
*
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
@if(count($attributes)>0)
|
||||
<label>
|
||||
The site has also requested some personal information
|
||||
<b>The site has also requested some personal information</b>
|
||||
</label>
|
||||
<ul class="unstyled list-inline">
|
||||
@foreach ($attributes as $attr)
|
||||
<li>{{$attr}} <i class="icon-info-sign"></i></li>
|
||||
<li>{{$attr}} <i class="icon-info-sign info"></i></li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endif
|
|
@ -0,0 +1,55 @@
|
|||
@if(count($requested_scopes)>0)
|
||||
<label>
|
||||
<b>The site has also requested some permissions for following OAuth2 application</b>
|
||||
</label>
|
||||
<div class="container">
|
||||
<div class="row-fluid">
|
||||
<div class="span6">
|
||||
<div class="row-fluid">
|
||||
<div class="span2">
|
||||
<img src="{{$app_logo}}" border="0"/>
|
||||
</div>
|
||||
<div class="span10">
|
||||
<h2>{{$app_name}} <i data-content="Developer Email: <a href='mailto:{{$dev_info_email}}'>{{$dev_info_email}}</a>.<br> Clicking 'Accept' will redirect you to: <a href='{{$redirect_to}}' target='_blank'>{{$redirect_to}}</a>" class="icon-info-sign info" title="Developer Info"></i></h2>
|
||||
</div>
|
||||
</div>
|
||||
<legend>This app would like to:</legend>
|
||||
<ul class="unstyled list-inline">
|
||||
@foreach ($requested_scopes as $scope)
|
||||
<li> {{$scope->short_description}} <i class="icon-info-sign info" data-content="{{$scope->description}}" title="Scope Info"></i></li>
|
||||
@endforeach
|
||||
</ul>
|
||||
<p class="privacy-policy">
|
||||
** <b>{{$app_name}}</b> Application and <b>Openstack</b> will use this information in accordance with their respective terms of service and privacy policies.
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@section('subscripts')
|
||||
<script type="application/javascript">
|
||||
$(document).ready(function() {
|
||||
|
||||
var hideAllPopovers = function() {
|
||||
$('.icon-info-sign').each(function() {
|
||||
$(this).popover('hide');
|
||||
});
|
||||
};
|
||||
|
||||
$('.icon-info-sign').popover({html:true});
|
||||
|
||||
$(':not(#anything)').on('click', function (e) {
|
||||
$('.icon-info-sign').each(function () {
|
||||
//the 'is' for buttons that trigger popups
|
||||
//the 'has' for icons and other elements within a button that triggers a popup
|
||||
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
|
||||
$(this).popover('hide');
|
||||
return;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@stop
|
|
@ -1,10 +1,10 @@
|
|||
@if(count($attributes)>0)
|
||||
<label>
|
||||
The site has also requested some personal information
|
||||
<b>The site has also requested some personal information</b>
|
||||
</label>
|
||||
<ul class="unstyled list-inline">
|
||||
@foreach ($attributes as $attr)
|
||||
<li>{{$attr}} <i class="icon-info-sign"></i></li>
|
||||
<li>{{$attr}} <i class="icon-info-sign info"></i></li>
|
||||
@endforeach
|
||||
</ul>
|
||||
@endif
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
{{ HTML::script('js/jquery.validate.min.js')}}
|
||||
{{ HTML::script('js/additional-methods.min.js')}}
|
||||
@yield('scripts')
|
||||
@yield('subscripts')
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -22,7 +22,7 @@
|
|||
<img src="{{$app_logo}}" border="0"/>
|
||||
</div>
|
||||
<div class="span10">
|
||||
<h2>{{$app_name}} <i data-content="Developer Email: <a href='#'>{{$dev_info_email}}</a>.<br> Clicking 'Accept' will redirect you to: <a href='#'>{{$redirect_to}}</a>" class="icon-info-sign info" title="Developer Info"></i></h2>
|
||||
<h2>{{$app_name}} <i data-content="Developer Email: <a href='mailto:{{$dev_info_email}}'>{{$dev_info_email}}</a>.<br> Clicking 'Accept' will redirect you to: <a href='{{$redirect_to}}' target="_blank">{{$redirect_to}}</a>" class="icon-info-sign info" title="Developer Info"></i></h2>
|
||||
</div>
|
||||
</div>
|
||||
<legend>This app would like to:</legend>
|
||||
|
@ -50,6 +50,17 @@
|
|||
|
||||
$('.icon-info-sign').popover({html:true});
|
||||
|
||||
$(':not(#anything)').on('click', function (e) {
|
||||
$('.icon-info-sign').each(function () {
|
||||
//the 'is' for buttons that trigger popups
|
||||
//the 'has' for icons and other elements within a button that triggers a popup
|
||||
if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
|
||||
$(this).popover('hide');
|
||||
return;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("body").on('click',"#cancel-authorization",function(event){
|
||||
$form = $('#authorization_form');
|
||||
$('#trust').attr('value','DenyOnce');
|
||||
|
|
|
@ -18,7 +18,10 @@ Welcome, <a href="{{ URL::action("UserController@getProfile") }}">{{Auth::user()
|
|||
Sign in to <b>{{ $realm }}</b> using your openstackid
|
||||
</legend>
|
||||
<p>A site identifying itself as <b>{{ $realm }}</b></p>
|
||||
<p>has asked us for confirmation that <a href="{{ str_replace("%23","#",$openid_url) }}">{{ str_replace("%23","#",$openid_url) }}</a> is your identity URL</p>
|
||||
<p>has asked us for confirmation that <a href="{{ str_replace("%23","#",$openid_url) }}" target='_blank'>{{ str_replace("%23","#",$openid_url) }}</a> is your identity URL</p>
|
||||
@foreach ($views as $view)
|
||||
{{ $view}}
|
||||
@endforeach
|
||||
<div>
|
||||
<label class="radio">
|
||||
{{ Form::radio('trust[]', 'AllowOnce','true',array('id'=>'allow_once','class'=>'input-block-level')) }}
|
||||
|
@ -41,9 +44,7 @@ Welcome, <a href="{{ URL::action("UserController@getProfile") }}">{{Auth::user()
|
|||
{{ Form::button('Cancel',array('id'=>'cancel_authorization','class'=>'btn cancel_authorization')) }}
|
||||
</fieldset>
|
||||
{{ Form::close() }}
|
||||
@foreach ($views as $view)
|
||||
{{ $view}}
|
||||
@endforeach
|
||||
|
||||
</div>
|
||||
@stop
|
||||
|
||||
|
@ -59,4 +60,6 @@ Welcome, <a href="{{ URL::action("UserController@getProfile") }}">{{Auth::user()
|
|||
});
|
||||
});
|
||||
</script>
|
||||
@stop
|
||||
@stop
|
||||
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ use auth\CustomAuthProvider;
|
|||
|
||||
Auth::extend('custom', function($app) {
|
||||
return new Guard(
|
||||
new CustomAuthProvider(),
|
||||
new CustomAuthProvider($app->app->make('auth\\IAuthenticationExtensionService')),
|
||||
App::make('session.store')
|
||||
);
|
||||
});
|
||||
|
|
|
@ -69,3 +69,16 @@ select, input[type="text"]{
|
|||
#redirect_uri{
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
.popover-content{
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.popover {
|
||||
width: auto;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
.info{
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue