SSO 3rd Party integration
Disqus GET /api/v1/sso/disqus/{forum_slug}/profile required scope sso Rocket Chat GET /api/v1/sso/rocket-chat/{forum_slug}/profile required scope sso Change-Id: Ie72bc4846356cbef00c04a52d1329af53469e9a6 Signed-off-by: smarcet <smarcet@gmail.com>
This commit is contained in:
parent
e5898c4fab
commit
cff54c01e6
|
@ -0,0 +1,66 @@
|
|||
<?php namespace App\Http\Controllers\Api\OAuth2;
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
use App\Services\Auth\IDisqusSSOService;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use models\exceptions\EntityNotFoundException;
|
||||
use models\exceptions\ValidationException;
|
||||
use OAuth2\IResourceServerContext;
|
||||
use Utils\Services\ILogService;
|
||||
/**
|
||||
* Class OAuth2DisqusSSOApiController
|
||||
* @package App\Http\Controllers\Api\OAuth2
|
||||
*/
|
||||
final class OAuth2DisqusSSOApiController extends OAuth2ProtectedController
|
||||
{
|
||||
|
||||
/**
|
||||
* @var IDisqusSSOService
|
||||
*/
|
||||
private $service;
|
||||
|
||||
public function __construct
|
||||
(
|
||||
IDisqusSSOService $service,
|
||||
IResourceServerContext $resource_server_context,
|
||||
ILogService $log_service
|
||||
)
|
||||
{
|
||||
parent::__construct($resource_server_context, $log_service);
|
||||
$this->service = $service;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $forum_slug
|
||||
* @return \Illuminate\Http\JsonResponse|mixed
|
||||
*/
|
||||
public function getUserProfile(string $forum_slug){
|
||||
try{
|
||||
$profile = $this->service->getUserProfile($forum_slug);
|
||||
return $this->ok($profile->serialize());
|
||||
}
|
||||
catch (ValidationException $ex) {
|
||||
Log::warning($ex);
|
||||
return $this->error412([$ex->getMessage()]);
|
||||
}
|
||||
catch(EntityNotFoundException $ex)
|
||||
{
|
||||
Log::warning($ex);
|
||||
return $this->error404(['message'=> $ex->getMessage()]);
|
||||
}
|
||||
catch (\Exception $ex) {
|
||||
Log::error($ex);
|
||||
return $this->error500($ex);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
<?php namespace App\Http\Controllers\Api\OAuth2;
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
use App\Services\Auth\IRocketChatSSOService;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use models\exceptions\EntityNotFoundException;
|
||||
use models\exceptions\ValidationException;
|
||||
use OAuth2\IResourceServerContext;
|
||||
use Utils\Services\ILogService;
|
||||
/**
|
||||
* Class OAuth2RocketChatSSOApiController
|
||||
* @package App\Http\Controllers\Api\OAuth2
|
||||
*/
|
||||
class OAuth2RocketChatSSOApiController extends OAuth2ProtectedController
|
||||
{
|
||||
/**
|
||||
* @var IRocketChatSSOService
|
||||
*/
|
||||
private $service;
|
||||
|
||||
public function __construct
|
||||
(
|
||||
IRocketChatSSOService $service,
|
||||
IResourceServerContext $resource_server_context,
|
||||
ILogService $log_service
|
||||
)
|
||||
{
|
||||
parent::__construct($resource_server_context, $log_service);
|
||||
$this->service = $service;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $forum_slug
|
||||
* @return \Illuminate\Http\JsonResponse|mixed
|
||||
*/
|
||||
public function getUserProfile(string $forum_slug){
|
||||
try{
|
||||
$profile = $this->service->getUserProfile($forum_slug);
|
||||
return $this->ok($profile->serialize());
|
||||
}
|
||||
catch (ValidationException $ex) {
|
||||
Log::warning($ex);
|
||||
return $this->error412([$ex->getMessage()]);
|
||||
}
|
||||
catch(EntityNotFoundException $ex)
|
||||
{
|
||||
Log::warning($ex);
|
||||
return $this->error404(['message'=> $ex->getMessage()]);
|
||||
}
|
||||
catch (\Exception $ex) {
|
||||
Log::error($ex);
|
||||
return $this->error500($ex);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,7 +27,7 @@ use Exception;
|
|||
* Class OAuth2UserApiController
|
||||
* @package App\Http\Controllers\Api\OAuth2
|
||||
*/
|
||||
final class OAuth2UserApiController extends OAuth2ProtectedController
|
||||
final class OAuth2UserApiController extends OAuth2ProtectedController
|
||||
{
|
||||
use GetAllTrait;
|
||||
|
||||
|
|
|
@ -193,7 +193,7 @@ final class OAuth2BearerAccessTokenRequestValidator
|
|||
//if js client , then check if the origin is allowed ....
|
||||
if($client->getApplicationType() == IClient::ApplicationType_JS_Client)
|
||||
{
|
||||
if(!$client->isOriginAllowed($origin))
|
||||
if(!empty($origin) && !$client->isOriginAllowed($origin))
|
||||
throw new OAuth2ResourceServerException
|
||||
(
|
||||
403,
|
||||
|
|
|
@ -160,7 +160,7 @@ Route::group(['namespace' => 'App\Http\Controllers', 'middleware' => 'web' ], fu
|
|||
});
|
||||
});
|
||||
|
||||
//Admin Backend API
|
||||
// Admin Backend Services
|
||||
|
||||
Route::group([
|
||||
'namespace' => 'Api',
|
||||
|
@ -365,7 +365,8 @@ Route::group(['namespace' => 'App\Http\Controllers', 'middleware' => 'web' ], fu
|
|||
});
|
||||
});
|
||||
|
||||
//OAuth2 Protected API
|
||||
// OAuth2 Protected API
|
||||
|
||||
Route::group(
|
||||
[
|
||||
'namespace' => 'App\Http\Controllers\Api\OAuth2',
|
||||
|
@ -383,4 +384,21 @@ Route::group(
|
|||
Route::group(['prefix' => 'user-registration-requests'], function(){
|
||||
Route::post('', 'OAuth2UserRegistrationRequestApiController@register');
|
||||
});
|
||||
|
||||
// 3rd Party SSO integrations
|
||||
|
||||
Route::group(['prefix' => 'sso'], function () {
|
||||
|
||||
Route::group(['prefix' => 'disqus'], function () {
|
||||
Route::group(['prefix' => '{forum_slug}'], function () {
|
||||
Route::get('profile', 'OAuth2DisqusSSOApiController@getUserProfile');
|
||||
});
|
||||
});
|
||||
|
||||
Route::group(['prefix' => 'rocket-chat'], function () {
|
||||
Route::group(['prefix' => '{forum_slug}'], function () {
|
||||
Route::get('profile', 'OAuth2RocketChatSSOApiController@getUserProfile');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,24 @@
|
|||
<?php namespace App\Models\Repositories;
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
use App\Models\SSO\DisqusSSOProfile;
|
||||
use models\utils\IBaseRepository;
|
||||
|
||||
/**
|
||||
* Interface IDisqusSSOProfileRepository
|
||||
* @package App\Models\Repositories
|
||||
*/
|
||||
interface IDisqusSSOProfileRepository extends IBaseRepository
|
||||
{
|
||||
public function getByForumSlug(string $forum_slug):?DisqusSSOProfile;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
<?php namespace App\Models\Repositories;
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
use App\Models\SSO\RocketChatSSOProfile;
|
||||
use models\utils\IBaseRepository;
|
||||
/**
|
||||
* Interface IRocketChatSSOProfileRepository
|
||||
* @package App\Models\Repositories
|
||||
*/
|
||||
interface IRocketChatSSOProfileRepository extends IBaseRepository
|
||||
{
|
||||
public function getByForumSlug(string $forum_slug):?RocketChatSSOProfile;
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
<?php namespace App\Models\SSO;
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
use App\Models\Utils\BaseEntity;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\Mapping AS ORM;
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Repositories\DoctrineDisqusSSOProfileRepository")
|
||||
* @ORM\Table(name="sso_disqus_profile")
|
||||
* Class DisqusSSOProfile
|
||||
* @package App\Models\SSO
|
||||
*/
|
||||
class DisqusSSOProfile extends BaseEntity
|
||||
{
|
||||
/**
|
||||
* @ORM\Column(name="forum_slug", type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $forum_slug;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="public_key", type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $public_key;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="secret_key", type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $secret_key;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getForumSlug(): string
|
||||
{
|
||||
return $this->forum_slug;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $forum_slug
|
||||
*/
|
||||
public function setForumSlug(string $forum_slug): void
|
||||
{
|
||||
$this->forum_slug = $forum_slug;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getPublicKey(): string
|
||||
{
|
||||
return $this->public_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $public_key
|
||||
*/
|
||||
public function setPublicKey(string $public_key): void
|
||||
{
|
||||
$this->public_key = $public_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSecretKey(): string
|
||||
{
|
||||
return $this->secret_key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $secret_key
|
||||
*/
|
||||
public function setSecretKey(string $secret_key): void
|
||||
{
|
||||
$this->secret_key = $secret_key;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
<?php namespace App\Models\SSO\Disqus;
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
use App\Models\SSO\DisqusSSOProfile;
|
||||
use Auth\User;
|
||||
|
||||
/**
|
||||
* Class DisqusUserProfile
|
||||
* @package App\Models\SSO\Disqus
|
||||
*/
|
||||
class DisqusUserProfile
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $public_key;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $user_id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $user_email;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $user_name;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $private_key;
|
||||
|
||||
/**
|
||||
* DisqusUserProfile constructor.
|
||||
* @param DisqusSSOProfile $profile
|
||||
* @param User $user
|
||||
*/
|
||||
public function __construct(DisqusSSOProfile $profile, User $user)
|
||||
{
|
||||
$this->public_key = $profile->getPublicKey();
|
||||
$this->private_key = $profile->getSecretKey();
|
||||
$this->user_id = $user->getId();
|
||||
$this->user_email = $user->getEmail();
|
||||
$this->user_name = $user->getNickName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
* @param string $key
|
||||
* @return string
|
||||
*/
|
||||
private function dsq_hmacsha1(string $data, string $key):string {
|
||||
$blocksize=64;
|
||||
$hashfunc='sha1';
|
||||
if (strlen($key)>$blocksize)
|
||||
$key=pack('H*', $hashfunc($key));
|
||||
$key=str_pad($key,$blocksize,chr(0x00));
|
||||
$ipad=str_repeat(chr(0x36),$blocksize);
|
||||
$opad=str_repeat(chr(0x5c),$blocksize);
|
||||
$hmac = pack(
|
||||
'H*',$hashfunc(
|
||||
($key^$opad).pack(
|
||||
'H*',$hashfunc(
|
||||
($key^$ipad).$data
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
return bin2hex($hmac);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function serialize(){
|
||||
$data = [
|
||||
"id" => $this->user_id,
|
||||
"username" => $this->user_name,
|
||||
"email" => $this->user_email
|
||||
];
|
||||
|
||||
$message = base64_encode(json_encode($data));
|
||||
$timestamp = time();
|
||||
$hmac = $this->dsq_hmacsha1($message . ' ' . $timestamp, $this->private_key);
|
||||
|
||||
return [
|
||||
'auth' => $message." ".$hmac." ".$timestamp,
|
||||
'public_key' => $this->public_key
|
||||
];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
<?php namespace App\Models\SSO;
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
use App\Models\Utils\BaseEntity;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\Mapping AS ORM;
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Repositories\DoctrineRocketChatSSOProfileRepository")
|
||||
* @ORM\Table(name="sso_rocket_chat_profile")
|
||||
* Class RocketChatSSOProfile
|
||||
* @package App\Models\SSO
|
||||
*/
|
||||
class RocketChatSSOProfile extends BaseEntity
|
||||
{
|
||||
/**
|
||||
* @ORM\Column(name="forum_slug", type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $forum_slug;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="base_url", type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $base_url;
|
||||
|
||||
/**
|
||||
* @ORM\Column(name="service_name", type="string")
|
||||
* @var string
|
||||
*/
|
||||
private $service_name;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getForumSlug(): string
|
||||
{
|
||||
return $this->forum_slug;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $forum_slug
|
||||
*/
|
||||
public function setForumSlug(string $forum_slug): void
|
||||
{
|
||||
$this->forum_slug = $forum_slug;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getBaseUrl(): string
|
||||
{
|
||||
return $this->base_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $base_url
|
||||
*/
|
||||
public function setBaseUrl(string $base_url): void
|
||||
{
|
||||
$this->base_url = $base_url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getServiceName(): string
|
||||
{
|
||||
return $this->service_name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $service_name
|
||||
*/
|
||||
public function setServiceName(string $service_name): void
|
||||
{
|
||||
$this->service_name = $service_name;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
<?php namespace App\Models\SSO;
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
/**
|
||||
* Class RocketChatUserProfile
|
||||
* @package App\Models\SSO
|
||||
*/
|
||||
class RocketChatUserProfile
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $payload;
|
||||
|
||||
/**
|
||||
* RocketChatUserProfile constructor.
|
||||
* @param array $payload
|
||||
*/
|
||||
public function __construct(array $payload)
|
||||
{
|
||||
$this->payload = $payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function serialize():array {
|
||||
return $this->payload['data'] ?? [];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?php namespace App\Repositories;
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
use App\Models\Repositories\IDisqusSSOProfileRepository;
|
||||
use App\Models\SSO\DisqusSSOProfile;
|
||||
/**
|
||||
* Class DoctrineDisqusSSOProfileRepository
|
||||
* @package App\Repositories
|
||||
*/
|
||||
final class DoctrineDisqusSSOProfileRepository extends ModelDoctrineRepository
|
||||
implements IDisqusSSOProfileRepository
|
||||
{
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function getBaseEntity()
|
||||
{
|
||||
return DisqusSSOProfile::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $forum_slug
|
||||
* @return DisqusSSOProfile|null
|
||||
*/
|
||||
public function getByForumSlug(string $forum_slug): ?DisqusSSOProfile
|
||||
{
|
||||
return $this->findOneBy([
|
||||
'forum_slug' => trim($forum_slug)
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
<?php namespace App\Repositories;
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
use App\Models\Repositories\IRocketChatSSOProfileRepository;
|
||||
use App\Models\SSO\RocketChatSSOProfile;
|
||||
/**
|
||||
* Class DoctrineRocketChatSSOProfileRepository
|
||||
* @package App\Repositories
|
||||
*/
|
||||
final class DoctrineRocketChatSSOProfileRepository extends ModelDoctrineRepository
|
||||
implements IRocketChatSSOProfileRepository
|
||||
{
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function getBaseEntity()
|
||||
{
|
||||
return RocketChatSSOProfile::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $forum_slug
|
||||
* @return RocketChatSSOProfile|null
|
||||
*/
|
||||
public function getByForumSlug(string $forum_slug): ?RocketChatSSOProfile
|
||||
{
|
||||
return $this->findOneBy([
|
||||
'forum_slug' => trim($forum_slug)
|
||||
]);
|
||||
}
|
||||
}
|
|
@ -21,6 +21,10 @@ use App\libs\Auth\Repositories\IUserPasswordResetRequestRepository;
|
|||
use App\libs\Auth\Repositories\IUserRegistrationRequestRepository;
|
||||
use App\libs\Auth\Repositories\IWhiteListedIPRepository;
|
||||
use App\libs\OAuth2\Repositories\IOAuth2TrailExceptionRepository;
|
||||
use App\Models\Repositories\IDisqusSSOProfileRepository;
|
||||
use App\Models\Repositories\IRocketChatSSOProfileRepository;
|
||||
use App\Models\SSO\DisqusSSOProfile;
|
||||
use App\Models\SSO\RocketChatSSOProfile;
|
||||
use App\Repositories\IServerConfigurationRepository;
|
||||
use App\Repositories\IServerExtensionRepository;
|
||||
use Auth\Group;
|
||||
|
@ -224,6 +228,20 @@ final class RepositoriesProvider extends ServiceProvider
|
|||
}
|
||||
);
|
||||
|
||||
App::singleton(
|
||||
IDisqusSSOProfileRepository::class,
|
||||
function(){
|
||||
return EntityManager::getRepository(DisqusSSOProfile::class);
|
||||
}
|
||||
);
|
||||
|
||||
App::singleton(
|
||||
IRocketChatSSOProfileRepository::class,
|
||||
function(){
|
||||
return EntityManager::getRepository(RocketChatSSOProfile::class);
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
public function provides()
|
||||
|
@ -246,6 +264,8 @@ final class RepositoriesProvider extends ServiceProvider
|
|||
IWhiteListedIPRepository::class,
|
||||
IUserRegistrationRequestRepository::class,
|
||||
ISpamEstimatorFeedRepository::class,
|
||||
IDisqusSSOProfileRepository::class,
|
||||
IRocketChatSSOProfileRepository::class,
|
||||
];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
<?php namespace App\Services\Apis;
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
|
||||
/**
|
||||
* Interface IRocketChatAPI
|
||||
* @package App\Services\Apis
|
||||
*/
|
||||
interface IRocketChatAPI
|
||||
{
|
||||
/**
|
||||
* @param string $base_url
|
||||
* @return IRocketChatAPI
|
||||
*/
|
||||
public function setBaseUrl(string $base_url):IRocketChatAPI;
|
||||
|
||||
/**
|
||||
* @param string $service_name
|
||||
* @return array
|
||||
*/
|
||||
public function login(string $service_name):array;
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
<?php namespace App\Services\Apis;
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
use GuzzleHttp\Client;
|
||||
use Exception;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use models\exceptions\ValidationException;
|
||||
use OAuth2\IResourceServerContext;
|
||||
/**
|
||||
* Class RocketChatAPI
|
||||
* @package App\Services\Apis
|
||||
*/
|
||||
final class RocketChatAPI implements IRocketChatAPI
|
||||
{
|
||||
|
||||
/**
|
||||
* @var IResourceServerContext
|
||||
*/
|
||||
private $resource_server_context;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $base_url;
|
||||
|
||||
/**
|
||||
* RocketChatAPI constructor.
|
||||
* @param IResourceServerContext $resource_server_context
|
||||
*/
|
||||
public function __construct(IResourceServerContext $resource_server_context)
|
||||
{
|
||||
$this->resource_server_context = $resource_server_context;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $service_name
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function login(string $service_name): array
|
||||
{
|
||||
try {
|
||||
$client = new Client();
|
||||
$endpoint = sprintf("%s/api/v1/login", $this->base_url);
|
||||
|
||||
$payload = [
|
||||
'serviceName' => $service_name,
|
||||
'accessToken' => $this->resource_server_context->getCurrentAccessToken(),
|
||||
"expiresIn" => 3600
|
||||
];
|
||||
|
||||
$response = $client->post($endpoint, [
|
||||
'json' => $payload
|
||||
]);
|
||||
|
||||
$json = $response->getBody()->getContents();
|
||||
return json_decode($json, true);
|
||||
}
|
||||
catch (ClientException $ex){
|
||||
Log::error($ex->getMessage());
|
||||
throw new ValidationException($ex->getMessage());
|
||||
}
|
||||
catch(Exception $ex){
|
||||
Log::error($ex->getMessage());
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $base_url
|
||||
* @return IRocketChatAPI
|
||||
*/
|
||||
public function setBaseUrl(string $base_url): IRocketChatAPI
|
||||
{
|
||||
$this->base_url = $base_url;
|
||||
return $this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
<?php namespace App\Services\Auth;
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
use App\Models\Repositories\IDisqusSSOProfileRepository;
|
||||
use App\Models\SSO\Disqus\DisqusUserProfile;
|
||||
use App\Services\AbstractService;
|
||||
use Auth\Repositories\IUserRepository;
|
||||
use Auth\User;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use models\exceptions\EntityNotFoundException;
|
||||
use models\exceptions\ValidationException;
|
||||
use models\utils\IEntity;
|
||||
use OAuth2\IResourceServerContext;
|
||||
use Utils\Db\ITransactionService;
|
||||
/**
|
||||
* Class DisqusSSOService
|
||||
* @package App\Services\Auth
|
||||
*/
|
||||
final class DisqusSSOService extends AbstractService implements IDisqusSSOService
|
||||
{
|
||||
|
||||
/**
|
||||
* @var IDisqusSSOProfileRepository
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* @var IResourceServerContext
|
||||
*/
|
||||
private $resource_server_context;
|
||||
|
||||
/**
|
||||
* @var IUserRepository
|
||||
*/
|
||||
private $user_repository;
|
||||
|
||||
/**
|
||||
* DisqusSSOService constructor.
|
||||
* @param IResourceServerContext $resource_server_context
|
||||
* @param IUserRepository $user_repository
|
||||
* @param IDisqusSSOProfileRepository $repository
|
||||
* @param ITransactionService $tx_service
|
||||
*/
|
||||
public function __construct
|
||||
(
|
||||
|
||||
IResourceServerContext $resource_server_context,
|
||||
IUserRepository $user_repository,
|
||||
IDisqusSSOProfileRepository $repository,
|
||||
ITransactionService $tx_service
|
||||
)
|
||||
{
|
||||
parent::__construct($tx_service);
|
||||
$this->repository = $repository;
|
||||
$this->user_repository = $user_repository;
|
||||
$this->resource_server_context = $resource_server_context;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function create(array $payload): IEntity
|
||||
{
|
||||
// TODO: Implement create() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function update(int $id, array $payload): IEntity
|
||||
{
|
||||
// TODO: Implement update() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function delete(int $id): void
|
||||
{
|
||||
// TODO: Implement delete() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $forum_slug
|
||||
* @return DisqusUserProfile|null
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getUserProfile(string $forum_slug): ?DisqusUserProfile
|
||||
{
|
||||
return $this->tx_service->transaction(function() use($forum_slug){
|
||||
|
||||
Log::debug("DisqusSSOService::getUserProfile");
|
||||
$current_user_id = $this->resource_server_context->getCurrentUserId();
|
||||
|
||||
Log::debug(sprintf("DisqusSSOService::getUserProfile current_user_id %s", $current_user_id));
|
||||
if (is_null($current_user_id)) {
|
||||
throw new ValidationException('me is no set!.');
|
||||
}
|
||||
|
||||
$current_user = $this->user_repository->getById($current_user_id);
|
||||
if(is_null($current_user)) throw new EntityNotFoundException();
|
||||
|
||||
if(!$current_user instanceof User) throw new EntityNotFoundException();
|
||||
$sso_profile = $this->repository->getByForumSlug($forum_slug);
|
||||
if(is_null($sso_profile)){
|
||||
throw new EntityNotFoundException("Forum not found");
|
||||
}
|
||||
|
||||
return new DisqusUserProfile($sso_profile, $current_user);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php namespace App\Services\Auth;
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
use App\Models\SSO\Disqus\DisqusUserProfile;
|
||||
use App\Services\IBaseService;
|
||||
use models\exceptions\EntityNotFoundException;
|
||||
|
||||
/**
|
||||
* Interface IDisqusSSOService
|
||||
* @package App\Services\Auth
|
||||
*/
|
||||
interface IDisqusSSOService extends IBaseService
|
||||
{
|
||||
/**
|
||||
* @param string $forum_slug
|
||||
* @return DisqusUserProfile|null
|
||||
* @throws EntityNotFoundException
|
||||
*/
|
||||
public function getUserProfile(string $forum_slug):?DisqusUserProfile;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
<?php namespace App\Services\Auth;
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
use App\Models\SSO\RocketChatUserProfile;
|
||||
use App\Services\IBaseService;
|
||||
use models\exceptions\EntityNotFoundException;
|
||||
/**
|
||||
* Interface IRocketChatSSOService
|
||||
* @package App\Services\Auth
|
||||
*/
|
||||
interface IRocketChatSSOService extends IBaseService
|
||||
{
|
||||
/**
|
||||
* @param string $forum_slug
|
||||
* @return RocketChatUserProfile|null
|
||||
* @throws EntityNotFoundException
|
||||
*/
|
||||
public function getUserProfile(string $forum_slug):?RocketChatUserProfile;
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
<?php namespace App\Services\Auth;
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
use App\Models\Repositories\IRocketChatSSOProfileRepository;
|
||||
use App\Models\SSO\RocketChatUserProfile;
|
||||
use App\Services\AbstractService;
|
||||
use App\Services\Apis\IRocketChatAPI;
|
||||
use Auth\Repositories\IUserRepository;
|
||||
use Auth\User;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use models\exceptions\EntityNotFoundException;
|
||||
use models\exceptions\ValidationException;
|
||||
use models\utils\IEntity;
|
||||
use OAuth2\IResourceServerContext;
|
||||
use Utils\Db\ITransactionService;
|
||||
/**
|
||||
* Class RocketChatSSOService
|
||||
* @package App\Services\Auth
|
||||
*/
|
||||
final class RocketChatSSOService extends AbstractService implements IRocketChatSSOService
|
||||
{
|
||||
|
||||
/**
|
||||
* @var IRocketChatSSOProfileRepository
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* @var IResourceServerContext
|
||||
*/
|
||||
private $resource_server_context;
|
||||
|
||||
/**
|
||||
* @var IUserRepository
|
||||
*/
|
||||
private $user_repository;
|
||||
|
||||
/**
|
||||
* @var IRocketChatAPI
|
||||
*/
|
||||
private $rocket_chat_api;
|
||||
|
||||
/**
|
||||
* RocketChatSSOService constructor.
|
||||
* @param IResourceServerContext $resource_server_context
|
||||
* @param IUserRepository $user_repository
|
||||
* @param IRocketChatSSOProfileRepository $repository
|
||||
* @param IRocketChatAPI $rocket_chat_api
|
||||
* @param ITransactionService $tx_service
|
||||
*/
|
||||
public function __construct
|
||||
(
|
||||
IResourceServerContext $resource_server_context,
|
||||
IUserRepository $user_repository,
|
||||
IRocketChatSSOProfileRepository $repository,
|
||||
IRocketChatAPI $rocket_chat_api,
|
||||
ITransactionService $tx_service
|
||||
)
|
||||
{
|
||||
parent::__construct($tx_service);
|
||||
$this->repository = $repository;
|
||||
$this->user_repository = $user_repository;
|
||||
$this->resource_server_context = $resource_server_context;
|
||||
$this->rocket_chat_api = $rocket_chat_api;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function create(array $payload): IEntity
|
||||
{
|
||||
// TODO: Implement create() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function update(int $id, array $payload): IEntity
|
||||
{
|
||||
// TODO: Implement update() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function delete(int $id): void
|
||||
{
|
||||
// TODO: Implement delete() method.
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $forum_slug
|
||||
* @return RocketChatUserProfile|null
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getUserProfile(string $forum_slug): ?RocketChatUserProfile
|
||||
{
|
||||
return $this->tx_service->transaction(function() use($forum_slug){
|
||||
|
||||
Log::debug("RocketChatSSOService::getUserProfile");
|
||||
$current_user_id = $this->resource_server_context->getCurrentUserId();
|
||||
$access_token = $this->resource_server_context->getCurrentAccessToken();
|
||||
if(empty($access_token)){
|
||||
throw new ValidationException("Access Token is empty.");
|
||||
}
|
||||
Log::debug(sprintf("RocketChatSSOService::getUserProfile current_user_id %s", $current_user_id));
|
||||
if (is_null($current_user_id)) {
|
||||
throw new ValidationException('me is no set!.');
|
||||
}
|
||||
|
||||
$current_user = $this->user_repository->getById($current_user_id);
|
||||
if(is_null($current_user)) throw new EntityNotFoundException();
|
||||
|
||||
if(!$current_user instanceof User) throw new EntityNotFoundException();
|
||||
$sso_profile = $this->repository->getByForumSlug($forum_slug);
|
||||
if(is_null($sso_profile)){
|
||||
throw new EntityNotFoundException("Forum not found");
|
||||
}
|
||||
|
||||
return new RocketChatUserProfile
|
||||
(
|
||||
$this->rocket_chat_api->setBaseUrl($sso_profile->getBaseUrl())->login($sso_profile->getServiceName())
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ use App\ModelSerializers\SerializerRegistry;
|
|||
use Auth\Repositories\IUserRepository;
|
||||
use Auth\User;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use jwt\impl\JWTClaimSet;
|
||||
use jwt\JWTClaim;
|
||||
use OAuth2\AddressClaim;
|
||||
|
@ -102,9 +103,10 @@ final class UserService extends OAuth2ProtectedService implements IUserService
|
|||
$data = [];
|
||||
try
|
||||
{
|
||||
|
||||
Log::debug("UserService::getCurrentUserInfo");
|
||||
$current_user_id = $this->resource_server_context->getCurrentUserId();
|
||||
|
||||
Log::debug(sprintf("UserService::getCurrentUserInfo current_user_id %s", $current_user_id));
|
||||
if (is_null($current_user_id)) {
|
||||
throw new Exception('me is no set!.');
|
||||
}
|
||||
|
@ -114,10 +116,11 @@ final class UserService extends OAuth2ProtectedService implements IUserService
|
|||
|
||||
if(!$current_user instanceof User) throw new EntityNotFoundException();
|
||||
|
||||
$scopes = $this->resource_server_context->getCurrentScope();
|
||||
$scopes = $this->resource_server_context->getCurrentScope();
|
||||
|
||||
if (in_array(self::UserProfileScope_Address, $scopes)) {
|
||||
// Address Claims
|
||||
Log::debug(sprintf("UserService::getCurrentUserInfo current_user_id %s address", $current_user_id));
|
||||
$data[AddressClaim::Country] = $current_user->getCountry();
|
||||
$data[AddressClaim::StreetAddress] = $current_user->getCountry();
|
||||
$data[AddressClaim::PostalCode] = $current_user->getPostalCode();
|
||||
|
@ -125,6 +128,7 @@ final class UserService extends OAuth2ProtectedService implements IUserService
|
|||
$data[AddressClaim::Locality] = $current_user->getLocality();
|
||||
}
|
||||
if (in_array(self::UserProfileScope_Profile, $scopes)) {
|
||||
Log::debug(sprintf("UserService::getCurrentUserInfo current_user_id %s profile", $current_user_id));
|
||||
// Profile Claims
|
||||
$data[StandardClaims::Name] = $current_user->getFullName();
|
||||
$data[StandardClaims::GivenName] = $current_user->getFirstName();
|
||||
|
@ -152,6 +156,7 @@ final class UserService extends OAuth2ProtectedService implements IUserService
|
|||
$data[StandardClaims::Groups] = $user_groups;
|
||||
}
|
||||
if (in_array(self::UserProfileScope_Email, $scopes)) {
|
||||
Log::debug(sprintf("UserService::getCurrentUserInfo current_user_id %s email", $current_user_id));
|
||||
// Email Claim
|
||||
$data[StandardClaims::Email] = $current_user->getEmail();
|
||||
$data[StandardClaims::SecondEmail] = $current_user->getSecondEmail();
|
||||
|
|
|
@ -11,11 +11,16 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
use App\libs\Auth\Repositories\IUserExceptionTrailRepository;
|
||||
use App\Services\Apis\IRocketChatAPI;
|
||||
use App\Services\Apis\RocketChatAPI;
|
||||
use App\Services\Auth\DisqusSSOService;
|
||||
use App\Services\Auth\GroupService;
|
||||
use App\Services\Auth\IDisqusSSOService;
|
||||
use App\Services\Auth\IGroupService;
|
||||
use App\Services\Auth\IRocketChatSSOService;
|
||||
use App\Services\Auth\IUserService;
|
||||
use App\Services\Auth\RocketChatSSOService;
|
||||
use App\Services\Auth\UserService;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Services\SecurityPolicies\AuthorizationCodeRedeemPolicy;
|
||||
|
@ -84,12 +89,15 @@ final class ServicesProvider extends ServiceProvider
|
|||
|
||||
App::singleton(IUserService::class, UserService::class);
|
||||
App::singleton(IGroupService::class, GroupService::class);
|
||||
App::singleton(IDisqusSSOService::class, DisqusSSOService::class);
|
||||
App::singleton(IRocketChatSSOService::class, RocketChatSSOService::class);
|
||||
App::singleton(IRocketChatAPI::class, RocketChatAPI::class);
|
||||
}
|
||||
|
||||
public function provides()
|
||||
{
|
||||
return [
|
||||
\Services\IUserActionService::class,
|
||||
IUserActionService::class,
|
||||
\Services\SecurityPolicies\DelayCounterMeasure::class,
|
||||
\Services\SecurityPolicies\LockUserCounterMeasure::class,
|
||||
\Services\SecurityPolicies\RevokeAuthorizationCodeRelatedTokens::class,
|
||||
|
@ -100,6 +108,9 @@ final class ServicesProvider extends ServiceProvider
|
|||
AuthorizationCodeRedeemPolicy::class,
|
||||
UtilsServiceCatalog::CheckPointService,
|
||||
IUserService::class,
|
||||
IDisqusSSOService::class,
|
||||
IRocketChatSSOService::class,
|
||||
IRocketChatAPI::class,
|
||||
];
|
||||
}
|
||||
}
|
|
@ -25,5 +25,6 @@ interface IUserScopes
|
|||
const Address = 'address';
|
||||
const Registration = 'user-registration';
|
||||
const ReadAll = 'users-read-all';
|
||||
const SSO = 'sso';
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
<?php namespace Database\Migrations;
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
use Doctrine\DBAL\Schema\Schema as Schema;
|
||||
use LaravelDoctrine\Migrations\Schema\Builder;
|
||||
use LaravelDoctrine\Migrations\Schema\Table;
|
||||
/**
|
||||
* Class Version20200528175450
|
||||
* @package Database\Migrations
|
||||
*/
|
||||
class Version20200528175450 extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* @param Schema $schema
|
||||
*/
|
||||
public function up(Schema $schema)
|
||||
{
|
||||
$builder = new Builder($schema);
|
||||
|
||||
if (!$builder->hasTable("sso_disqus_profile")) {
|
||||
$builder->create("sso_disqus_profile", function (Table $table) {
|
||||
$table->increments('id');
|
||||
$table->timestamps();
|
||||
$table->string("forum_slug")->setNotnull(true);
|
||||
$table->string("public_key")->setNotnull(true);
|
||||
$table->string("secret_key")->setNotnull(true);
|
||||
$table->unique("forum_slug");
|
||||
});
|
||||
}
|
||||
|
||||
if (!$builder->hasTable("sso_rocket_chat_profile")) {
|
||||
$builder->create("sso_rocket_chat_profile", function (Table $table) {
|
||||
$table->increments('id');
|
||||
$table->timestamps();
|
||||
$table->string("forum_slug")->setNotnull(true);
|
||||
$table->string("base_url")->setNotnull(true);
|
||||
$table->string("service_name")->setNotnull(true);
|
||||
$table->unique("forum_slug");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Schema $schema
|
||||
*/
|
||||
public function down(Schema $schema)
|
||||
{
|
||||
$builder = new Builder($schema);
|
||||
|
||||
$builder->dropIfExists("sso_disqus_profile");
|
||||
|
||||
$builder->dropIfExists("sso_rocket_chat_profile");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
<?php namespace Database\Migrations;
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
use App\libs\OAuth2\IUserScopes;
|
||||
use Doctrine\Migrations\AbstractMigration;
|
||||
use Doctrine\DBAL\Schema\Schema as Schema;
|
||||
use SeedUtils;
|
||||
/**
|
||||
* Class Version20200530150357
|
||||
* @package Database\Migrations
|
||||
*/
|
||||
class Version20200530150357 extends AbstractMigration
|
||||
{
|
||||
/**
|
||||
* @param Schema $schema
|
||||
*/
|
||||
public function up(Schema $schema)
|
||||
{
|
||||
if(!SeedUtils::seedApi("sso", "SSO Integration API")) return;
|
||||
|
||||
SeedUtils::seedScopes([
|
||||
[
|
||||
'name' => IUserScopes::SSO,
|
||||
'short_description' => 'Allows SSO integration',
|
||||
'description' => 'Allows SSO integration',
|
||||
'system' => false,
|
||||
'default' => false,
|
||||
'groups' => true,
|
||||
],
|
||||
|
||||
], 'sso');
|
||||
|
||||
SeedUtils::seedApiEndpoints('sso', [
|
||||
[
|
||||
'name' => 'sso-disqus',
|
||||
'active' => true,
|
||||
'route' => '/api/v1/sso/disqus/{forum_slug}/profile',
|
||||
'http_method' => 'GET',
|
||||
'scopes' => [
|
||||
\App\libs\OAuth2\IUserScopes::SSO
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'sso-rocket-chat',
|
||||
'active' => true,
|
||||
'route' => '/api/v1/sso/rocket-chat/{forum_slug}/profile',
|
||||
'http_method' => 'GET',
|
||||
'scopes' => [
|
||||
\App\libs\OAuth2\IUserScopes::SSO
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Schema $schema
|
||||
*/
|
||||
public function down(Schema $schema)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ class ApiEndpointSeeder extends Seeder
|
|||
DB::table('oauth2_api_endpoint')->delete();
|
||||
$this->seedUsersEndpoints();
|
||||
$this->seedRegistrationEndpoints();
|
||||
$this->seedSSOEndpoints();
|
||||
}
|
||||
|
||||
|
||||
|
@ -92,4 +93,27 @@ class ApiEndpointSeeder extends Seeder
|
|||
]);
|
||||
}
|
||||
|
||||
private function seedSSOEndpoints(){
|
||||
SeedUtils::seedApiEndpoints('sso', [
|
||||
[
|
||||
'name' => 'sso-disqus',
|
||||
'active' => true,
|
||||
'route' => '/api/v1/sso/disqus/{forum_slug}/profile',
|
||||
'http_method' => 'GET',
|
||||
'scopes' => [
|
||||
\App\libs\OAuth2\IUserScopes::SSO
|
||||
],
|
||||
],
|
||||
[
|
||||
'name' => 'sso-rocket-chat',
|
||||
'active' => true,
|
||||
'route' => '/api/v1/sso/rocket-chat/{forum_slug}/profile',
|
||||
'http_method' => 'GET',
|
||||
'scopes' => [
|
||||
\App\libs\OAuth2\IUserScopes::SSO
|
||||
],
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
|
@ -30,6 +30,7 @@ class ApiScopeSeeder extends Seeder {
|
|||
DB::table('oauth2_api_scope')->delete();
|
||||
$this->seedUsersScopes();
|
||||
$this->seedRegistrationScopes();
|
||||
$this->seedSSOScopes();
|
||||
}
|
||||
|
||||
|
||||
|
@ -99,6 +100,19 @@ class ApiScopeSeeder extends Seeder {
|
|||
],
|
||||
|
||||
], 'user-registration');
|
||||
}
|
||||
|
||||
private function seedSSOScopes(){
|
||||
SeedUtils::seedScopes([
|
||||
[
|
||||
'name' => IUserScopes::SSO,
|
||||
'short_description' => 'Allows SSO integration',
|
||||
'description' => 'Allows SSO integration',
|
||||
'system' => false,
|
||||
'default' => false,
|
||||
'groups' => true,
|
||||
],
|
||||
|
||||
], 'sso');
|
||||
}
|
||||
}
|
|
@ -52,5 +52,15 @@ class ApiSeeder extends Seeder {
|
|||
EntityManager::persist($api);
|
||||
|
||||
EntityManager::flush();
|
||||
|
||||
$api = new Api();
|
||||
$api->setName('sso');
|
||||
$api->setActive(true);
|
||||
$api->setDescription('SSO Integration API');
|
||||
$api->setResourceServer($rs);
|
||||
|
||||
EntityManager::persist($api);
|
||||
|
||||
EntityManager::flush();
|
||||
}
|
||||
}
|
|
@ -16,11 +16,34 @@ use Models\OAuth2\ApiEndpoint;
|
|||
use Models\OAuth2\ApiScope;
|
||||
use Models\OAuth2\Api;
|
||||
use LaravelDoctrine\ORM\Facades\EntityManager;
|
||||
use Models\OAuth2\ResourceServer;
|
||||
/**
|
||||
* Class SeedUtils
|
||||
*/
|
||||
final class SeedUtils
|
||||
{
|
||||
/**
|
||||
* @param string $api_name
|
||||
* @param string $api_description
|
||||
* @return bool
|
||||
*/
|
||||
public static function seedApi(string $api_name, string $api_description){
|
||||
$resource_server_repository = EntityManager::getRepository(ResourceServer::class);
|
||||
$rs = $resource_server_repository->find(1);
|
||||
if(is_null($rs)) return false;
|
||||
$api = new Api();
|
||||
$api->setName($api_name);
|
||||
$api->setActive(true);
|
||||
$api->setDescription($api_description);
|
||||
$api->setResourceServer($rs);
|
||||
|
||||
EntityManager::persist($api);
|
||||
|
||||
EntityManager::flush();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $api_name
|
||||
* @param array $endpoints_info
|
||||
|
|
|
@ -418,6 +418,7 @@ PPK;
|
|||
$this->seedApiScopeScopes();
|
||||
$this->seedUsersScopes();
|
||||
$this->seedUsersRegistrationScopes();
|
||||
$this->seedSSOScopes();
|
||||
$this->seedPublicCloudScopes();
|
||||
$this->seedPrivateCloudScopes();
|
||||
$this->seedConsultantScopes();
|
||||
|
@ -427,6 +428,7 @@ PPK;
|
|||
$this->seedApiEndpoints();
|
||||
$this->seedUsersEndpoints();
|
||||
$this->seedUserRegistrationEndpoints();
|
||||
$this->seedSSOEndpoints();
|
||||
/*
|
||||
$this->seedApiEndpointEndpoints();
|
||||
$this->seedScopeEndpoints();
|
||||
|
@ -669,6 +671,13 @@ PPK;
|
|||
'resource_server' => $resource_server,
|
||||
'logo' => asset('/assets/img/apis/server.png')
|
||||
),
|
||||
array(
|
||||
'name' => 'sso',
|
||||
'active' => true,
|
||||
'description' => 'SSO Integration',
|
||||
'resource_server' => $resource_server,
|
||||
'logo' => asset('/assets/img/apis/server.png')
|
||||
),
|
||||
array(
|
||||
'name' => 'public-clouds',
|
||||
'active' => true,
|
||||
|
@ -1405,6 +1414,31 @@ PPK;
|
|||
EntityManager::flush();
|
||||
}
|
||||
|
||||
private function seedSSOScopes(){
|
||||
|
||||
$api_repository = EntityManager::getRepository(Api::class);
|
||||
$api = $api_repository->findOneBy(['name' => 'sso']);
|
||||
|
||||
$current_realm = Config::get('app.url');
|
||||
|
||||
|
||||
$api_scope_payloads = [
|
||||
array(
|
||||
'name' => IUserScopes::SSO,
|
||||
'short_description' => 'Allows SSO integration',
|
||||
'description' => 'Allows SSO integration',
|
||||
'api' => $api,
|
||||
'system' => false,
|
||||
'active' => true,
|
||||
),
|
||||
];
|
||||
|
||||
foreach($api_scope_payloads as $payload) {
|
||||
EntityManager::persist(ApiScopeFactory::build($payload));
|
||||
}
|
||||
EntityManager::flush();
|
||||
}
|
||||
|
||||
private function seedPublicCloudScopes(){
|
||||
|
||||
$api_repository = EntityManager::getRepository(Api::class);
|
||||
|
@ -1688,6 +1722,46 @@ PPK;
|
|||
EntityManager::flush();
|
||||
}
|
||||
|
||||
private function seedSSOEndpoints(){
|
||||
$api_repository = EntityManager::getRepository(Api::class);
|
||||
$endpoint_repository = EntityManager::getRepository(ApiEndpoint::class);
|
||||
$api = $api_repository->findOneBy(['name' => 'sso']);
|
||||
|
||||
$api_scope_payloads = [
|
||||
array(
|
||||
'name' => 'sso-disqus',
|
||||
'active' => true,
|
||||
'api' => $api,
|
||||
'route' => '/api/v1/sso/disqus/{forum_slug}/profile',
|
||||
'http_method' => 'GET'
|
||||
),
|
||||
|
||||
array(
|
||||
'name' => 'sso-rocket-chat',
|
||||
'active' => true,
|
||||
'api' => $api,
|
||||
'route' => '/api/v1/sso/rocket-chat/{forum_slug}/profile',
|
||||
'http_method' => 'GET'
|
||||
),
|
||||
];
|
||||
|
||||
foreach($api_scope_payloads as $payload) {
|
||||
EntityManager::persist(ApiEndpointFactory::build($payload));
|
||||
}
|
||||
EntityManager::flush();
|
||||
|
||||
$api_scope_repository = EntityManager::getRepository(ApiScope::class);
|
||||
$scope = $api_scope_repository->findOneBy(['name' => \App\libs\OAuth2\IUserScopes::SSO]);
|
||||
|
||||
foreach($api_scope_payloads as $payload) {
|
||||
$endpoint = $endpoint_repository->findOneBy(['name' => $payload['name']]);
|
||||
$endpoint->addScope($scope);
|
||||
EntityManager::persist($endpoint);
|
||||
}
|
||||
|
||||
EntityManager::flush();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
private function seedApiEndpointEndpoints(){
|
||||
|
|
|
@ -34,7 +34,7 @@ abstract class BrowserKitTestCase extends BaseTestCase
|
|||
*/
|
||||
protected $baseUrl = 'http://localhost';
|
||||
|
||||
public function setUp()
|
||||
protected function setUp()
|
||||
{
|
||||
parent::setUp(); // Don't forget this!
|
||||
$this->redis = Redis::connection();
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
<?php
|
||||
/**
|
||||
* Copyright 2020 OpenStack Foundation
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
use LaravelDoctrine\ORM\Facades\EntityManager;
|
||||
use LaravelDoctrine\ORM\Facades\Registry;
|
||||
use Doctrine\Common\Persistence\ObjectRepository;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Models\SSO\DisqusSSOProfile;
|
||||
use App\Models\Utils\BaseEntity;
|
||||
use App\Models\SSO\RocketChatSSOProfile;
|
||||
/**
|
||||
* Class OAuthSSOApiControllerTest
|
||||
*/
|
||||
final class OAuthSSOApiControllerTest extends OAuth2ProtectedApiTest
|
||||
{
|
||||
/**
|
||||
* @var EntityManager
|
||||
*/
|
||||
static $em;
|
||||
|
||||
/**
|
||||
* @var ObjectRepository
|
||||
*/
|
||||
static $disqus_repository;
|
||||
|
||||
/**
|
||||
* @var ObjectRepository
|
||||
*/
|
||||
static $rocket_chat_repository;
|
||||
|
||||
/**
|
||||
* @var DisqusSSOProfile
|
||||
*/
|
||||
static $disqus_profile;
|
||||
|
||||
/**
|
||||
* @var RocketChatSSOProfile
|
||||
*/
|
||||
static $rocket_chat_profile;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
DB::table("sso_disqus_profile")->delete();
|
||||
DB::table("sso_rocket_chat_profile")->delete();
|
||||
|
||||
self::$disqus_repository = EntityManager::getRepository(DisqusSSOProfile::class);
|
||||
self::$rocket_chat_repository = EntityManager::getRepository(RocketChatSSOProfile::class);
|
||||
|
||||
self::$disqus_profile = new DisqusSSOProfile();
|
||||
self::$disqus_profile->setForumSlug("poc_disqus");
|
||||
self::$disqus_profile->setPublicKey("PUBLIC_KEY");
|
||||
self::$disqus_profile->setSecretKey("SECRET_KEY");
|
||||
|
||||
self::$rocket_chat_profile = new RocketChatSSOProfile();
|
||||
self::$rocket_chat_profile->setForumSlug("poc_rocket_chat");
|
||||
self::$rocket_chat_profile->setBaseUrl("https://rocket-chat.dev.fnopen.com");
|
||||
self::$rocket_chat_profile->setServiceName("fnid");
|
||||
|
||||
self::$em = Registry::getManager(BaseEntity::EntityManager);
|
||||
if (!self::$em ->isOpen()) {
|
||||
self::$em = Registry::resetManager(BaseEntity::EntityManager);
|
||||
}
|
||||
self::$em->persist(self::$disqus_profile);
|
||||
self::$em->persist(self::$rocket_chat_profile);
|
||||
self::$em->flush();
|
||||
|
||||
}
|
||||
|
||||
protected function tearDown()
|
||||
{
|
||||
self::$em = Registry::resetManager(BaseEntity::EntityManager);
|
||||
self::$disqus_profile = self::$disqus_repository->find(self::$disqus_profile->getId());
|
||||
self::$em->remove(self::$disqus_profile);
|
||||
self::$em->flush();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function testDisqusGetUserProfile(){
|
||||
|
||||
$params = [
|
||||
"forum_slug" => self::$disqus_profile->getForumSlug()
|
||||
];
|
||||
|
||||
$headers = [
|
||||
"HTTP_Authorization" => " Bearer " . $this->access_token,
|
||||
"CONTENT_TYPE" => "application/json"
|
||||
];
|
||||
|
||||
$response = $this->action
|
||||
(
|
||||
"GET",
|
||||
"Api\\OAuth2\\OAuth2DisqusSSOApiController@getUserProfile",
|
||||
$params,
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
$headers
|
||||
);
|
||||
|
||||
$this->assertResponseStatus(200);
|
||||
$content = $response->getContent();
|
||||
$profile = json_decode($content);
|
||||
|
||||
$this->assertTrue(!empty($profile->auth));
|
||||
$this->assertTrue(!empty($profile->public_key));
|
||||
$this->assertTrue($profile->public_key == self::$disqus_profile->getPublicKey());
|
||||
}
|
||||
|
||||
public function testRocketGetUserProfileFails(){
|
||||
|
||||
$params = [
|
||||
"forum_slug" => self::$rocket_chat_profile->getForumSlug()
|
||||
];
|
||||
|
||||
$headers = [
|
||||
"HTTP_Authorization" => " Bearer " . $this->access_token,
|
||||
"CONTENT_TYPE" => "application/json"
|
||||
];
|
||||
|
||||
$response = $this->action
|
||||
(
|
||||
"GET",
|
||||
"Api\\OAuth2\\OAuth2RocketChatSSOApiController@getUserProfile",
|
||||
$params,
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
$headers
|
||||
);
|
||||
|
||||
$this->assertResponseStatus(412);
|
||||
$content = $response->getContent();
|
||||
}
|
||||
|
||||
protected function getScopes()
|
||||
{
|
||||
$scope = array(
|
||||
\App\libs\OAuth2\IUserScopes::SSO
|
||||
);
|
||||
|
||||
return $scope;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue