Implements: blueprint oauth2-openid-refresh-tokens-administration

[smarcet] - #5036 - Refresh Tokens Administration

Change-Id: I14a9ed2f060d5681aa6362bd11e0c879b438a31e
This commit is contained in:
smarcet 2014-01-20 18:15:38 -03:00
parent 89bc75eb8c
commit 5ac8ac455a
27 changed files with 882 additions and 544 deletions

View File

@ -15,8 +15,8 @@ class HomeController extends BaseController
{
//This field contains a semicolon-separated list of representation schemes
//which will be accepted in the response to this request.
$accept = Request::header('Accept');
$accept_values = explode(",", $accept);
$accept = Request::header('Accept');
$accept_values = explode(",", $accept);
if (in_array(XRDSDocumentBuilder::ContentType, $accept_values))
return $this->discovery->idp();
if (Auth::guest())

View File

@ -1,9 +1,10 @@
<?php
use oauth2\exceptions\AllowedClientUriAlreadyExistsException;
use oauth2\services\IApiScopeService;
use oauth2\services\IClientService;
use oauth2\services\IMementoOAuth2AuthenticationRequestService;
use oauth2\exceptions\AllowedClientUriAlreadyExistsException;
use oauth2\services\ITokenService;
use openid\requests\OpenIdAuthenticationRequest;
use openid\services\IMementoOpenIdRequestService;
use openid\services\IServerConfigurationService;
@ -19,7 +20,6 @@ use strategies\OpenIdConsentStrategy;
use strategies\OpenIdLoginStrategy;
use utils\services\IAuthService;
class UserController extends BaseController
{
@ -34,6 +34,7 @@ class UserController extends BaseController
private $consent_strategy;
private $client_service;
private $scope_service;
private $token_service;
public function __construct(IMementoOpenIdRequestService $openid_memento_service,
IMementoOAuth2AuthenticationRequestService $oauth2_memento_service,
@ -44,7 +45,8 @@ class UserController extends BaseController
IUserService $user_service,
IUserActionService $user_action_service,
IClientService $client_service,
IApiScopeService $scope_service)
IApiScopeService $scope_service,
ITokenService $token_service)
{
$this->openid_memento_service = $openid_memento_service;
$this->oauth2_memento_service = $oauth2_memento_service;
@ -56,6 +58,7 @@ class UserController extends BaseController
$this->user_action_service = $user_action_service;
$this->client_service = $client_service;
$this->scope_service = $scope_service;
$this->token_service = $token_service;
//filters
$this->beforeFilter('csrf', array('only' => array('postLogin', 'postConsent')));
@ -89,15 +92,15 @@ class UserController extends BaseController
'postUseRefreshTokenClient',
'postRotateRefreshTokenPolicy')));
$this->beforeFilter('ajax', array('only' => array(
'postAddAllowedScope',
'getRegenerateClientSecret',
'getDeleteClientAllowedUri',
'postAddAllowedRedirectUri',
'getRegisteredClientUris',
'postActivateClient',
'postUseRefreshTokenClient',
'postRotateRefreshTokenPolicy')));
$this->beforeFilter('ajax', array('only' => array(
'postAddAllowedScope',
'getRegenerateClientSecret',
'getDeleteClientAllowedUri',
'postAddAllowedRedirectUri',
'getRegisteredClientUris',
'postActivateClient',
'postUseRefreshTokenClient',
'postRotateRefreshTokenPolicy')));
}
@ -115,7 +118,7 @@ class UserController extends BaseController
{
try {
$max_login_attempts_2_show_captcha = $this->server_configuration_service->getConfigValue("MaxFailed.LoginAttempts.2ShowCaptcha");
$data = Input::all();
$data = Input::all();
$login_attempts = intval(Input::get('login_attempts'));
// Build the validation constraint set.
$rules = array(
@ -200,13 +203,13 @@ class UserController extends BaseController
}
$params = array(
'show_fullname' => $user->getShowProfileFullName(),
'username' => $user->getFullName(),
'show_email' => $user->getShowProfileEmail(),
'email' => $user->getEmail(),
'identifier' => $user->getIdentifier(),
'show_pic' => $user->getShowProfilePic(),
'pic' => $user->getPic(),
'another_user' => $another_user,
'username' => $user->getFullName(),
'show_email' => $user->getShowProfileEmail(),
'email' => $user->getEmail(),
'identifier' => $user->getIdentifier(),
'show_pic' => $user->getShowProfilePic(),
'pic' => $user->getPic(),
'another_user' => $another_user,
);
return View::make("identity", $params);
} catch (Exception $ex) {
@ -224,21 +227,21 @@ class UserController extends BaseController
public function getProfile()
{
$user = $this->auth_service->getCurrentUser();
$sites = $this->trusted_sites_service->getAllTrustedSitesByUser($user);
$user = $this->auth_service->getCurrentUser();
$sites = $this->trusted_sites_service->getAllTrustedSitesByUser($user);
$actions = $user->getActions();
$clients = $user->getClients();
return View::make("profile", array(
"username" => $user->getFullName(),
"openid_url" => $this->server_configuration_service->getUserIdentityEndpointURL($user->getIdentifier()),
"identifier " => $user->getIdentifier(),
"sites" => $sites,
"show_pic" => $user->getShowProfilePic(),
"username" => $user->getFullName(),
"openid_url" => $this->server_configuration_service->getUserIdentityEndpointURL($user->getIdentifier()),
"identifier " => $user->getIdentifier(),
"sites" => $sites,
"show_pic" => $user->getShowProfilePic(),
"show_full_name" => $user->getShowProfileFullName(),
"show_email" => $user->getShowProfileEmail(),
'actions' => $actions,
'clients' => $clients,
"show_email" => $user->getShowProfileEmail(),
'actions' => $actions,
'clients' => $clients,
));
}
@ -267,33 +270,51 @@ class UserController extends BaseController
return View::make("404");
}
$allowed_uris = $client->getClientRegisteredUris();
$allowed_uris = $client->getClientRegisteredUris();
$selected_scopes = $client->getClientScopes();
$aux_scopes = array();
foreach ($selected_scopes as $scope) {
array_push($aux_scopes, $scope->id);
}
$scopes = $this->scope_service->getAvailableScopes();
$scopes = $this->scope_service->getAvailableScopes();
return View::make("edit-registered-client",
array('client' => $client,
'allowed_uris' => $allowed_uris,
$access_tokens = $this->token_service->getAccessTokenByClient($client->client_id);
foreach($access_tokens as $token){
$friendly_scopes = $this->scope_service->getFriendlyScopesByName(explode(' ',$token->scope));
$token->setFriendlyScopes(implode(',',$friendly_scopes));
}
$refresh_tokens = $this->token_service->getRefreshTokenByClient($client->client_id);
foreach($refresh_tokens as $token){
$friendly_scopes = $this->scope_service->getFriendlyScopesByName(explode(' ',$token->scope));
$token->setFriendlyScopes(implode(',',$friendly_scopes));
}
return View::make("oauth2.profile.edit-client",
array(
'client' => $client,
'allowed_uris' => $allowed_uris,
'selected_scopes' => $aux_scopes,
'scopes' => $scopes
'scopes' => $scopes,
'access_tokens' => $access_tokens,
'refresh_tokens' => $refresh_tokens,
));
}
public function getRegisteredClientUris($id){
public function getRegisteredClientUris($id)
{
try {
$client = $this->client_service->getClientByIdentifier($id);
$allowed_uris = $client->getClientRegisteredUris();
$container = array();
foreach($allowed_uris as $uri){
array_push($container,array('id'=>$uri->id,'redirect_uri'=>$uri->uri));
foreach ($allowed_uris as $uri) {
array_push($container, array('id' => $uri->id, 'redirect_uri' => $uri->uri));
}
return Response::json(array('status' => 'OK','allowed_uris'=>$container));
return Response::json(array('status' => 'OK', 'allowed_uris' => $container));
} catch (Exception $ex) {
Log::error($ex);
return Response::json(array('status' => 'ERROR'));
@ -332,8 +353,7 @@ class UserController extends BaseController
$app_desc = trim($input['app_desc']);
$app_type = $input['app_type'];
if($this->client_service->existClientAppName($app_name))
{
if ($this->client_service->existClientAppName($app_name)) {
throw new Exception("Application Name already exists!");
}
@ -343,23 +363,23 @@ class UserController extends BaseController
$clients_response = array();
foreach($clients as $client){
foreach ($clients as $client) {
array_push($clients_response, array(
'id' => $client->id,
'app_name' => $client->app_name,
'id' => $client->id,
'app_name' => $client->app_name,
'client_type' => $client->getFriendlyClientType(),
'active' => $client->active,
'locked' => $client->locked,
'updated_at' => $client->updated_at->format('Y-m-d H:i:s')
'active' => $client->active,
'locked' => $client->locked,
'updated_at' => $client->updated_at->format('Y-m-d H:i:s')
));
}
return Response::json(array('status' => 'OK','clients'=> $clients_response));
return Response::json(array('status' => 'OK', 'clients' => $clients_response));
}
throw new Exception("invalid param!");
} catch (Exception $ex) {
Log::error($ex);
return Response::json(array('status' => 'ERROR', 'msg'=> $ex->getMessage()));
return Response::json(array('status' => 'ERROR', 'msg' => $ex->getMessage()));
}
}
@ -383,14 +403,12 @@ class UserController extends BaseController
} else {
return Response::json(array('status' => 'ERROR'));
}
}
catch (AllowedClientUriAlreadyExistsException $ex1) {
} catch (AllowedClientUriAlreadyExistsException $ex1) {
Log::error($ex1);
return Response::json(array('status' => 'ERROR','msg'=>'Uri already exists!'));
}
catch (Exception $ex) {
return Response::json(array('status' => 'ERROR', 'msg' => 'Uri already exists!'));
} catch (Exception $ex) {
Log::error($ex);
return Response::json(array('status' => 'ERROR','msg'=>'There was an error!'));
return Response::json(array('status' => 'ERROR', 'msg' => 'There was an error!'));
}
}
@ -409,7 +427,7 @@ class UserController extends BaseController
{
try {
$new_secret = $this->client_service->regenerateClientSecret($id);
return Response::json(array('status' => 'OK','new_secret'=>$new_secret));
return Response::json(array('status' => 'OK', 'new_secret' => $new_secret));
} catch (Exception $ex) {
Log::error($ex);
return Response::json(array('status' => 'ERROR'));
@ -424,21 +442,20 @@ class UserController extends BaseController
// Build the validation constraint set.
$rules = array(
'scope_id' => 'required',
'checked' => 'required',
'scope_id' => 'required',
'checked' => 'required',
);
// Create a new validator instance.
$validator = Validator::make($input, $rules);
if ($validator->passes()) {
$client_id = $id;
$checked = $input['checked'];
$scope_id = $input['scope_id'];
if($checked){
$this->client_service->addClientScope($client_id,$scope_id);
}
else{
$this->client_service->deleteClientScope($client_id,$scope_id);
$checked = $input['checked'];
$scope_id = $input['scope_id'];
if ($checked) {
$this->client_service->addClientScope($client_id, $scope_id);
} else {
$this->client_service->deleteClientScope($client_id, $scope_id);
}
return Response::json(array('status' => 'OK'));
}
@ -448,22 +465,23 @@ class UserController extends BaseController
}
}
public function postActivateClient($id){
public function postActivateClient($id)
{
try {
$input = Input::All();
// Build the validation constraint set.
$rules = array(
'active' => 'required',
'active' => 'required',
);
// Create a new validator instance.
$validator = Validator::make($input, $rules);
if ($validator->passes()) {
$active = $input['active'];
$active = $input['active'];
$this->client_service->activateClient($id,$active);
$this->client_service->activateClient($id, $active);
return Response::json(array('status' => 'OK'));
}
@ -473,22 +491,23 @@ class UserController extends BaseController
}
}
public function postUseRefreshTokenClient($id){
public function postUseRefreshTokenClient($id)
{
try {
$input = Input::All();
// Build the validation constraint set.
$rules = array(
'use_refresh_token' => 'required'
'use_refresh_token' => 'required'
);
// Create a new validator instance.
$validator = Validator::make($input, $rules);
if ($validator->passes()) {
$use_refresh_token = $input['use_refresh_token'];
$use_refresh_token = $input['use_refresh_token'];
$this->client_service->setRefreshTokenUsage($id,$use_refresh_token);
$this->client_service->setRefreshTokenUsage($id, $use_refresh_token);
return Response::json(array('status' => 'OK'));
}
@ -498,13 +517,14 @@ class UserController extends BaseController
}
}
public function postRotateRefreshTokenPolicy($id){
public function postRotateRefreshTokenPolicy($id)
{
try {
$input = Input::All();
// Build the validation constraint set.
$rules = array(
'rotate_refresh_token' => 'required'
'rotate_refresh_token' => 'required'
);
// Create a new validator instance.
@ -512,9 +532,9 @@ class UserController extends BaseController
if ($validator->passes()) {
$rotate_refresh_token = $input['rotate_refresh_token'];
$rotate_refresh_token = $input['rotate_refresh_token'];
$this->client_service->setRotateRefreshTokenPolicy($id,$rotate_refresh_token);
$this->client_service->setRotateRefreshTokenPolicy($id, $rotate_refresh_token);
return Response::json(array('status' => 'OK'));
}
@ -523,4 +543,43 @@ class UserController extends BaseController
return Response::json(array('status' => 'ERROR'));
}
}
public function getRevokeToken($value, $hint)
{
try {
$res = false;
switch ($hint) {
case 'access-token':
$res = $this->token_service->revokeAccessToken($value, true);
break;
case 'refresh-token':
$res = $this->token_service->revokeRefreshToken($value, true);
break;
default:
break;
}
return $res ? Response::json(array('status' => 'OK')) : Response::json(array('status' => 'ERROR'));
}
catch (Exception $ex) {
Log::error($ex);
return Response::json(array('status' => 'ERROR'));
}
}
public function getAccessTokens($client_id){
$access_tokens = $this->token_service->getAccessTokenByClient($client_id);
$res = array();
foreach($access_tokens as $token){
$friendly_scopes = $this->scope_service->getFriendlyScopesByName(explode(' ',$token->scope));
array_push($res,array(
'value' => $token->value,
'scope' => implode(',',$friendly_scopes),
'lifetime' => $token->getRemainingLifetime(),
'issued' => $token->created_at->format('Y-m-d H:i:s')
));
}
return Response::json(array('status' => 'OK','access_tokens'=>$res));
}
}

View File

@ -10,7 +10,7 @@ class CreateTrustedSitesTable extends Migration {
{
$table->bigIncrements('id')->unsigned();
$table->string('realm',1024);
$table->string('data',5000)->nullable();
$table->text('data')->nullable();
$table->string('policy',255);
$table->bigInteger("user_id")->unsigned();
});

View File

@ -49,7 +49,14 @@ App::after(function ($request, $response) {
*/
Route::filter('auth', function () {
if (Auth::guest()) return Redirect::action('HomeController@index');
if (Auth::guest()) {
Session::put('url.intended', URL::full());
return Redirect::action('HomeController@index');
}
if ($redirect = Session::get('url.intended')) {
Session::forget('url.intended');
return Redirect::to($redirect);
}
});

View File

@ -53,12 +53,12 @@ abstract class AbstractGrantType implements IGrantType
throw new InvalidClientException;
if (!$this->current_client->isActive() || $this->current_client->isLocked()) {
throw new UnAuthorizedClientException();
throw new UnAuthorizedClientException(sprintf('client id %s',$this->current_client_id));
}
//verify client credentials (only for confidential clients )
if ($this->current_client->getClientType() == IClient::ClientType_Confidential && $this->current_client->getClientSecret() !== $this->current_client_secret)
throw new UnAuthorizedClientException;
throw new UnAuthorizedClientException(sprintf('client id %s',$this->current_client_id));
}
}

View File

@ -8,6 +8,8 @@ interface IApiScopeService {
*/
public function getScopesByName(array $scopes_names);
public function getFriendlyScopesByName(array $scopes_names);
/** get all active scopes
* @return mixed
*/

View File

@ -108,6 +108,10 @@ interface ITokenService {
*/
public function revokeClientRelatedTokens($client_id);
public function getAccessTokenByClient($client_id);
public function getRefreshTokenByClient($client_id);
/**
* Revokes a given access token

View File

@ -11,7 +11,7 @@ class RequestContext
public function __construct()
{
$this->partial_views = array();
$this->trusted_data = array();
$this->trusted_data = array();
}
public function addPartialView(PartialView $partial_view)

View File

@ -1,11 +1,14 @@
<?php
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';
private $friendly_scopes;
public function refresh_token()
{
return $this->belongsTo('RefreshToken');
@ -14,4 +17,34 @@ class AccessToken extends Eloquent {
public function client(){
return $this->belongsTo('Client');
}
public function isVoid(){
//check lifetime...
$created_at = $this->created_at;
$created_at->add(new DateInterval('PT' . $this->lifetime . 'S'));
$now = new DateTime(gmdate("Y-m-d H:i:s", time()));
return ($now > $created_at);
}
public function getFriendlyScopes(){
return $this->friendly_scopes;
}
public function setFriendlyScopes($friendly_scopes){
$this->friendly_scopes = $friendly_scopes;
}
public function getRemainingLifetime()
{
//check is refresh token is stills alive... (ZERO is infinite lifetime)
if ($this->lifetime === 0) return 0;
$created_at = new DateTime($this->created_at);
$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;
}
}

View File

@ -4,6 +4,8 @@ class RefreshToken extends Eloquent {
protected $table = 'oauth2_refresh_token';
private $friendly_scopes;
protected $fillable = array('value', 'from_ip', 'lifetime','scope','audience','void','created_at','updated_at','client_id');
public function access_tokens()
@ -15,4 +17,35 @@ class RefreshToken extends Eloquent {
return $this->belongsTo('Client');
}
public function isVoid(){
if($this->lifetime === 0) return false;
//check lifetime...
$created_at = $this->created_at;
$created_at->add(new DateInterval('PT' . $this->lifetime . 'S'));
$now = new DateTime(gmdate("Y-m-d H:i:s", time()));
return ($now > $created_at);
}
public function getRemainingLifetime()
{
//check is refresh token is stills alive... (ZERO is infinite lifetime)
if ($this->lifetime === 0) return 0;
$created_at = new DateTime($this->created_at);
$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;
}
public function getFriendlyScopes(){
return $this->friendly_scopes;
}
public function setFriendlyScopes($friendly_scopes){
$this->friendly_scopes = $friendly_scopes;
}
}

View File

@ -58,8 +58,10 @@ Route::group(array("before" => array("ssl", "auth")), function () {
Route::get('/accounts/user/profile/clients/redirect_uri/delete/{id}/{uri_id}','UserController@getDeleteClientAllowedUri');
Route::post('/accounts/user/profile/clients/scope/add/{id}','UserController@postAddAllowedScope');
Route::post('/accounts/user/profile/clients/activate/{id}','UserController@postActivateClient');
Route::post('/accounts/user/profile/clients/use/refresh_token/{id}','UserController@postUseRefreshTokenClient');
Route::post('/accounts/user/profile/clients/rotate/refresh_token/{id}','UserController@postRotateRefreshTokenPolicy');
Route::post('/accounts/user/profile/clients/token/use/refresh_token/{id}','UserController@postUseRefreshTokenClient');
Route::post('/accounts/user/profile/clients/token/rotate/refresh_token/{id}','UserController@postRotateRefreshTokenPolicy');
Route::get('/accounts/user/profile/clients/token/revoke/{value}/{hint}','UserController@getRevokeToken');
Route::get('/accounts/user/profile/clients/token/access_tokens/{client_id}','UserController@getAccessTokens');
});

View File

@ -4,6 +4,7 @@ namespace services\oauth2;
use oauth2\services\IApiScopeService;
use ApiScope;
use DB;
class ApiScopeService implements IApiScopeService {
@ -16,6 +17,11 @@ class ApiScopeService implements IApiScopeService {
return ApiScope::where('active','=',true)->whereIn('name',$scopes_names)->get();
}
public function getFriendlyScopesByName(array $scopes_names){
return DB::table('oauth2_api_scope')->where('active','=',true)->whereIn('name',$scopes_names)->lists('short_description');
}
/** get all active scopes
* @return mixed
*/

View File

@ -82,7 +82,7 @@ class ClientService implements IClientService
$instance->client_id = Rand::getString(32, OAuth2Protocol::VsChar, true) . '.openstack.client';
//only generates secret for confidential clients
if ($client_type == IClient::ClientType_Confidential)
$instance->client_secret = Rand::getString(16, OAuth2Protocol::VsChar, true);
$instance->client_secret = Rand::getString(24, OAuth2Protocol::VsChar, true);
$instance->client_type = $client_type;
$instance->user_id = $user_id;
$instance->active = true;
@ -169,7 +169,7 @@ class ClientService implements IClientService
DB::transaction(function () use ($id, &$new_secret) {
$client = Client::find($id);
if (!is_null($client)) {
$client_secret = Rand::getString(16, OAuth2Protocol::VsChar, true);
$client_secret = Rand::getString(24, OAuth2Protocol::VsChar, true);
$client->client_secret = $client_secret;
$client->Save();
$token_service = Registry::getInstance()->get(OAuth2ServiceCatalog::TokenService);

View File

@ -359,12 +359,8 @@ class TokenService implements ITokenService
$lock_name = 'lock.get.accesstoken.' . $hashed_value;
$this->lock_manager_service->acquireLock($lock_name);
//check lifetime...
$lifetime = $access_token_db->lifetime;
$created_at = $access_token_db->created_at;
$created_at->add(new DateInterval('PT' . $lifetime . 'S'));
$now = new DateTime(gmdate("Y-m-d H:i:s", time()));
if ($now > $created_at) {
if ($access_token_db->isVoid()){
//invalid one ...
$access_token_db->delete();
throw new InvalidGrantTypeException(sprintf('Access token %s is expired!', $value));
@ -496,14 +492,8 @@ class TokenService implements ITokenService
}
//check is refresh token is stills alive... (ZERO is infinite lifetime)
if ($refresh_token_db->lifetime !== 0) {
$created_at = $refresh_token_db->created_at;
$created_at->add(new DateInterval('PT' . $refresh_token_db->lifetime . 'S'));
$now = new DateTime(gmdate("Y-m-d H:i:s", time()));
//check validity...
if ($now > $created_at)
throw new InvalidGrantTypeException(sprintf("Refresh token %s is expired!", $value));
}
if($refresh_token_db->isVoid())
throw new InvalidGrantTypeException(sprintf("Refresh token %s is expired!", $value));
$client = $refresh_token_db->client()->first();
@ -589,13 +579,14 @@ class TokenService implements ITokenService
$access_tokens = $this->cache_service->getSet($client_id . self::ClientAccessTokenPrefixList);
DB::transaction(function () use ($client_id, $auth_codes, $access_tokens) {
$client = $this->client_service->getClientById($client_id);
if(is_null($client)) return;
//revoke on cache
$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();
//revoke on db
$client->access_tokens()->delete();
$client->refresh_tokens()->delete();
//delete client list (auth codes and access tokens)
$this->cache_service->delete($client_id . self::ClientAuthCodePrefixList);
$this->cache_service->delete($client_id . self::ClientAccessTokenPrefixList);
@ -641,11 +632,12 @@ class TokenService implements ITokenService
public function clearAccessTokensForRefreshToken($value, $is_hashed = false){
$hashed_value = !$is_hashed?Hash::compute('sha256', $value):$value;
DB::transaction(function () use ($hashed_value) {
$res = false;
DB::transaction(function () use ($hashed_value, &$res) {
$refresh_token_db = DBRefreshToken::where('value','=',$hashed_value)->first();
if(!is_null($refresh_token_db)){
$access_tokens_db = DBAccessToken::where('refresh_token_id','=',$refresh_token_db->id)->get();
if(!count($access_tokens_db)) $res = true;
foreach($access_tokens_db as $access_token_db){
$res = $this->cache_service->delete($access_token_db->value);
$client = $access_token_db->client()->first();
@ -654,7 +646,27 @@ class TokenService implements ITokenService
}
}
});
return $res;
}
public function getAccessTokenByClient($client_id){
$client = $this->client_service->getClientById($client_id);
$res = array();
$access_tokens = $client->access_tokens()->get();
foreach($access_tokens as $access_token){
if(!$access_token->isVoid()) array_push($res,$access_token);
}
return $res;
}
public function getRefreshTokenByClient($client_id){
$client = $this->client_service->getClientById($client_id);
$res = array();
$refresh_tokens = $client->refresh_tokens()->where('void','=',false)->get();
foreach($refresh_tokens as $refresh_token){
if(!$refresh_token->isVoid()) array_push($res,$refresh_token);
}
return $res;
}
}

View File

@ -7,6 +7,7 @@ use services\IPHelper;
use services\IUserActionService;
use utils\services\IAuthService;
use View;
use URL;
class DefaultLoginStrategy implements ILoginStrategy
{
@ -33,7 +34,9 @@ class DefaultLoginStrategy implements ILoginStrategy
$user = $this->auth_service->getCurrentUser();
$identifier = $user->getIdentifier();
$this->user_action_service->addUserAction($this->auth_service->getCurrentUser(), IPHelper::getUserIp(), IUserActionService::LoginAction);
return Redirect::action("UserController@getIdentity", array("identifier" => $identifier));
$default_url = URL::action("UserController@getIdentity", array("identifier" => $identifier));
return Redirect::intended($default_url);
}
public function cancelLogin()

View File

@ -26,10 +26,10 @@ class OpenIdConsentStrategy implements IConsentStrategy
public function __construct(IMementoOpenIdRequestService $memento_service, IAuthService $auth_service, IServerConfigurationService $server_configuration_service, IUserActionService $user_action_service)
{
$this->memento_service = $memento_service;
$this->auth_service = $auth_service;
$this->memento_service = $memento_service;
$this->auth_service = $auth_service;
$this->server_configuration_service = $server_configuration_service;
$this->user_action_service = $user_action_service;
$this->user_action_service = $user_action_service;
}
public function getConsent()
@ -44,16 +44,12 @@ class OpenIdConsentStrategy implements IConsentStrategy
if (is_null($context))
throw new InvalidRequestContextException();
$partial_views = $context->getPartials();
$data = array();
$views = array();
foreach ($partial_views as $partial) {
$views[$partial->getName()] = View::make($partial->getName(), $partial->getData());
}
$request = $this->memento_service->getCurrentRequest();
$user = $this->auth_service->getCurrentUser();
$data['realm'] = $request->getParam(OpenIdProtocol::OpenIDProtocol_Realm);
$data = array();
$request = $this->memento_service->getCurrentRequest();
$user = $this->auth_service->getCurrentUser();
$data['realm'] = $request->getParam(OpenIdProtocol::OpenIDProtocol_Realm);
$data['openid_url'] = $this->server_configuration_service->getUserIdentityEndpointURL($user->getIdentifier());
$data['views'] = $views;
$data['views'] = $partial_views;
return $data;
}

View File

@ -1,363 +0,0 @@
@extends('layout')
@section('title')
<title>Welcome to openstackId - Edit Registered Application</title>
@stop
@section('content')
<a href="{{ URL::previous() }}">Go Back</a>
<legend>{{ $client->app_name }}</legend>
@if($errors->any())
<div class="errors">
<ul>
@foreach($errors->all() as $error)
<div class="alert alert-error">
<button type="button" class="close" data-dismiss="alert">&times;</button>
{{ $error }}
</div>
@endforeach
</ul>
</div>
@endif
<div id="accordion">
<h3><i class="icon-info-sign accordion-toggle" title="OAuth2 Client ID and Client Secret"></i>&nbsp;OAuth 2.0 Client ID</h3>
<div class="row-fluid">
<div class="span12">
<div class="row-fluid">
<div class="span12">
<label for="client_id" class="label-client-secret">Client ID</label>
<span id="client_id">{{ $client->client_id }}</span>
</div>
</div>
@if($client->client_type === oauth2\models\IClient::ClientType_Confidential)
<div class="row-fluid">
<div class="span12">
<label for="client_secret" class="label-client-secret">Client Secret</label>
<span id="client_secret">{{ $client->client_secret }}</span>
{{ HTML::link(URL::action("UserController@getRegenerateClientSecret",array("id"=>$client->id)),'Regenerate',array('class'=>'btn regenerate-client-secret','title'=>'Regenerates Client Secret')) }}
</div>
</div>
<div class="row-fluid">
<div class="span12">
<label class="label-client-secret">Client Settings</label>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<label class="checkbox">
<input type="checkbox"
@if ($client->use_refresh_token)
checked
@endif
id="use-refresh-token">
Use Refresh Tokens
&nbsp;<i class="icon-info-sign accordion-toggle" title=""></i>
</label>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<label class="checkbox">
<input type="checkbox"
@if ($client->rotate_refresh_token)
checked
@endif
id="use-rotate-refresh-token-policy">
Use Rotate Refresh Token Policy
&nbsp;<i class="icon-info-sign accordion-toggle" title=""></i>
</label>
</div>
</div>
@endif
</div>
</div>
<h3><i class="icon-info-sign accordion-toggle" title="Authorized Client Redirection Uris"></i>&nbsp;Authorized Redirection Uris</h3>
<div class="row-fluid">
<div class="span12">
<div class="row-fluid">
<div class="span12">
<label for="redirect_uri">New Authorized Redirect Uri&nbsp;<i class="icon-info-sign accordion-toggle" title="Uri schema must be under SSL"></i></label>
<input type="text" value="" id="redirect_uri" name="redirect_uri"/>
{{ HTML::link(URL::action("UserController@postAddAllowedRedirectUri",array("id"=>$client->id)),'Add',array('class'=>'btn add-uri-client','title'=>'Add a new Registered Client Uri')) }}
</div>
</div>
@if (count($allowed_uris)>0)
<div class="row-fluid">
<div class="span12">
<table class="table table-hover table-condensed">
<thead>
<tr>
<th>Authorized Uri</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody id="body-allowed-uris">
@foreach ($allowed_uris as $uri)
<tr>
<td>{{ $uri->uri }}</td>
<td>&nbsp;{{ HTML::link(URL::action("UserController@getDeleteClientAllowedUri",array("id"=>$client->id,'uri_id'=>$uri->id)),'Delete',array('class'=>'btn del-allowed-uri','title'=>'Deletes a Allowed Uri')) }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endif
</div>
</div>
<h3><i class="icon-info-sign accordion-toggle" title="Application Allowed Scopes"></i>&nbsp;Application Allowed Scopes</h3>
<div class="row-fluid">
<div class="span12">
<ul class="unstyled list-inline"><li>
<?php $last_api = ''; ?>
@foreach ($scopes as $scope)
<?php $current_api = $scope->getApiName(); ?>
@if($last_api!=$current_api)
@if($last_api!='')
</ul><!--scopes-->
</li><li>
@endif
<?php $last_api = $current_api;?>
{{ $current_api }}&nbsp;<i class="icon-info-sign accordion-toggle" title="{{$scope->getApiDescription()}}"></i>
<ul class="unstyled list-inline">
@endif
<li>
<label class="checkbox">
<input type="checkbox" class="scope-checkbox" id="scope[]"
@if ( in_array($scope->id,$selected_scopes))
checked
@endif
value="{{$scope->id}}"/> {{$scope->name}}&nbsp;<i class="icon-info-sign accordion-toggle" title="{{$scope->description}}"></i>
</label>
</li>
@endforeach
</ul><!--scopes-->
</li></ul>
</div>
</div>
</div>
@stop
@section('scripts')
<script type="application/javascript">
$(document).ready(function() {
$( "#accordion" ).accordion({
collapsible: true,
heightStyle: "content"
});
function displayAlert(msg,after){
var alert = $('<div class="alert alert-error"><button type="button" class="close" data-dismiss="alert">&times;</button>'+msg+'</div>');
alert.insertAfter(after);
}
function loadAllowedClientUris(){
var link = '{{URL::action("UserController@getRegisteredClientUris",array("id"=>$client->id))}}';
$.ajax(
{
type: "GET",
url: link,
dataType: "json",
timeout:60000,
success: function (data,textStatus,jqXHR) {
//load data...
if(data.status==='OK'){
var uris = data.allowed_uris;
var template = $('<tbody><tr><td class="uri-text"></td><td><a title="Deletes a Allowed Uri" class="btn del-allowed-uri">Delete</a></td></tr></tbody>');
var directives = {
'tr':{
'uri<-context':{
'td.uri-text':'uri.redirect_uri',
'a.del-allowed-uri@href':function(arg){
var uri_id = arg.item.id;
var href = '{{ URL::action("UserController@getDeleteClientAllowedUri", array("id"=>$client->id,"uri_id"=>"-1")) }}';
return href.replace('-1',uri_id);
}
}
}
};
var html = template.render(uris, directives);
//alert(html.html());
$('#body-allowed-uris').html(html.html());
}
else{
alert('There was an error!');
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert( "Request failed: " + textStatus );
}
}
);
}
$("body").on('click',".regenerate-client-secret",function(event){
if(confirm("Are you sure? Regenerating client secret would invalidate all current tokens")){
var link = $(this).attr('href');
$.ajax(
{
type: "GET",
url: link,
dataType: "json",
timeout:60000,
success: function (data,textStatus,jqXHR) {
//load data...
if(data.status==='OK'){
$('#client_secret').text(data.new_secret);
}
else{
alert('There was an error!');
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert( "Request failed: " + textStatus );
}
}
);
}
event.preventDefault();
return false;
});
$("body").on('click',".add-uri-client",function(event){
var link = $(this).attr('href');
var data = {};
data.redirect_uri = $('#redirect_uri').val();
var regex = /https:\/\/([\w@][\w.:@]+)\/?[\w\.?=%&=\-@/$,]*/ig;
if(regex.test(data.redirect_uri)){
$.ajax(
{
type: "POST",
url: link,
dataType: "json",
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
timeout:60000,
success: function (data,textStatus,jqXHR) {
//load data...
if(data.status==='OK'){
$('#redirect_uri').val('');
loadAllowedClientUris();
}
else{
displayAlert(data.msg,'.add-uri-client');
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert( "Request failed: " + textStatus );
}
}
);
}
else{
displayAlert('Uri not valid!','.add-uri-client');
}
event.preventDefault();
return false;
});
$("body").on('click',".del-allowed-uri",function(event){
if(confirm("Are you sure?")){
var link = $(this).attr('href');
$.ajax(
{
type: "GET",
url: link,
dataType: "json",
timeout:60000,
success: function (data,textStatus,jqXHR) {
//load data...
if(data.status==='OK'){
loadAllowedClientUris();
}
else{
alert('There was an error!');
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert( "Request failed: " + textStatus );
}
}
);
}
event.preventDefault();
return false;
});
$("body").on('click',"#use-refresh-token",function(event){
var param = {};
param.use_refresh_token = $(this).is(':checked');
$.ajax(
{
type: "POST",
url: '{{URL::action("UserController@postUseRefreshTokenClient",array("id"=>$client->id))}}',
data: JSON.stringify(param),
contentType: "application/json; charset=utf-8",
dataType: "json",
timeout:60000,
success: function (data,textStatus,jqXHR) {
//load data...
},
error: function (jqXHR, textStatus, errorThrown) {
alert( "Request failed: " + textStatus );
}
}
);
});
$("body").on('click',"#use-rotate-refresh-token-policy",function(event){
var param = {};
param.rotate_refresh_token = $(this).is(':checked');
$.ajax(
{
type: "POST",
url: '{{URL::action("UserController@postRotateRefreshTokenPolicy",array("id"=>$client->id))}}',
data: JSON.stringify(param),
contentType: "application/json; charset=utf-8",
dataType: "json",
timeout:60000,
success: function (data,textStatus,jqXHR) {
//load data...
},
error: function (jqXHR, textStatus, errorThrown) {
alert( "Request failed: " + textStatus );
}
}
);
});
$("body").on('click',".scope-checkbox",function(event){
var scope = {};
scope.scope_id = $(this).attr('value');
scope.checked = $(this).is(':checked');
$.ajax(
{
type: "POST",
url: '{{URL::action("UserController@postAddAllowedScope",array("id"=>$client->id))}}',
data: JSON.stringify(scope),
contentType: "application/json; charset=utf-8",
dataType: "json",
timeout:60000,
success: function (data,textStatus,jqXHR) {
//load data...
},
error: function (jqXHR, textStatus, errorThrown) {
alert( "Request failed: " + textStatus );
}
}
);
});
});
</script>
@stop

View File

@ -28,7 +28,8 @@
</div>
@endif
@section('subscripts')
@section('scripts')
@parent
<script type="application/javascript">
$(document).ready(function() {

File diff suppressed because one or more lines are too long

View File

@ -29,7 +29,5 @@
{{ HTML::script('js/jquery.validate.min.js')}}
{{ HTML::script('js/additional-methods.min.js')}}
@yield('scripts')
@yield('subscripts')
</body>
</html>

View File

@ -0,0 +1,131 @@
<div class="row-fluid">
<div class="span12">
<div class="row-fluid">
<div class="span12">
<label for="client_id" class="label-client-secret">Client ID</label>
<span id="client_id">{{ $client->client_id }}</span>
</div>
</div>
@if($client->client_type === oauth2\models\IClient::ClientType_Confidential)
<div class="row-fluid">
<div class="span12">
<label for="client_secret" class="label-client-secret">Client Secret</label>
<span id="client_secret">{{ $client->client_secret }}</span>
{{ HTML::link(URL::action("UserController@getRegenerateClientSecret",array("id"=>$client->id)),'Regenerate',array('class'=>'btn regenerate-client-secret','title'=>'Regenerates Client Secret')) }}
</div>
</div>
<div class="row-fluid">
<div class="span12">
<label class="label-client-secret">Client Settings</label>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<label class="checkbox">
<input type="checkbox"
@if ($client->use_refresh_token)
checked
@endif
id="use-refresh-token">
Use Refresh Tokens
&nbsp;<i class="icon-info-sign accordion-toggle" title=""></i>
</label>
</div>
</div>
<div class="row-fluid">
<div class="span12">
<label class="checkbox">
<input type="checkbox"
@if ($client->rotate_refresh_token)
checked
@endif
id="use-rotate-refresh-token-policy">
Use Rotate Refresh Token Policy
&nbsp;<i class="icon-info-sign accordion-toggle" title=""></i>
</label>
</div>
</div>
@endif
</div>
</div>
@section('scripts')
@parent
<script type="application/javascript">
$(document).ready(function() {
$("body").on('click',".regenerate-client-secret",function(event){
if(confirm("Are you sure? Regenerating client secret would invalidate all current tokens")){
var link = $(this).attr('href');
$.ajax(
{
type: "GET",
url: link,
dataType: "json",
timeout:60000,
success: function (data,textStatus,jqXHR) {
//load data...
if(data.status==='OK'){
$('#client_secret').text(data.new_secret);
//clean token UI
$('#table-access-tokens').remove();
$('#table-refresh-tokens').remove();
}
else{
alert('There was an error!');
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert( "Request failed: " + textStatus );
}
}
);
}
event.preventDefault();
return false;
});
$("body").on('click',"#use-refresh-token",function(event){
var param = {};
param.use_refresh_token = $(this).is(':checked');
$.ajax(
{
type: "POST",
url: '{{URL::action("UserController@postUseRefreshTokenClient",array("id"=>$client->id))}}',
data: JSON.stringify(param),
contentType: "application/json; charset=utf-8",
dataType: "json",
timeout:60000,
success: function (data,textStatus,jqXHR) {
//load data...
},
error: function (jqXHR, textStatus, errorThrown) {
alert( "Request failed: " + textStatus );
}
}
);
});
$("body").on('click',"#use-rotate-refresh-token-policy",function(event){
var param = {};
param.rotate_refresh_token = $(this).is(':checked');
$.ajax(
{
type: "POST",
url: '{{URL::action("UserController@postRotateRefreshTokenPolicy",array("id"=>$client->id))}}',
data: JSON.stringify(param),
contentType: "application/json; charset=utf-8",
dataType: "json",
timeout:60000,
success: function (data,textStatus,jqXHR) {
//load data...
},
error: function (jqXHR, textStatus, errorThrown) {
alert( "Request failed: " + textStatus );
}
}
);
});
});
</script>
@stop

View File

@ -0,0 +1,158 @@
<div class="row-fluid">
<div class="span12">
<div class="row-fluid">
<div class="span12">
<label for="redirect_uri">New Authorized Redirect Uri&nbsp;<i class="icon-info-sign accordion-toggle" title="Uri schema must be under SSL"></i></label>
<input type="text" value="" id="redirect_uri" name="redirect_uri"/>
{{HTML::link(URL::action("UserController@postAddAllowedRedirectUri",array("id"=>$client->id)),'Add',array('class'=>'btn add-uri-client','title'=>'Add a new Registered Client Uri')) }}
</div>
</div>
@if (count($allowed_uris)>0)
<div class="row-fluid">
<div class="span12">
<table class="table table-hover table-condensed">
<thead>
<tr>
<th>Authorized Uri</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody id="body-allowed-uris">
@foreach ($allowed_uris as $uri)
<tr>
<td>{{ $uri->uri }}</td>
<td>&nbsp;{{ HTML::link(URL::action("UserController@getDeleteClientAllowedUri",array("id"=>$client->id,'uri_id'=>$uri->id)),'Delete',array('class'=>'btn del-allowed-uri','title'=>'Deletes a Allowed Uri')) }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endif
</div>
</div>
@section('scripts')
@parent
<script type="application/javascript">
function loadAllowedClientUris(){
var link = '{{URL::action("UserController@getRegisteredClientUris",array("id"=>$client->id))}}';
$.ajax(
{
type: "GET",
url: link,
dataType: "json",
timeout:60000,
success: function (data,textStatus,jqXHR) {
//load data...
if(data.status==='OK'){
var uris = data.allowed_uris;
var template = $('<tbody><tr><td class="uri-text"></td><td><a title="Deletes a Allowed Uri" class="btn del-allowed-uri">Delete</a></td></tr></tbody>');
var directives = {
'tr':{
'uri<-context':{
'td.uri-text':'uri.redirect_uri',
'a.del-allowed-uri@href':function(arg){
var uri_id = arg.item.id;
var href = '{{ URL::action("UserController@getDeleteClientAllowedUri", array("id"=>$client->id,"uri_id"=>"-1")) }}';
return href.replace('-1',uri_id);
}
}
}
};
var html = template.render(uris, directives);
//alert(html.html());
$('#body-allowed-uris').html(html.html());
}
else{
alert('There was an error!');
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert( "Request failed: " + textStatus );
}
}
);
}
$(document).ready(function() {
$("body").on('click',".add-uri-client",function(event){
var link = $(this).attr('href');
var data = {};
data.redirect_uri = $('#redirect_uri').val();
var regex_schema = /https.*/ig;
var regex = /https:\/\/([\w@][\w.:@]+)\/?[\w\.?=%&=\-@/$,]*/ig;
if(!regex_schema.test(data.redirect_uri)){
displayAlert('Redirect Uri must under https schema!','.add-uri-client');
event.preventDefault();
return false;
}
if(!regex.test(data.redirect_uri)){
displayAlert('Uri not valid!','.add-uri-client');
event.preventDefault();
return false;
}
$.ajax({
type: "POST",
url: link,
dataType: "json",
data: JSON.stringify(data),
contentType: "application/json; charset=utf-8",
timeout:60000,
success: function (data,textStatus,jqXHR) {
//load data...
if(data.status==='OK'){
$('#redirect_uri').val('');
loadAllowedClientUris();
return;
}
displayAlert(data.msg,'.add-uri-client');
},
error: function (jqXHR, textStatus, errorThrown) {
alert( "Request failed: " + textStatus );
}
});
event.preventDefault();
return false;
});
$("body").on('click',".del-allowed-uri",function(event){
if(confirm("Are you sure?")){
var link = $(this).attr('href');
$.ajax(
{
type: "GET",
url: link,
dataType: "json",
timeout:60000,
success: function (data,textStatus,jqXHR) {
//load data...
if(data.status==='OK'){
loadAllowedClientUris();
}
else{
alert('There was an error!');
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert( "Request failed: " + textStatus );
}
}
);
}
event.preventDefault();
return false;
});
});
</script>
@stop

View File

@ -0,0 +1,58 @@
<div class="row-fluid">
<div class="span12">
<ul class="unstyled list-inline"><li>
<?php $last_api = ''; ?>
@foreach ($scopes as $scope)
<?php $current_api = $scope->getApiName(); ?>
@if($last_api!=$current_api)
@if($last_api!='')
</ul><!--scopes-->
</li><li>
@endif
<?php $last_api = $current_api;?>
{{ $current_api }}&nbsp;<i class="icon-info-sign accordion-toggle" title="{{$scope->getApiDescription()}}"></i>
<ul class="unstyled list-inline">
@endif
<li>
<label class="checkbox">
<input type="checkbox" class="scope-checkbox" id="scope[]"
@if ( in_array($scope->id,$selected_scopes))
checked
@endif
value="{{$scope->id}}"/> {{$scope->name}}&nbsp;<i class="icon-info-sign accordion-toggle" title="{{$scope->description}}"></i>
</label>
</li>
@endforeach
</ul><!--scopes-->
</li></ul>
</div>
</div>
@section('scripts')
@parent
<script type="application/javascript">
$(document).ready(function() {
$("body").on('click',".scope-checkbox",function(event){
var scope = {};
scope.scope_id = $(this).attr('value');
scope.checked = $(this).is(':checked');
$.ajax(
{
type: "POST",
url: '{{URL::action("UserController@postAddAllowedScope",array("id"=>$client->id))}}',
data: JSON.stringify(scope),
contentType: "application/json; charset=utf-8",
dataType: "json",
timeout:60000,
success: function (data,textStatus,jqXHR) {
//load data...
},
error: function (jqXHR, textStatus, errorThrown) {
alert( "Request failed: " + textStatus );
}
}
);
});
});
</script>
@stop

View File

@ -0,0 +1,196 @@
<div class="row-fluid">
<div class="row">
<h4 style="float:left">Issued Access Tokens</h4>
<div style="position: relative;float:left;">
<div style="position:absolute;top:13px;margin-left:5px"><i class="icon-refresh accordion-toggle refresh-access-tokens" title="Update Access Tokens List"></i></div>
</div>
</div>
<div class="row">
<div class="alert alert-info" id="info-access-tokens" style="display: none">
<strong>There are not any Access Tokens granted for this application</strong>
</div>
</div>
<table id='table-access-tokens' class="table table-hover table-condensed"
@if (!count($access_tokens))
style='display:none';
@endif
<thead>
<tr>
<th><i class="icon-info-sign accordion-toggle" title="Time is on UTC"></i>&nbsp;Issued</th>
<th>Scopes</th>
<th><i class="icon-info-sign accordion-toggle" title="Lifetime is on seconds"></i>&nbsp;Remaining Lifetime</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody id="body-access-tokens">
@foreach ($access_tokens as $access_token)
<tr id="{{ $access_token->value }}">
<td>{{ $access_token->created_at }}</td>
<td>{{ $access_token->getFriendlyScopes() }}</td>
<td>{{ $access_token->getRemainingLifetime() }}</td>
<td>{{ HTML::link(URL::action("UserController@getRevokeToken",array("value"=>$access_token->value,'hint'=>'access-token')),'Revoke',array('class'=>'btn revoke-token revoke-access-token','title'=>'Revoke Access Token','data-value'=>$access_token->value,'data-hint'=>'access-token')) }}</td>
</tr>
@endforeach
</tbody>
</table>
<div class="row">
<h4 style="float:left">Issued Refresh Tokens</h4>
<div style="position: relative;float:left;">
<div style="position:absolute;top:13px;margin-left:5px"><i class="icon-refresh accordion-toggle refresh-refresh-tokens" title="Update Refresh Tokens List"></i></div>
</div>
</div>
<div class="row">
<div class="alert alert-info" style="display: none" id="info-refresh-tokens">
<strong>There are not any Refresh Tokens granted for this application</strong>
</div>
</div>
<table id='table-refresh-tokens' class="table table-hover table-condensed"
@if (!count($refresh_tokens))
style='display:none';
@endif
<thead>
<tr>
<th><i class="icon-info-sign accordion-toggle" title="Time is on UTC"></i>&nbsp;Issued</th>
<th>Scopes</th>
<th><i class="icon-info-sign accordion-toggle" title="Time is on UTC"></i>&nbsp;Remaining Lifetime</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
@foreach ($refresh_tokens as $refresh_token)
<tr id="{{ $refresh_token->value }}">
<td>{{ $refresh_token->created_at }}</td>
<td>{{ $refresh_token->getFriendlyScopes() }}</td>
@if($refresh_token->getRemainingLifetime()===0)
<td>Not Expire</td>
@else
<td>{{ $refresh_token->getRemainingLifetime() }}</td>
@endif
<td>{{ HTML::link(URL::action("UserController@getRevokeToken",array("value"=>$refresh_token->value,'hint'=>'refresh-token')),'Revoke',array('class'=>'btn revoke-token revoke-refresh-token','title'=>'Revoke Refresh Token','data-value'=>$refresh_token->value,'data-hint'=>'refresh-token')) }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
@section('scripts')
@parent
<script type="application/javascript">
function refreshAccessTokenList(){
//reload access tokens
$.ajax(
{
type: "GET",
url:'{{ URL::action("UserController@getAccessTokens",array("client_id"=>$client->client_id))}}' ,
dataType: "json",
timeout:60000,
success: function (data,textStatus,jqXHR) {
//load data...
if(data.status==='OK'){
if(data.access_tokens.length===0){
$('#table-access-tokens').hide();
$('#info-access-tokens').show();
}
else{
$('#info-access-tokens').hide();
$('#table-access-tokens').show();
var template = $('<tbody><tr><td class="issued"></td><td class="scope"></td><td class="lifetime"></td><td><a title="Revoke Access Token" class="btn revoke-token revoke-access-token" data-hint="access-token">Revoke</a></td></tr></tbody>');
var directives = {
'tr':{
'token<-context':{
'@id' :'token.value',
'td.issued' :'token.issued',
'td.scope' :'token.scope',
'td.lifetime':'token.lifetime',
'a@href':function(arg){
var token_value = arg.item.value;
var href = '{{ URL::action("UserController@getRevokeToken",array("value"=>-1,"hint"=>"access-token")) }}';
return href.replace('-1',token_value);
},
'a@data-value' :'token.value'
}
}
};
var html = template.render(data.access_tokens, directives);
$('#body-access-tokens').html(html.html());
}
}
else{
alert('There was an error!');
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert( "Request failed: " + textStatus );
}
});
}
$(document).ready(function() {
if($('#table-access-tokens').length===0)
$('#info-access-tokens').show();
if($('#table-refresh-tokens').length===0)
$('#info-refresh-tokens').show();
$("body").on('click','.refresh-access-tokens',function(event){
refreshAccessTokenList();
event.preventDefault();
return false;
});
$("body").on('click',".revoke-token",function(event){
var link = $(this);
var value = link.attr('data-value');
var hint = link.attr('data-hint');
var url = link.attr('href');
var table_id = hint ==='refresh-token'? 'table-refresh-tokens':'table-access-tokens';
var info_id = hint ==='refresh-token'? 'info-refresh-tokens':'info-access-tokens';
var confirm_msg = hint ==='refresh-token'? 'Are you sure?, revoking this refresh token also will become void all related Access Tokens':'Are you sure?';
if(confirm(confirm_msg)){
$.ajax(
{
type: "GET",
url: url,
dataType: "json",
timeout:60000,
success: function (data,textStatus,jqXHR) {
//load data...
if(data.status==='OK'){
var row = $('#'+value);
row.remove();
var row_qty = $('#'+table_id+' tr').length;
if(row_qty===1){ //only we have the header ...
$('#'+table_id).remove();
$('#'+info_id).show();
}
if(hint=='refresh-token'){
refreshAccessTokenList();
}
}
else{
alert('There was an error!');
}
},
error: function (jqXHR, textStatus, errorThrown) {
alert( "Request failed: " + textStatus );
}
}
);
}
event.preventDefault();
return false;
});
});
</script>
@stop

View File

@ -0,0 +1,54 @@
@extends('layout')
@section('title')
<title>Welcome to openstackId - Edit Registered Application</title>
@stop
@section('content')
<a href="{{ URL::previous() }}">Go Back</a>
<legend>{{ $client->app_name }}</legend>
@if($errors->any())
<div class="errors">
<ul>
@foreach($errors->all() as $error)
<div class="alert alert-error">
<button type="button" class="close" data-dismiss="alert">&times;</button>
{{ $error }}
</div>
@endforeach
</ul>
</div>
@endif
<div id="accordion">
<h3><i class="icon-info-sign accordion-toggle" title="OAuth2 Client ID and Client Secret"></i>&nbsp;OAuth 2.0 Client ID</h3>
@include('oauth2.profile.edit-client-data',array('access_tokens' => $access_tokens, 'refresh_tokens' => $refresh_tokens,'client'=>$client,'allowed_uris'=>$allowed_uris))
<h3><i class="icon-info-sign accordion-toggle" title="Authorized Client Redirection Uris"></i>&nbsp;Authorized Redirection Uris</h3>
@include('oauth2.profile.edit-client-redirect-uris',array('access_tokens' => $access_tokens, 'refresh_tokens' => $refresh_tokens,'client'=>$client,'allowed_uris'=>$allowed_uris))
<h3><i class="icon-info-sign accordion-toggle" title="Application Allowed Scopes"></i>&nbsp;Application Allowed Scopes</h3>
@include('oauth2.profile.edit-client-scopes',array('access_tokens' => $access_tokens, 'refresh_tokens' => $refresh_tokens,'client'=>$client) )
<h3><i class="icon-info-sign accordion-toggle" title="Application Grants"></i>&nbsp;Application Grants</h3>
@include('oauth2.profile.edit-client-tokens',array('access_tokens' => $access_tokens, 'refresh_tokens' => $refresh_tokens,'client'=>$client) )
</div>
@stop
@section('scripts')
<script type="application/javascript">
function displayAlert(msg,after){
$('.alert-error').remove();
var alert = $('<div class="alert alert-error"><button type="button" class="close" data-dismiss="alert">&times;</button>'+msg+'</div>');
alert.insertAfter(after);
}
$(document).ready(function() {
$( "#accordion" ).accordion({
collapsible: true,
heightStyle: "content"
});
});
</script>
@stop

View File

@ -19,8 +19,8 @@ Welcome, <a href="{{ URL::action("UserController@getProfile") }}">{{Auth::user()
</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) }}" target='_blank'>{{ str_replace("%23","#",$openid_url) }}</a> is your identity URL</p>
@foreach ($views as $view)
{{ $view}}
@foreach ($views as $partial)
@include($partial->getName(),$partial->getData())
@endforeach
<div>
<label class="radio">

View File

@ -10,7 +10,7 @@
<div class="row-fluid">
<div class="span12">
Hello, {{{ $username }}}.
<a class="btn btn-small" href="{{ URL::action("UserController@logout") }}"">logout</a>
<a class="btn btn-small" href="{{ URL::action("UserController@logout") }}">logout</a>
<div>Your OPENID: <a href="{{ str_replace("%23","#",$openid_url) }}">{{ str_replace("%23","#",$openid_url) }}</a></div>
</div>
</div>