public clients
This commit is contained in:
parent
d7b616773a
commit
599faa3cb5
43 changed files with 570 additions and 258 deletions
|
@ -2,13 +2,13 @@
|
||||||
<div id="content-area" class="col-md-9" role="main">
|
<div id="content-area" class="col-md-9" role="main">
|
||||||
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}">Settings</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}">Settings</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/credentials">Credentials</a></li>
|
<li data-ng-show="!application.bearerOnly && !application.publicClient"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/credentials">Credentials</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/installation">Installation</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/installation">Installation</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/roles">Roles</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/roles">Roles</a></li>
|
||||||
<li class="active"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/claims">Claims</a></li>
|
<li class="active"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/claims">Claims</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/scope-mappings">Scope</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/scope-mappings">Scope</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/revocation">Revocation</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/revocation">Revocation</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/sessions">Sessions</a></li>
|
<li data-ng-show="!application.bearerOnly"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/sessions">Sessions</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<ol class="breadcrumb" data-ng-hide="create">
|
<ol class="breadcrumb" data-ng-hide="create">
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/claims">Claims</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/claims">Claims</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/scope-mappings">Scope</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/scope-mappings">Scope</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/revocation">Revocation</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/revocation">Revocation</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/sessions">Sessions</a></li>
|
<li data-ng-show="!application.bearerOnly"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/sessions">Sessions</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<ol class="breadcrumb" data-ng-hide="create">
|
<ol class="breadcrumb" data-ng-hide="create">
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
<div id="content-area" class="col-md-9" role="main">
|
<div id="content-area" class="col-md-9" role="main">
|
||||||
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
||||||
<li class="active"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}">Settings</a></li>
|
<li class="active"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}">Settings</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/credentials">Credentials</a></li>
|
<li data-ng-show="!application.bearerOnly && !application.publicClient"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/credentials">Credentials</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/installation">Installation</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/installation">Installation</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/roles">Roles</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/roles">Roles</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/claims">Claims</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/claims">Claims</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/scope-mappings">Scope</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/scope-mappings">Scope</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/revocation">Revocation</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/revocation">Revocation</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/sessions">Sessions</a></li>
|
<li data-ng-show="!application.bearerOnly"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/sessions">Sessions</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<ol class="breadcrumb" data-ng-show="create">
|
<ol class="breadcrumb" data-ng-show="create">
|
||||||
|
@ -39,6 +39,44 @@
|
||||||
<input ng-model="application.enabled" name="enabled" id="enabled" onoffswitch />
|
<input ng-model="application.enabled" name="enabled" id="enabled" onoffswitch />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group clearfix block" data-ng-show="!application.publicClient">
|
||||||
|
<label class="col-sm-2 control-label" for="bearerOnly">Bearer Only</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input ng-model="application.bearerOnly" name="bearerOnly" id="bearerOnly" onoffswitch />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group clearfix block">
|
||||||
|
<label class="col-sm-2 control-label" for="publicClient">Public Client</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input ng-model="application.publicClient" name="publicClient" id="publicClient" onoffswitch />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group" data-ng-show="!application.bearerOnly">
|
||||||
|
<label class="col-sm-2 control-label" for="newRedirectUri">Redirect URI <span class="required" data-ng-show="create">*</span></label>
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<div ng-repeat="redirectUri in application.redirectUris" class="row kc-item-deletable">
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input class="form-control" type="text" data-ng-class="{'input-below':!$first}"
|
||||||
|
name="redirectUri" id="redirectUri" data-ng-model="redirectUri" readonly />
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<button class="btn btn-danger" type="button" data-ng-click="deleteRedirectUri($index)">
|
||||||
|
Delete</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-8">
|
||||||
|
<input class="form-control" type="text" name="newRedirectUri" id="newRedirectUri"
|
||||||
|
placeholder="New Redirect URI..." data-ng-model="newRedirectUri"
|
||||||
|
data-ng-class="{'input-below':application.redirectUris.length}" />
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<button class="btn btn-primary" data-ng-click="addRedirectUri()" ng-show="newRedirectUri.length > 0">Add</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-2 control-label" for="baseUrl">Base URL</label>
|
<label class="col-sm-2 control-label" for="baseUrl">Base URL</label>
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-4">
|
||||||
|
@ -55,9 +93,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-2 control-label" for="newWebOrigin">Web Origin</label>
|
<label class="col-sm-2 control-label" for="newWebOrigin">Web Origin</label>
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-6">
|
||||||
<div ng-repeat="webOrigin in application.webOrigins" class="row kc-item-deletable">
|
<div ng-repeat="webOrigin in application.webOrigins" class="row kc-item-deletable">
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-8">
|
||||||
<input class="form-control kc-button-control"
|
<input class="form-control kc-button-control"
|
||||||
type="text" data-ng-class="{'input-below':!$first}"
|
type="text" data-ng-class="{'input-below':!$first}"
|
||||||
name="webOrigin" id="webOrigin"
|
name="webOrigin" id="webOrigin"
|
||||||
|
@ -69,7 +107,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-8">
|
||||||
<input class="form-control kc-button-control"
|
<input class="form-control kc-button-control"
|
||||||
type="text" name="newWebOrigin" id="newWebOrigin"
|
type="text" name="newWebOrigin" id="newWebOrigin"
|
||||||
placeholder="New Web Origin..." data-ng-model="newWebOrigin"
|
placeholder="New Web Origin..." data-ng-model="newWebOrigin"
|
||||||
|
@ -82,32 +120,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
|
||||||
<label class="col-sm-2 control-label" for="newRedirectUri">Redirect URI</label>
|
|
||||||
<div class="col-sm-4">
|
|
||||||
<div ng-repeat="redirectUri in application.redirectUris" class="row kc-item-deletable">
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input class="form-control" type="text" data-ng-class="{'input-below':!$first}"
|
|
||||||
name="redirectUri" id="redirectUri" data-ng-model="redirectUri" readonly />
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-2">
|
|
||||||
<button class="btn btn-danger" type="button" data-ng-click="deleteRedirectUri($index)">
|
|
||||||
Delete</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input class="form-control" type="text" name="newRedirectUri" id="newRedirectUri"
|
|
||||||
placeholder="New Redirect URI..." data-ng-model="newRedirectUri"
|
|
||||||
data-ng-class="{'input-below':application.redirectUris.length}" />
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-2">
|
|
||||||
<button class="btn btn-primary" data-ng-click="addRedirectUri()" ng-show="newRedirectUri.length > 0">Add</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<div class="pull-right form-actions" data-ng-show="create && access.manageApplications">
|
<div class="pull-right form-actions" data-ng-show="create && access.manageApplications">
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
|
|
||||||
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}">Settings</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}">Settings</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/credentials">Credentials</a></li>
|
<li data-ng-show="!application.bearerOnly && !application.publicClient"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/credentials">Credentials</a></li>
|
||||||
<li class="active"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/installation">Installation</a></li>
|
<li class="active"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/installation">Installation</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/roles">Roles</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/roles">Roles</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/claims">Claims</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/claims">Claims</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/scope-mappings">Scope</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/scope-mappings">Scope</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/revocation">Revocation</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/revocation">Revocation</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/sessions">Sessions</a></li>
|
<li data-ng-show="!application.bearerOnly"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/sessions">Sessions</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div class="top-nav" data-ng-show="create">
|
<div class="top-nav" data-ng-show="create">
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
<div id="content-area" class="col-md-9" role="main">
|
<div id="content-area" class="col-md-9" role="main">
|
||||||
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}">Settings</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}">Settings</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/credentials">Credentials</a></li>
|
<li data-ng-show="!application.bearerOnly && !application.publicClient"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/credentials">Credentials</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/installation">Installation</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/installation">Installation</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/roles">Roles</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/roles">Roles</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/claims">Claims</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/claims">Claims</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/scope-mappings">Scope</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/scope-mappings">Scope</a></li>
|
||||||
<li class="active"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/revocation">Revocation</a></li>
|
<li class="active"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/revocation">Revocation</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/sessions">Sessions</a></li>
|
<li data-ng-show="!application.bearerOnly"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/sessions">Sessions</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<div id="content">
|
<div id="content">
|
||||||
<ol class="breadcrumb">
|
<ol class="breadcrumb">
|
||||||
|
|
|
@ -2,13 +2,13 @@
|
||||||
<div id="content-area" class="col-md-9" role="main">
|
<div id="content-area" class="col-md-9" role="main">
|
||||||
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}">Settings</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}">Settings</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/credentials">Credentials</a></li>
|
<li data-ng-show="!application.bearerOnly && !application.publicClient"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/credentials">Credentials</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/installation">Installation</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/installation">Installation</a></li>
|
||||||
<li class="active"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/roles">Roles</a></li>
|
<li class="active"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/roles">Roles</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/claims">Claims</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/claims">Claims</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/scope-mappings">Scope</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/scope-mappings">Scope</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/revocation">Revocation</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/revocation">Revocation</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/sessions">Sessions</a></li>
|
<li data-ng-show="!application.bearerOnly"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/sessions">Sessions</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div id="content">
|
<div id="content">
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
|
|
||||||
<ul class="nav nav-tabs nav-tabs-pf">
|
<ul class="nav nav-tabs nav-tabs-pf">
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}">Settings</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}">Settings</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/credentials">Credentials</a></li>
|
<li data-ng-show="!application.bearerOnly && !application.publicClient"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/credentials">Credentials</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/installation">Installation</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/installation">Installation</a></li>
|
||||||
<li class="active"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/roles">Roles</a></li>
|
<li class="active"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/roles">Roles</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/claims">Claims</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/claims">Claims</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/scope-mappings">Scope</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/scope-mappings">Scope</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/revocation">Revocation</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/revocation">Revocation</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/sessions">Sessions</a></li>
|
<li data-ng-show="!application.bearerOnly"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/sessions">Sessions</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div id="content">
|
<div id="content">
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
|
|
||||||
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}">Settings</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}">Settings</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/credentials">Credentials</a></li>
|
<li data-ng-show="!application.bearerOnly && !application.publicClient"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/credentials">Credentials</a></li>
|
||||||
<li><a href="#">Installation</a></li>
|
<li><a href="#">Installation</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/roles">Roles</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/roles">Roles</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/claims">Claims</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/claims">Claims</a></li>
|
||||||
<li class="active"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/scope-mappings">Scope</a></li>
|
<li class="active"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/scope-mappings">Scope</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/revocation">Revocation</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/revocation">Revocation</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/sessions">Sessions</a></li>
|
<li data-ng-show="!application.bearerOnly"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/sessions">Sessions</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div id="content">
|
<div id="content">
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div id="content-area" class="col-md-9" role="main">
|
<div id="content-area" class="col-md-9" role="main">
|
||||||
<ul class="nav nav-tabs nav-tabs-pf">
|
<ul class="nav nav-tabs nav-tabs-pf">
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}">Settings</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}">Settings</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/credentials">Credentials</a></li>
|
<li data-ng-show="!application.bearerOnly && !application.publicClient"><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/credentials">Credentials</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/installation">Installation</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/installation">Installation</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/roles">Roles</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/roles">Roles</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/claims">Claims</a></li>
|
<li><a href="#/realms/{{realm.realm}}/applications/{{application.name}}/claims">Claims</a></li>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div id="content-area" class="col-md-9" role="main">
|
<div id="content-area" class="col-md-9" role="main">
|
||||||
<ul class="nav nav-tabs nav-tabs-pf">
|
<ul class="nav nav-tabs nav-tabs-pf">
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}">Settings</a></li>
|
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}">Settings</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
|
<li data-ng-show="!oauth.publicClient"><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
|
||||||
<li class="active"><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/claims">Claims</a></li>
|
<li class="active"><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/claims">Claims</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
|
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
|
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div id="content-area" class="col-md-9" role="main">
|
<div id="content-area" class="col-md-9" role="main">
|
||||||
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
||||||
<li class="active"><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}">Settings</a></li>
|
<li class="active"><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}">Settings</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
|
<li data-ng-show="!oauth.publicClient"><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/claims">Claims</a></li>
|
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/claims">Claims</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
|
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
|
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
|
||||||
|
@ -40,6 +40,37 @@
|
||||||
<input ng-model="oauth.enabled" name="enabled" id="enabled" onoffswitch />
|
<input ng-model="oauth.enabled" name="enabled" id="enabled" onoffswitch />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group clearfix block">
|
||||||
|
<label class="col-sm-2 control-label" for="publicClient">Public Client</label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<input ng-model="oauth.publicClient" name="publicClient" id="publicClient" onoffswitch />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-sm-2 control-label" for="newRedirectUri">Redirect URI <span class="required" data-ng-show="create">*</span></label>
|
||||||
|
<div class="col-sm-4">
|
||||||
|
<div ng-repeat="redirectUri in oauth.redirectUris" class="kc-item-deletable row">
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input class="form-control" type="text" data-ng-class="{'input-below':!$first}"
|
||||||
|
name="redirectUri" id="redirectUri" data-ng-model="redirectUri" readonly />
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<button class="btn btn-danger" type="button" data-ng-click="deleteRedirectUri($index)">
|
||||||
|
Delete</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<input class="form-control" type="text" name="newRedirectUri" id="newRedirectUri"
|
||||||
|
placeholder="New Redirect URI..." data-ng-model="newRedirectUri"
|
||||||
|
data-ng-class="{'input-below':oauth.redirectUris.length}" />
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-2">
|
||||||
|
<button class="btn btn-primary" data-ng-click="addRedirectUri()" ng-show="newRedirectUri.length > 0">Add</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="col-sm-2 control-label" for="newWebOrigin">Web Origin</label>
|
<label class="col-sm-2 control-label" for="newWebOrigin">Web Origin</label>
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-4">
|
||||||
|
@ -65,31 +96,6 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
|
||||||
<label class="col-sm-2 control-label" for="newRedirectUri">Redirect URI</label>
|
|
||||||
<div class="col-sm-4">
|
|
||||||
<div ng-repeat="redirectUri in oauth.redirectUris" class="kc-item-deletable row">
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input class="form-control" type="text" data-ng-class="{'input-below':!$first}"
|
|
||||||
name="redirectUri" id="redirectUri" data-ng-model="redirectUri" readonly />
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-2">
|
|
||||||
<button class="btn btn-danger" type="button" data-ng-click="deleteRedirectUri($index)">
|
|
||||||
Delete</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-sm-9">
|
|
||||||
<input class="form-control" type="text" name="newRedirectUri" id="newRedirectUri"
|
|
||||||
placeholder="New Redirect URI..." data-ng-model="newRedirectUri"
|
|
||||||
data-ng-class="{'input-below':oauth.redirectUris.length}" />
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-2">
|
|
||||||
<button class="btn btn-primary" data-ng-click="addRedirectUri()" ng-show="newRedirectUri.length > 0">Add</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<div class="pull-right form-actions" data-ng-show="create && access.manageClients">
|
<div class="pull-right form-actions" data-ng-show="create && access.manageClients">
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div id="content-area" class="col-md-9" role="main">
|
<div id="content-area" class="col-md-9" role="main">
|
||||||
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}">Settings</a></li>
|
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}">Settings</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
|
<li data-ng-show="!oauth.publicClient"><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/claims">Claims</a></li>
|
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/claims">Claims</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
|
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
|
||||||
<li class="active"><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
|
<li class="active"><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div id="content-area" class="col-md-9" role="main">
|
<div id="content-area" class="col-md-9" role="main">
|
||||||
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}">Settings</a></li>
|
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}">Settings</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
|
<li data-ng-show="!oauth.publicClient"><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/claims">Claims</a></li>
|
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/claims">Claims</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
|
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
|
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}">Settings</a></li>
|
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}">Settings</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
|
<li data-ng-show="!oauth.publicClient"><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/claims">Claims</a></li>
|
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/claims">Claims</a></li>
|
||||||
<li class="active"><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
|
<li class="active"><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
|
||||||
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
|
<li><a href="#/realms/{{realm.realm}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
|
||||||
|
|
|
@ -23,6 +23,7 @@ public class AbstractOAuthClient {
|
||||||
protected String stateCookieName = OAUTH_TOKEN_REQUEST_STATE;
|
protected String stateCookieName = OAUTH_TOKEN_REQUEST_STATE;
|
||||||
protected String stateCookiePath;
|
protected String stateCookiePath;
|
||||||
protected boolean isSecure;
|
protected boolean isSecure;
|
||||||
|
protected boolean publicClient;
|
||||||
protected final AtomicLong counter = new AtomicLong();
|
protected final AtomicLong counter = new AtomicLong();
|
||||||
|
|
||||||
protected String getStateCode() {
|
protected String getStateCode() {
|
||||||
|
@ -103,6 +104,14 @@ public class AbstractOAuthClient {
|
||||||
this.stateCookiePath = stateCookiePath;
|
this.stateCookiePath = stateCookiePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPublicClient() {
|
||||||
|
return publicClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPublicClient(boolean publicClient) {
|
||||||
|
this.publicClient = publicClient;
|
||||||
|
}
|
||||||
|
|
||||||
protected String stripOauthParametersFromRedirect(String uri) {
|
protected String stripOauthParametersFromRedirect(String uri) {
|
||||||
KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(uri)
|
KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(uri)
|
||||||
.replaceQueryParam("code", null)
|
.replaceQueryParam("code", null)
|
||||||
|
|
|
@ -14,7 +14,7 @@ import java.util.Map;
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-not-required",
|
@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-not-required",
|
||||||
"resource", "credentials",
|
"resource", "public-client", "credentials",
|
||||||
"use-resource-role-mappings",
|
"use-resource-role-mappings",
|
||||||
"enable-cors", "cors-max-age", "cors-allowed-methods",
|
"enable-cors", "cors-max-age", "cors-allowed-methods",
|
||||||
"expose-token", "bearer-only", "scope"})
|
"expose-token", "bearer-only", "scope"})
|
||||||
|
@ -35,6 +35,8 @@ public class BaseAdapterConfig extends BaseRealmConfig {
|
||||||
protected boolean exposeToken;
|
protected boolean exposeToken;
|
||||||
@JsonProperty("bearer-only")
|
@JsonProperty("bearer-only")
|
||||||
protected boolean bearerOnly;
|
protected boolean bearerOnly;
|
||||||
|
@JsonProperty("public-client")
|
||||||
|
protected boolean publicClient;
|
||||||
@JsonProperty("credentials")
|
@JsonProperty("credentials")
|
||||||
protected Map<String, String> credentials = new HashMap<String, String>();
|
protected Map<String, String> credentials = new HashMap<String, String>();
|
||||||
@JsonProperty("scope")
|
@JsonProperty("scope")
|
||||||
|
@ -120,4 +122,12 @@ public class BaseAdapterConfig extends BaseRealmConfig {
|
||||||
public void setScope(AccessScope scope) {
|
public void setScope(AccessScope scope) {
|
||||||
this.scope = scope;
|
this.scope = scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPublicClient() {
|
||||||
|
return publicClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPublicClient(boolean publicClient) {
|
||||||
|
this.publicClient = publicClient;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ public class ApplicationRepresentation {
|
||||||
protected List<String> webOrigins;
|
protected List<String> webOrigins;
|
||||||
protected ClaimRepresentation claims;
|
protected ClaimRepresentation claims;
|
||||||
protected Integer notBefore;
|
protected Integer notBefore;
|
||||||
|
protected Boolean bearerOnly;
|
||||||
|
protected Boolean publicClient;
|
||||||
|
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
|
@ -117,4 +119,20 @@ public class ApplicationRepresentation {
|
||||||
public void setNotBefore(Integer notBefore) {
|
public void setNotBefore(Integer notBefore) {
|
||||||
this.notBefore = notBefore;
|
this.notBefore = notBefore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean isBearerOnly() {
|
||||||
|
return bearerOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBearerOnly(Boolean bearerOnly) {
|
||||||
|
this.bearerOnly = bearerOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean isPublicClient() {
|
||||||
|
return publicClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPublicClient(Boolean publicClient) {
|
||||||
|
this.publicClient = publicClient;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ public class OAuthClientRepresentation {
|
||||||
protected String secret;
|
protected String secret;
|
||||||
protected ClaimRepresentation claims;
|
protected ClaimRepresentation claims;
|
||||||
protected Integer notBefore;
|
protected Integer notBefore;
|
||||||
|
protected Boolean publicClient;
|
||||||
|
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
|
@ -89,4 +90,12 @@ public class OAuthClientRepresentation {
|
||||||
public void setNotBefore(Integer notBefore) {
|
public void setNotBefore(Integer notBefore) {
|
||||||
this.notBefore = notBefore;
|
this.notBefore = notBefore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean isPublicClient() {
|
||||||
|
return publicClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPublicClient(Boolean publicClient) {
|
||||||
|
this.publicClient = publicClient;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,8 @@ public class JsonSerialization {
|
||||||
public static final ObjectMapper prettyMapper = new ObjectMapper();
|
public static final ObjectMapper prettyMapper = new ObjectMapper();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
|
|
||||||
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
|
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
|
||||||
prettyMapper.enable(SerializationConfig.Feature.INDENT_OUTPUT);
|
prettyMapper.enable(SerializationConfig.Feature.INDENT_OUTPUT);
|
||||||
prettyMapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
|
|
||||||
prettyMapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
|
prettyMapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,12 +62,18 @@
|
||||||
"name": "customer-portal",
|
"name": "customer-portal",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"adminUrl": "http://localhost:8080/customer-portal",
|
"adminUrl": "http://localhost:8080/customer-portal",
|
||||||
|
"redirectUris": [
|
||||||
|
"http://localhost:8080/customer-portal/*"
|
||||||
|
],
|
||||||
"secret": "password"
|
"secret": "password"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "product-portal",
|
"name": "product-portal",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"adminUrl": "http://localhost:8080/product-portal",
|
"adminUrl": "http://localhost:8080/product-portal",
|
||||||
|
"redirectUris": [
|
||||||
|
"http://localhost:8080/product-portal/*"
|
||||||
|
],
|
||||||
"secret": "password"
|
"secret": "password"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
@ -75,6 +81,10 @@
|
||||||
{
|
{
|
||||||
"name": "third-party",
|
"name": "third-party",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
|
"redirectUris": [
|
||||||
|
"http://localhost:8080/oauth-client/*",
|
||||||
|
"http://localhost:8080/oauth-client-cdi/*"
|
||||||
|
],
|
||||||
"secret": "password"
|
"secret": "password"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -9,6 +9,7 @@ import org.apache.http.client.methods.HttpPost;
|
||||||
import org.apache.http.message.BasicNameValuePair;
|
import org.apache.http.message.BasicNameValuePair;
|
||||||
import org.keycloak.adapters.config.RealmConfiguration;
|
import org.keycloak.adapters.config.RealmConfiguration;
|
||||||
import org.keycloak.representations.AccessTokenResponse;
|
import org.keycloak.representations.AccessTokenResponse;
|
||||||
|
import org.keycloak.representations.adapters.config.AdapterConfig;
|
||||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
import org.keycloak.util.BasicAuthHelper;
|
import org.keycloak.util.BasicAuthHelper;
|
||||||
import org.keycloak.util.JsonSerialization;
|
import org.keycloak.util.JsonSerialization;
|
||||||
|
@ -52,24 +53,28 @@ public class ServerRequest {
|
||||||
Map<String, String> credentials = config.getResourceCredentials();
|
Map<String, String> credentials = config.getResourceCredentials();
|
||||||
HttpClient client = config.getClient();
|
HttpClient client = config.getClient();
|
||||||
|
|
||||||
return invokeAccessCodeToToken(client, code, codeUrl, redirectUri, client_id, credentials);
|
return invokeAccessCodeToToken(client, config.isPublicClient(), code, codeUrl, redirectUri, client_id, credentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AccessTokenResponse invokeAccessCodeToToken(HttpClient client, String code, String codeUrl, String redirectUri, String client_id, Map<String, String> credentials) throws IOException, HttpFailure {
|
public static AccessTokenResponse invokeAccessCodeToToken(HttpClient client, boolean publicClient, String code, String codeUrl, String redirectUri, String client_id, Map<String, String> credentials) throws IOException, HttpFailure {
|
||||||
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
|
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
|
||||||
redirectUri = stripOauthParametersFromRedirect(redirectUri);
|
redirectUri = stripOauthParametersFromRedirect(redirectUri);
|
||||||
formparams.add(new BasicNameValuePair("grant_type", "authorization_code"));
|
formparams.add(new BasicNameValuePair("grant_type", "authorization_code"));
|
||||||
formparams.add(new BasicNameValuePair("code", code));
|
formparams.add(new BasicNameValuePair("code", code));
|
||||||
formparams.add(new BasicNameValuePair("redirect_uri", redirectUri));
|
formparams.add(new BasicNameValuePair("redirect_uri", redirectUri));
|
||||||
HttpResponse response = null;
|
HttpResponse response = null;
|
||||||
UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
|
|
||||||
HttpPost post = new HttpPost(codeUrl);
|
HttpPost post = new HttpPost(codeUrl);
|
||||||
|
if (!publicClient) {
|
||||||
String clientSecret = credentials.get(CredentialRepresentation.SECRET);
|
String clientSecret = credentials.get(CredentialRepresentation.SECRET);
|
||||||
if (clientSecret != null) {
|
if (clientSecret != null) {
|
||||||
String authorization = BasicAuthHelper.createHeader(client_id, clientSecret);
|
String authorization = BasicAuthHelper.createHeader(client_id, clientSecret);
|
||||||
post.setHeader("Authorization", authorization);
|
post.setHeader("Authorization", authorization);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
formparams.add(new BasicNameValuePair("client_id", client_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
|
||||||
post.setEntity(form);
|
post.setEntity(form);
|
||||||
response = client.execute(post);
|
response = client.execute(post);
|
||||||
int status = response.getStatusLine().getStatusCode();
|
int status = response.getStatusLine().getStatusCode();
|
||||||
|
@ -108,11 +113,11 @@ public class ServerRequest {
|
||||||
String client_id = config.getMetadata().getResourceName();
|
String client_id = config.getMetadata().getResourceName();
|
||||||
Map<String, String> credentials = config.getResourceCredentials();
|
Map<String, String> credentials = config.getResourceCredentials();
|
||||||
HttpClient client = config.getClient();
|
HttpClient client = config.getClient();
|
||||||
return invokeRefresh(client, refreshToken, refreshUrl, client_id, credentials);
|
return invokeRefresh(client, config.isPublicClient(), refreshToken, refreshUrl, client_id, credentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static AccessTokenResponse invokeRefresh(HttpClient client, String refreshToken, String refreshUrl, String client_id, Map<String, String> credentials) throws IOException, HttpFailure {
|
public static AccessTokenResponse invokeRefresh(HttpClient client, boolean publicClient, String refreshToken, String refreshUrl, String client_id, Map<String, String> credentials) throws IOException, HttpFailure {
|
||||||
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
|
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
|
||||||
for (Map.Entry<String, String> entry : credentials.entrySet()) {
|
for (Map.Entry<String, String> entry : credentials.entrySet()) {
|
||||||
formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
|
formparams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
|
||||||
|
@ -120,14 +125,18 @@ public class ServerRequest {
|
||||||
formparams.add(new BasicNameValuePair("grant_type", "refresh_token"));
|
formparams.add(new BasicNameValuePair("grant_type", "refresh_token"));
|
||||||
formparams.add(new BasicNameValuePair("refresh_token", refreshToken));
|
formparams.add(new BasicNameValuePair("refresh_token", refreshToken));
|
||||||
HttpResponse response = null;
|
HttpResponse response = null;
|
||||||
UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
|
|
||||||
HttpPost post = new HttpPost(refreshUrl);
|
HttpPost post = new HttpPost(refreshUrl);
|
||||||
|
if (!publicClient) {
|
||||||
String clientSecret = credentials.get(CredentialRepresentation.SECRET);
|
String clientSecret = credentials.get(CredentialRepresentation.SECRET);
|
||||||
if (clientSecret != null) {
|
if (clientSecret != null) {
|
||||||
String authorization = BasicAuthHelper.createHeader(client_id, clientSecret);
|
String authorization = BasicAuthHelper.createHeader(client_id, clientSecret);
|
||||||
post.setHeader("Authorization", authorization);
|
post.setHeader("Authorization", authorization);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
formparams.add(new BasicNameValuePair("client_id", client_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
|
||||||
post.setEntity(form);
|
post.setEntity(form);
|
||||||
response = client.execute(post);
|
response = client.execute(post);
|
||||||
int status = response.getStatusLine().getStatusCode();
|
int status = response.getStatusLine().getStatusCode();
|
||||||
|
@ -189,5 +198,4 @@ public class ServerRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ public abstract class OAuthClientConfigLoader extends RealmConfigurationLoader {
|
||||||
|
|
||||||
public void configureOAuthClient(AbstractOAuthClient oauthClient) {
|
public void configureOAuthClient(AbstractOAuthClient oauthClient) {
|
||||||
oauthClient.setClientId(adapterConfig.getResource());
|
oauthClient.setClientId(adapterConfig.getResource());
|
||||||
|
oauthClient.setPublicClient(adapterConfig.isPublicClient());
|
||||||
oauthClient.setCredentials(adapterConfig.getCredentials());
|
oauthClient.setCredentials(adapterConfig.getCredentials());
|
||||||
if (adapterConfig.getAuthServerUrl() == null) {
|
if (adapterConfig.getAuthServerUrl() == null) {
|
||||||
throw new RuntimeException("You must specify auth-url");
|
throw new RuntimeException("You must specify auth-url");
|
||||||
|
|
|
@ -17,6 +17,7 @@ public class RealmConfiguration {
|
||||||
protected KeycloakUriBuilder authUrl;
|
protected KeycloakUriBuilder authUrl;
|
||||||
protected String codeUrl;
|
protected String codeUrl;
|
||||||
protected String refreshUrl;
|
protected String refreshUrl;
|
||||||
|
protected boolean publicClient;
|
||||||
protected Map<String, String> resourceCredentials = new HashMap<String, String>();
|
protected Map<String, String> resourceCredentials = new HashMap<String, String>();
|
||||||
protected boolean sslRequired = true;
|
protected boolean sslRequired = true;
|
||||||
protected String stateCookieName = "OAuth_Token_Request_State";
|
protected String stateCookieName = "OAuth_Token_Request_State";
|
||||||
|
@ -97,4 +98,12 @@ public class RealmConfiguration {
|
||||||
public void setNotBefore(int notBefore) {
|
public void setNotBefore(int notBefore) {
|
||||||
this.notBefore = notBefore;
|
this.notBefore = notBefore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPublicClient() {
|
||||||
|
return publicClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPublicClient(boolean publicClient) {
|
||||||
|
this.publicClient = publicClient;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ public class RealmConfigurationLoader extends AdapterConfigLoader {
|
||||||
realmConfiguration.setMetadata(resourceMetadata);
|
realmConfiguration.setMetadata(resourceMetadata);
|
||||||
realmConfiguration.setSslRequired(!adapterConfig.isSslNotRequired());
|
realmConfiguration.setSslRequired(!adapterConfig.isSslNotRequired());
|
||||||
realmConfiguration.setResourceCredentials(adapterConfig.getCredentials());
|
realmConfiguration.setResourceCredentials(adapterConfig.getCredentials());
|
||||||
|
realmConfiguration.setPublicClient(adapterConfig.isPublicClient());
|
||||||
if (!setupClient || adapterConfig.isBearerOnly()) return;
|
if (!setupClient || adapterConfig.isBearerOnly()) return;
|
||||||
initClient();
|
initClient();
|
||||||
if (adapterConfig.getAuthServerUrl() == null) {
|
if (adapterConfig.getAuthServerUrl() == null) {
|
||||||
|
|
|
@ -67,6 +67,12 @@ public class SecureDeploymentDefinition extends SimpleResourceDefinition {
|
||||||
.setAllowExpression(true)
|
.setAllowExpression(true)
|
||||||
.setDefaultValue(new ModelNode(false))
|
.setDefaultValue(new ModelNode(false))
|
||||||
.build();
|
.build();
|
||||||
|
protected static final SimpleAttributeDefinition PUBLIC_CLIENT =
|
||||||
|
new SimpleAttributeDefinitionBuilder("bearer-only", ModelType.BOOLEAN, true)
|
||||||
|
.setXmlName("bearer-only")
|
||||||
|
.setAllowExpression(true)
|
||||||
|
.setDefaultValue(new ModelNode(false))
|
||||||
|
.build();
|
||||||
|
|
||||||
protected static final List<SimpleAttributeDefinition> DEPLOYMENT_ONLY_ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
|
protected static final List<SimpleAttributeDefinition> DEPLOYMENT_ONLY_ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
|
||||||
static {
|
static {
|
||||||
|
@ -74,6 +80,7 @@ public class SecureDeploymentDefinition extends SimpleResourceDefinition {
|
||||||
DEPLOYMENT_ONLY_ATTRIBUTES.add(RESOURCE);
|
DEPLOYMENT_ONLY_ATTRIBUTES.add(RESOURCE);
|
||||||
DEPLOYMENT_ONLY_ATTRIBUTES.add(USE_RESOURCE_ROLE_MAPPINGS);
|
DEPLOYMENT_ONLY_ATTRIBUTES.add(USE_RESOURCE_ROLE_MAPPINGS);
|
||||||
DEPLOYMENT_ONLY_ATTRIBUTES.add(BEARER_ONLY);
|
DEPLOYMENT_ONLY_ATTRIBUTES.add(BEARER_ONLY);
|
||||||
|
DEPLOYMENT_ONLY_ATTRIBUTES.add(PUBLIC_CLIENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static final List<SimpleAttributeDefinition> ALL_ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
|
protected static final List<SimpleAttributeDefinition> ALL_ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
|
||||||
|
|
|
@ -7,51 +7,52 @@ keycloak.subsystem.secure-deployment=A deployment secured by Keycloak.
|
||||||
keycloak.realm=A Keycloak realm.
|
keycloak.realm=A Keycloak realm.
|
||||||
keycloak.realm.add=Add a realm definition to the subsystem.
|
keycloak.realm.add=Add a realm definition to the subsystem.
|
||||||
keycloak.realm.remove=Remove a realm from the subsystem.
|
keycloak.realm.remove=Remove a realm from the subsystem.
|
||||||
keycloak.realm.realm-public-key=TODO: fill in help text
|
keycloak.realm.realm-public-key=Public key of the realm
|
||||||
keycloak.realm.auth-server-url=TODO: fill in help text
|
keycloak.realm.auth-server-url=Base URL of the Realm Auth Server
|
||||||
keycloak.realm.disable-trust-manager=TODO: fill in help text
|
keycloak.realm.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests
|
||||||
keycloak.realm.ssl-not-required=TODO: fill in help text
|
keycloak.realm.ssl-not-required=SSL is not required for secure interactions
|
||||||
keycloak.realm.allow-any-hostname=TODO: fill in help text
|
keycloak.realm.allow-any-hostname=SSL Setting
|
||||||
keycloak.realm.truststore=TODO: fill in help text
|
keycloak.realm.truststore=Truststore used for adapter client HTTPS requests
|
||||||
keycloak.realm.truststore-password=TODO: fill in help text
|
keycloak.realm.truststore-password=Password of the Truststore
|
||||||
keycloak.realm.connection-pool-size=TODO: fill in help text
|
keycloak.realm.connection-pool-size=Connection pool size for the client used by the adapter
|
||||||
keycloak.realm.enable-cors=TODO: fill in help text
|
keycloak.realm.enable-cors=Enable Keycloak CORS support
|
||||||
keycloak.realm.client-keystore=TODO: fill in help text
|
keycloak.realm.client-keystore=n/a
|
||||||
keycloak.realm.client-keystore-password=TODO: fill in help text
|
keycloak.realm.client-keystore-password=n/a
|
||||||
keycloak.realm.client-key-password=TODO: fill in help text
|
keycloak.realm.client-key-password=n/a
|
||||||
keycloak.realm.cors-max-age=TODO: fill in help text
|
keycloak.realm.cors-max-age=CORS max-age header
|
||||||
keycloak.realm.cors-allowed-headers=TODO: fill in help text
|
keycloak.realm.cors-allowed-headers=CORS allowed headers
|
||||||
keycloak.realm.cors-allowed-methods=TODO: fill in help text
|
keycloak.realm.cors-allowed-methods=CORS allowed methods
|
||||||
keycloak.realm.expose-token=TODO: fill in help text
|
keycloak.realm.expose-token=Enable secure URL that exposes access token
|
||||||
|
|
||||||
keycloak.secure-deployment=A deployment secured by Keycloak
|
keycloak.secure-deployment=A deployment secured by Keycloak
|
||||||
keycloak.secure-deployment.add=Add a deployment to be secured by Keycloak
|
keycloak.secure-deployment.add=Add a deployment to be secured by Keycloak
|
||||||
keycloak.secure-deployment.realm=Keycloak realm
|
keycloak.secure-deployment.realm=Keycloak realm
|
||||||
keycloak.secure-deployment.remove=Remove a deployment to be secured by Keycloak
|
keycloak.secure-deployment.remove=Remove a deployment to be secured by Keycloak
|
||||||
keycloak.secure-deployment.realm-public-key=TODO: fill in help text
|
keycloak.secure-deployment.realm-public-key=Public key of the realm
|
||||||
keycloak.secure-deployment.auth-server-url=TODO: fill in help text
|
keycloak.secure-deployment.auth-server-url=Base URL of the Realm Auth Server
|
||||||
keycloak.secure-deployment.disable-trust-manager=TODO: fill in help text
|
keycloak.secure-deployment.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests
|
||||||
keycloak.secure-deployment.ssl-not-required=TODO: fill in help text
|
keycloak.secure-deployment.ssl-not-required=SSL is not required for secure interactions
|
||||||
keycloak.secure-deployment.allow-any-hostname=TODO: fill in help text
|
keycloak.secure-deployment.allow-any-hostname=SSL Setting
|
||||||
keycloak.secure-deployment.truststore=TODO: fill in help text
|
keycloak.secure-deployment.truststore=Truststore used for adapter client HTTPS requests
|
||||||
keycloak.secure-deployment.truststore-password=TODO: fill in help text
|
keycloak.secure-deployment.truststore-password=Password of the Truststore
|
||||||
keycloak.secure-deployment.connection-pool-size=TODO: fill in help text
|
keycloak.secure-deployment.connection-pool-size=Connection pool size for the client used by the adapter
|
||||||
keycloak.secure-deployment.resource=TODO: fill in help text
|
keycloak.secure-deployment.resource=Application name
|
||||||
keycloak.secure-deployment.use-resource-role-mappings=TODO: fill in help text
|
keycloak.secure-deployment.use-resource-role-mappings=Use resource level permissions from token
|
||||||
keycloak.secure-deployment.credentials=TODO: fill in help text
|
keycloak.secure-deployment.credentials=Adapter credentials
|
||||||
keycloak.secure-deployment.bearer-only=TODO: fill in help text
|
keycloak.secure-deployment.bearer-only=Bearer Token Auth only
|
||||||
keycloak.secure-deployment.enable-cors=TODO: fill in help text
|
keycloak.secure-deployment.public-client=Public client
|
||||||
keycloak.secure-deployment.client-keystore=TODO: fill in help text
|
keycloak.secure-deployment.enable-cors=Enable Keycloak CORS support
|
||||||
keycloak.secure-deployment.client-keystore-password=TODO: fill in help text
|
keycloak.secure-deployment.client-keystore=n/a
|
||||||
keycloak.secure-deployment.client-key-password=TODO: fill in help text
|
keycloak.secure-deployment.client-keystore-password=n/a
|
||||||
keycloak.secure-deployment.cors-max-age=TODO: fill in help text
|
keycloak.secure-deployment.client-key-password=n/a
|
||||||
keycloak.secure-deployment.cors-allowed-headers=TODO: fill in help text
|
keycloak.secure-deployment.cors-max-age=CORS max-age header
|
||||||
keycloak.secure-deployment.cors-allowed-methods=TODO: fill in help text
|
keycloak.secure-deployment.cors-allowed-headers=CORS allowed headers
|
||||||
keycloak.secure-deployment.expose-token=TODO: fill in help text
|
keycloak.secure-deployment.cors-allowed-methods=CORS allowed methods
|
||||||
|
keycloak.secure-deployment.expose-token=Enable secure URL that exposes access token
|
||||||
|
|
||||||
keycloak.secure-deployment.credential=TODO: fill in help text
|
keycloak.secure-deployment.credential=Credential value
|
||||||
|
|
||||||
keycloak.credential=TODO: fill in help text
|
keycloak.credential=Credential
|
||||||
keycloak.credential.value=TODO: fill in help text
|
keycloak.credential.value=Credential value
|
||||||
keycloak.credential.add=TODO: fill in help text
|
keycloak.credential.add=Credential add
|
||||||
keycloak.credential.remove=TODO: fill in help text
|
keycloak.credential.remove=Credential remove
|
|
@ -49,7 +49,7 @@ public class ServletOAuthClient extends AbstractOAuthClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccessTokenResponse resolveBearerToken(String redirectUri, String code) throws IOException, ServerRequest.HttpFailure {
|
public AccessTokenResponse resolveBearerToken(String redirectUri, String code) throws IOException, ServerRequest.HttpFailure {
|
||||||
return ServerRequest.invokeAccessCodeToToken(client, code, codeUrl, redirectUri, clientId, credentials);
|
return ServerRequest.invokeAccessCodeToToken(client, publicClient, code, codeUrl, redirectUri, clientId, credentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -155,7 +155,7 @@ public class ServletOAuthClient extends AbstractOAuthClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccessTokenResponse refreshToken(String refreshToken) throws IOException, ServerRequest.HttpFailure {
|
public AccessTokenResponse refreshToken(String refreshToken) throws IOException, ServerRequest.HttpFailure {
|
||||||
return ServerRequest.invokeRefresh(client, refreshToken, refreshUrl, clientId, credentials);
|
return ServerRequest.invokeRefresh(client, publicClient, refreshToken, refreshUrl, clientId, credentials);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IDToken extractIdToken(String idToken) {
|
public static IDToken extractIdToken(String idToken) {
|
||||||
|
|
|
@ -64,6 +64,12 @@ public class SecureDeploymentDefinition extends SimpleResourceDefinition {
|
||||||
.setAllowExpression(true)
|
.setAllowExpression(true)
|
||||||
.setDefaultValue(new ModelNode(false))
|
.setDefaultValue(new ModelNode(false))
|
||||||
.build();
|
.build();
|
||||||
|
protected static final SimpleAttributeDefinition PUBLIC_CLIENT =
|
||||||
|
new SimpleAttributeDefinitionBuilder("public-client", ModelType.BOOLEAN, true)
|
||||||
|
.setXmlName("public-client")
|
||||||
|
.setAllowExpression(true)
|
||||||
|
.setDefaultValue(new ModelNode(false))
|
||||||
|
.build();
|
||||||
|
|
||||||
protected static final List<SimpleAttributeDefinition> DEPLOYMENT_ONLY_ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
|
protected static final List<SimpleAttributeDefinition> DEPLOYMENT_ONLY_ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
|
||||||
static {
|
static {
|
||||||
|
@ -71,6 +77,7 @@ public class SecureDeploymentDefinition extends SimpleResourceDefinition {
|
||||||
DEPLOYMENT_ONLY_ATTRIBUTES.add(RESOURCE);
|
DEPLOYMENT_ONLY_ATTRIBUTES.add(RESOURCE);
|
||||||
DEPLOYMENT_ONLY_ATTRIBUTES.add(USE_RESOURCE_ROLE_MAPPINGS);
|
DEPLOYMENT_ONLY_ATTRIBUTES.add(USE_RESOURCE_ROLE_MAPPINGS);
|
||||||
DEPLOYMENT_ONLY_ATTRIBUTES.add(BEARER_ONLY);
|
DEPLOYMENT_ONLY_ATTRIBUTES.add(BEARER_ONLY);
|
||||||
|
DEPLOYMENT_ONLY_ATTRIBUTES.add(PUBLIC_CLIENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static final List<SimpleAttributeDefinition> ALL_ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
|
protected static final List<SimpleAttributeDefinition> ALL_ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
|
||||||
|
|
|
@ -7,51 +7,52 @@ keycloak.subsystem.secure-deployment=A deployment secured by Keycloak.
|
||||||
keycloak.realm=A Keycloak realm.
|
keycloak.realm=A Keycloak realm.
|
||||||
keycloak.realm.add=Add a realm definition to the subsystem.
|
keycloak.realm.add=Add a realm definition to the subsystem.
|
||||||
keycloak.realm.remove=Remove a realm from the subsystem.
|
keycloak.realm.remove=Remove a realm from the subsystem.
|
||||||
keycloak.realm.realm-public-key=TODO: fill in help text
|
keycloak.realm.realm-public-key=Public key of the realm
|
||||||
keycloak.realm.auth-server-url=TODO: fill in help text
|
keycloak.realm.auth-server-url=Base URL of the Realm Auth Server
|
||||||
keycloak.realm.disable-trust-manager=TODO: fill in help text
|
keycloak.realm.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests
|
||||||
keycloak.realm.ssl-not-required=TODO: fill in help text
|
keycloak.realm.ssl-not-required=SSL is not required for secure interactions
|
||||||
keycloak.realm.allow-any-hostname=TODO: fill in help text
|
keycloak.realm.allow-any-hostname=SSL Setting
|
||||||
keycloak.realm.truststore=TODO: fill in help text
|
keycloak.realm.truststore=Truststore used for adapter client HTTPS requests
|
||||||
keycloak.realm.truststore-password=TODO: fill in help text
|
keycloak.realm.truststore-password=Password of the Truststore
|
||||||
keycloak.realm.connection-pool-size=TODO: fill in help text
|
keycloak.realm.connection-pool-size=Connection pool size for the client used by the adapter
|
||||||
keycloak.realm.enable-cors=TODO: fill in help text
|
keycloak.realm.enable-cors=Enable Keycloak CORS support
|
||||||
keycloak.realm.client-keystore=TODO: fill in help text
|
keycloak.realm.client-keystore=n/a
|
||||||
keycloak.realm.client-keystore-password=TODO: fill in help text
|
keycloak.realm.client-keystore-password=n/a
|
||||||
keycloak.realm.client-key-password=TODO: fill in help text
|
keycloak.realm.client-key-password=n/a
|
||||||
keycloak.realm.cors-max-age=TODO: fill in help text
|
keycloak.realm.cors-max-age=CORS max-age header
|
||||||
keycloak.realm.cors-allowed-headers=TODO: fill in help text
|
keycloak.realm.cors-allowed-headers=CORS allowed headers
|
||||||
keycloak.realm.cors-allowed-methods=TODO: fill in help text
|
keycloak.realm.cors-allowed-methods=CORS allowed methods
|
||||||
keycloak.realm.expose-token=TODO: fill in help text
|
keycloak.realm.expose-token=Enable secure URL that exposes access token
|
||||||
|
|
||||||
keycloak.secure-deployment=A deployment secured by Keycloak
|
keycloak.secure-deployment=A deployment secured by Keycloak
|
||||||
keycloak.secure-deployment.add=Add a deployment to be secured by Keycloak
|
keycloak.secure-deployment.add=Add a deployment to be secured by Keycloak
|
||||||
keycloak.secure-deployment.realm=Keycloak realm
|
keycloak.secure-deployment.realm=Keycloak realm
|
||||||
keycloak.secure-deployment.remove=Remove a deployment to be secured by Keycloak
|
keycloak.secure-deployment.remove=Remove a deployment to be secured by Keycloak
|
||||||
keycloak.secure-deployment.realm-public-key=TODO: fill in help text
|
keycloak.secure-deployment.realm-public-key=Public key of the realm
|
||||||
keycloak.secure-deployment.auth-server-url=TODO: fill in help text
|
keycloak.secure-deployment.auth-server-url=Base URL of the Realm Auth Server
|
||||||
keycloak.secure-deployment.disable-trust-manager=TODO: fill in help text
|
keycloak.secure-deployment.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests
|
||||||
keycloak.secure-deployment.ssl-not-required=TODO: fill in help text
|
keycloak.secure-deployment.ssl-not-required=SSL is not required for secure interactions
|
||||||
keycloak.secure-deployment.allow-any-hostname=TODO: fill in help text
|
keycloak.secure-deployment.allow-any-hostname=SSL Setting
|
||||||
keycloak.secure-deployment.truststore=TODO: fill in help text
|
keycloak.secure-deployment.truststore=Truststore used for adapter client HTTPS requests
|
||||||
keycloak.secure-deployment.truststore-password=TODO: fill in help text
|
keycloak.secure-deployment.truststore-password=Password of the Truststore
|
||||||
keycloak.secure-deployment.connection-pool-size=TODO: fill in help text
|
keycloak.secure-deployment.connection-pool-size=Connection pool size for the client used by the adapter
|
||||||
keycloak.secure-deployment.resource=TODO: fill in help text
|
keycloak.secure-deployment.resource=Application name
|
||||||
keycloak.secure-deployment.use-resource-role-mappings=TODO: fill in help text
|
keycloak.secure-deployment.use-resource-role-mappings=Use resource level permissions from token
|
||||||
keycloak.secure-deployment.credentials=TODO: fill in help text
|
keycloak.secure-deployment.credentials=Adapter credentials
|
||||||
keycloak.secure-deployment.bearer-only=TODO: fill in help text
|
keycloak.secure-deployment.bearer-only=Bearer Token Auth only
|
||||||
keycloak.secure-deployment.enable-cors=TODO: fill in help text
|
keycloak.secure-deployment.public-client=Public client
|
||||||
keycloak.secure-deployment.client-keystore=TODO: fill in help text
|
keycloak.secure-deployment.enable-cors=Enable Keycloak CORS support
|
||||||
keycloak.secure-deployment.client-keystore-password=TODO: fill in help text
|
keycloak.secure-deployment.client-keystore=n/a
|
||||||
keycloak.secure-deployment.client-key-password=TODO: fill in help text
|
keycloak.secure-deployment.client-keystore-password=n/a
|
||||||
keycloak.secure-deployment.cors-max-age=TODO: fill in help text
|
keycloak.secure-deployment.client-key-password=n/a
|
||||||
keycloak.secure-deployment.cors-allowed-headers=TODO: fill in help text
|
keycloak.secure-deployment.cors-max-age=CORS max-age header
|
||||||
keycloak.secure-deployment.cors-allowed-methods=TODO: fill in help text
|
keycloak.secure-deployment.cors-allowed-headers=CORS allowed headers
|
||||||
keycloak.secure-deployment.expose-token=TODO: fill in help text
|
keycloak.secure-deployment.cors-allowed-methods=CORS allowed methods
|
||||||
|
keycloak.secure-deployment.expose-token=Enable secure URL that exposes access token
|
||||||
|
|
||||||
keycloak.secure-deployment.credential=TODO: fill in help text
|
keycloak.secure-deployment.credential=Credential value
|
||||||
|
|
||||||
keycloak.credential=TODO: fill in help text
|
keycloak.credential=Credential
|
||||||
keycloak.credential.value=TODO: fill in help text
|
keycloak.credential.value=Credential value
|
||||||
keycloak.credential.add=TODO: fill in help text
|
keycloak.credential.add=Credential add
|
||||||
keycloak.credential.remove=TODO: fill in help text
|
keycloak.credential.remove=Credential remove
|
|
@ -36,6 +36,9 @@ public interface ApplicationModel extends RoleContainerModel, ClientModel {
|
||||||
|
|
||||||
Set<RoleModel> getApplicationScopeMappings(ClientModel client);
|
Set<RoleModel> getApplicationScopeMappings(ClientModel client);
|
||||||
|
|
||||||
|
boolean isBearerOnly();
|
||||||
|
void setBearerOnly(boolean only);
|
||||||
|
|
||||||
void addScope(RoleModel role);
|
void addScope(RoleModel role);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,9 @@ public interface ClientModel {
|
||||||
String getSecret();
|
String getSecret();
|
||||||
public void setSecret(String secret);
|
public void setSecret(String secret);
|
||||||
|
|
||||||
|
boolean isPublicClient();
|
||||||
|
void setPublicClient(boolean flag);
|
||||||
|
|
||||||
RealmModel getRealm();
|
RealmModel getRealm();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -77,6 +77,16 @@ public class ApplicationAdapter extends ClientAdapter implements ApplicationMode
|
||||||
applicationEntity.setBaseUrl(url);
|
applicationEntity.setBaseUrl(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBearerOnly() {
|
||||||
|
return applicationEntity.isBearerOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBearerOnly(boolean only) {
|
||||||
|
applicationEntity.setBearerOnly(only);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RoleModel getRole(String name) {
|
public RoleModel getRole(String name) {
|
||||||
TypedQuery<ApplicationRoleEntity> query = em.createNamedQuery("getAppRoleByName", ApplicationRoleEntity.class);
|
TypedQuery<ApplicationRoleEntity> query = em.createNamedQuery("getAppRoleByName", ApplicationRoleEntity.class);
|
||||||
|
|
|
@ -60,6 +60,16 @@ public class ClientAdapter implements ClientModel {
|
||||||
entity.setAllowedClaimsMask(mask);
|
entity.setAllowedClaimsMask(mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPublicClient() {
|
||||||
|
return entity.isPublicClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPublicClient(boolean flag) {
|
||||||
|
entity.setPublicClient(flag);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getWebOrigins() {
|
public Set<String> getWebOrigins() {
|
||||||
Set<String> result = new HashSet<String>();
|
Set<String> result = new HashSet<String>();
|
||||||
|
@ -67,6 +77,8 @@ public class ClientAdapter implements ClientModel {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setWebOrigins(Set<String> webOrigins) {
|
public void setWebOrigins(Set<String> webOrigins) {
|
||||||
entity.setWebOrigins(webOrigins);
|
entity.setWebOrigins(webOrigins);
|
||||||
|
|
|
@ -28,6 +28,7 @@ public class ApplicationEntity extends ClientEntity {
|
||||||
private boolean surrogateAuthRequired;
|
private boolean surrogateAuthRequired;
|
||||||
private String baseUrl;
|
private String baseUrl;
|
||||||
private String managementUrl;
|
private String managementUrl;
|
||||||
|
private boolean bearerOnly;
|
||||||
|
|
||||||
@ManyToOne()
|
@ManyToOne()
|
||||||
private RealmEntity realm;
|
private RealmEntity realm;
|
||||||
|
@ -87,6 +88,11 @@ public class ApplicationEntity extends ClientEntity {
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isBearerOnly() {
|
||||||
|
return bearerOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBearerOnly(boolean bearerOnly) {
|
||||||
|
this.bearerOnly = bearerOnly;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ public class ClientEntity {
|
||||||
private String secret;
|
private String secret;
|
||||||
private long allowedClaimsMask;
|
private long allowedClaimsMask;
|
||||||
private int notBefore;
|
private int notBefore;
|
||||||
|
private boolean publicClient;
|
||||||
|
|
||||||
|
|
||||||
@ElementCollection
|
@ElementCollection
|
||||||
|
@ -101,4 +102,12 @@ public class ClientEntity {
|
||||||
public void setNotBefore(int notBefore) {
|
public void setNotBefore(int notBefore) {
|
||||||
this.notBefore = notBefore;
|
this.notBefore = notBefore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPublicClient() {
|
||||||
|
return publicClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPublicClient(boolean publicClient) {
|
||||||
|
this.publicClient = publicClient;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,6 +123,26 @@ public class ApplicationAdapter extends AbstractAdapter implements ApplicationMo
|
||||||
application.setNotBefore(notBefore);
|
application.setNotBefore(notBefore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBearerOnly() {
|
||||||
|
return application.isBearerOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBearerOnly(boolean only) {
|
||||||
|
application.setBearerOnly(only);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPublicClient() {
|
||||||
|
return application.isPublicClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPublicClient(boolean flag) {
|
||||||
|
application.setPublicClient(flag);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RoleAdapter getRole(String name) {
|
public RoleAdapter getRole(String name) {
|
||||||
DBObject query = new QueryBuilder()
|
DBObject query = new QueryBuilder()
|
||||||
|
|
|
@ -82,6 +82,16 @@ public class OAuthClientAdapter extends AbstractAdapter implements OAuthClientMo
|
||||||
delegate.setNotBefore(notBefore);
|
delegate.setNotBefore(notBefore);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPublicClient() {
|
||||||
|
return delegate.isPublicClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPublicClient(boolean flag) {
|
||||||
|
delegate.setPublicClient(flag);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<String> getWebOrigins() {
|
public Set<String> getWebOrigins() {
|
||||||
Set<String> result = new HashSet<String>();
|
Set<String> result = new HashSet<String>();
|
||||||
|
|
|
@ -24,6 +24,8 @@ public class ApplicationEntity extends AbstractMongoIdentifiableEntity implement
|
||||||
private String baseUrl;
|
private String baseUrl;
|
||||||
private String secret;
|
private String secret;
|
||||||
private int notBefore;
|
private int notBefore;
|
||||||
|
private boolean bearerOnly;
|
||||||
|
private boolean publicClient;
|
||||||
|
|
||||||
private String realmId;
|
private String realmId;
|
||||||
private long allowedClaimsMask;
|
private long allowedClaimsMask;
|
||||||
|
@ -156,6 +158,24 @@ public class ApplicationEntity extends AbstractMongoIdentifiableEntity implement
|
||||||
this.notBefore = notBefore;
|
this.notBefore = notBefore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MongoField
|
||||||
|
public boolean isBearerOnly() {
|
||||||
|
return bearerOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBearerOnly(boolean bearerOnly) {
|
||||||
|
this.bearerOnly = bearerOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
@MongoField
|
||||||
|
public boolean isPublicClient() {
|
||||||
|
return publicClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPublicClient(boolean publicClient) {
|
||||||
|
this.publicClient = publicClient;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterRemove(MongoStoreInvocationContext context) {
|
public void afterRemove(MongoStoreInvocationContext context) {
|
||||||
// Remove all roles, which belongs to this application
|
// Remove all roles, which belongs to this application
|
||||||
|
|
|
@ -20,6 +20,7 @@ public class OAuthClientEntity extends AbstractMongoIdentifiableEntity implement
|
||||||
private String secret;
|
private String secret;
|
||||||
private long allowedClaimsMask;
|
private long allowedClaimsMask;
|
||||||
private int notBefore;
|
private int notBefore;
|
||||||
|
private boolean publicClient;
|
||||||
private List<String> scopeIds;
|
private List<String> scopeIds;
|
||||||
private List<String> webOrigins;
|
private List<String> webOrigins;
|
||||||
private List<String> redirectUris;
|
private List<String> redirectUris;
|
||||||
|
@ -106,6 +107,16 @@ public class OAuthClientEntity extends AbstractMongoIdentifiableEntity implement
|
||||||
this.notBefore = notBefore;
|
this.notBefore = notBefore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MongoField
|
||||||
|
public boolean isPublicClient() {
|
||||||
|
return publicClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPublicClient(boolean publicClient) {
|
||||||
|
this.publicClient = publicClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterRemove(MongoStoreInvocationContext context) {
|
public void afterRemove(MongoStoreInvocationContext context) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import org.jboss.resteasy.logging.Logger;
|
||||||
import org.keycloak.models.ApplicationModel;
|
import org.keycloak.models.ApplicationModel;
|
||||||
import org.keycloak.models.ClaimMask;
|
import org.keycloak.models.ClaimMask;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.Constants;
|
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.UserCredentialModel;
|
import org.keycloak.models.UserCredentialModel;
|
||||||
|
@ -18,12 +17,12 @@ import org.keycloak.representations.idm.ScopeMappingRepresentation;
|
||||||
import org.keycloak.representations.idm.UserRoleMappingRepresentation;
|
import org.keycloak.representations.idm.UserRoleMappingRepresentation;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -54,8 +53,11 @@ public class ApplicationManager {
|
||||||
ApplicationModel applicationModel = realm.addApplication(resourceRep.getName());
|
ApplicationModel applicationModel = realm.addApplication(resourceRep.getName());
|
||||||
if (resourceRep.isEnabled() != null) applicationModel.setEnabled(resourceRep.isEnabled());
|
if (resourceRep.isEnabled() != null) applicationModel.setEnabled(resourceRep.isEnabled());
|
||||||
applicationModel.setManagementUrl(resourceRep.getAdminUrl());
|
applicationModel.setManagementUrl(resourceRep.getAdminUrl());
|
||||||
if (resourceRep.isSurrogateAuthRequired() != null) applicationModel.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
|
if (resourceRep.isSurrogateAuthRequired() != null)
|
||||||
|
applicationModel.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
|
||||||
applicationModel.setBaseUrl(resourceRep.getBaseUrl());
|
applicationModel.setBaseUrl(resourceRep.getBaseUrl());
|
||||||
|
if (resourceRep.isBearerOnly() != null) applicationModel.setBearerOnly(resourceRep.isBearerOnly());
|
||||||
|
if (resourceRep.isPublicClient() != null) applicationModel.setPublicClient(resourceRep.isPublicClient());
|
||||||
applicationModel.updateApplication();
|
applicationModel.updateApplication();
|
||||||
|
|
||||||
if (resourceRep.getNotBefore() != null) {
|
if (resourceRep.getNotBefore() != null) {
|
||||||
|
@ -138,6 +140,8 @@ public class ApplicationManager {
|
||||||
public void updateApplication(ApplicationRepresentation rep, ApplicationModel resource) {
|
public void updateApplication(ApplicationRepresentation rep, ApplicationModel resource) {
|
||||||
if (rep.getName() != null) resource.setName(rep.getName());
|
if (rep.getName() != null) resource.setName(rep.getName());
|
||||||
if (rep.isEnabled() != null) resource.setEnabled(rep.isEnabled());
|
if (rep.isEnabled() != null) resource.setEnabled(rep.isEnabled());
|
||||||
|
if (rep.isBearerOnly() != null) resource.setBearerOnly(rep.isBearerOnly());
|
||||||
|
if (rep.isPublicClient() != null) resource.setPublicClient(rep.isPublicClient());
|
||||||
if (rep.getAdminUrl() != null) resource.setManagementUrl(rep.getAdminUrl());
|
if (rep.getAdminUrl() != null) resource.setManagementUrl(rep.getAdminUrl());
|
||||||
if (rep.getBaseUrl() != null) resource.setBaseUrl(rep.getBaseUrl());
|
if (rep.getBaseUrl() != null) resource.setBaseUrl(rep.getBaseUrl());
|
||||||
if (rep.isSurrogateAuthRequired() != null) resource.setSurrogateAuthRequired(rep.isSurrogateAuthRequired());
|
if (rep.isSurrogateAuthRequired() != null) resource.setSurrogateAuthRequired(rep.isSurrogateAuthRequired());
|
||||||
|
@ -171,6 +175,8 @@ public class ApplicationManager {
|
||||||
rep.setName(applicationModel.getName());
|
rep.setName(applicationModel.getName());
|
||||||
rep.setEnabled(applicationModel.isEnabled());
|
rep.setEnabled(applicationModel.isEnabled());
|
||||||
rep.setAdminUrl(applicationModel.getManagementUrl());
|
rep.setAdminUrl(applicationModel.getManagementUrl());
|
||||||
|
rep.setPublicClient(applicationModel.isPublicClient());
|
||||||
|
rep.setBearerOnly(applicationModel.isBearerOnly());
|
||||||
rep.setSurrogateAuthRequired(applicationModel.isSurrogateAuthRequired());
|
rep.setSurrogateAuthRequired(applicationModel.isSurrogateAuthRequired());
|
||||||
rep.setBaseUrl(applicationModel.getBaseUrl());
|
rep.setBaseUrl(applicationModel.getBaseUrl());
|
||||||
rep.setNotBefore(applicationModel.getNotBefore());
|
rep.setNotBefore(applicationModel.getNotBefore());
|
||||||
|
@ -193,22 +199,26 @@ public class ApplicationManager {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-not-required",
|
@JsonPropertyOrder({"realm", "realm-public-key", "bearer-only", "auth-server-url", "ssl-not-required",
|
||||||
"resource", "credentials",
|
"resource", "public-client", "credentials",
|
||||||
"use-resource-role-mappings"})
|
"use-resource-role-mappings"})
|
||||||
public static class InstallationAdapterConfig extends BaseRealmConfig {
|
public static class InstallationAdapterConfig extends BaseRealmConfig {
|
||||||
@JsonProperty("resource")
|
@JsonProperty("resource")
|
||||||
protected String resource;
|
protected String resource;
|
||||||
@JsonProperty("use-resource-role-mappings")
|
@JsonProperty("use-resource-role-mappings")
|
||||||
protected boolean useResourceRoleMappings;
|
protected Boolean useResourceRoleMappings;
|
||||||
|
@JsonProperty("bearer-only")
|
||||||
|
protected Boolean bearerOnly;
|
||||||
|
@JsonProperty("public-client")
|
||||||
|
protected Boolean publicClient;
|
||||||
@JsonProperty("credentials")
|
@JsonProperty("credentials")
|
||||||
protected Map<String, String> credentials = new HashMap<String, String>();
|
protected Map<String, String> credentials;
|
||||||
|
|
||||||
public boolean isUseResourceRoleMappings() {
|
public Boolean isUseResourceRoleMappings() {
|
||||||
return useResourceRoleMappings;
|
return useResourceRoleMappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setUseResourceRoleMappings(boolean useResourceRoleMappings) {
|
public void setUseResourceRoleMappings(Boolean useResourceRoleMappings) {
|
||||||
this.useResourceRoleMappings = useResourceRoleMappings;
|
this.useResourceRoleMappings = useResourceRoleMappings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,6 +229,7 @@ public class ApplicationManager {
|
||||||
public void setResource(String resource) {
|
public void setResource(String resource) {
|
||||||
this.resource = resource;
|
this.resource = resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getCredentials() {
|
public Map<String, String> getCredentials() {
|
||||||
return credentials;
|
return credentials;
|
||||||
}
|
}
|
||||||
|
@ -227,6 +238,21 @@ public class ApplicationManager {
|
||||||
this.credentials = credentials;
|
this.credentials = credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean getPublicClient() {
|
||||||
|
return publicClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPublicClient(Boolean publicClient) {
|
||||||
|
this.publicClient = publicClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Boolean getBearerOnly() {
|
||||||
|
return bearerOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBearerOnly(Boolean bearerOnly) {
|
||||||
|
this.bearerOnly = bearerOnly;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -236,15 +262,19 @@ public class ApplicationManager {
|
||||||
rep.setRealmKey(realmModel.getPublicKeyPem());
|
rep.setRealmKey(realmModel.getPublicKeyPem());
|
||||||
rep.setSslNotRequired(realmModel.isSslNotRequired());
|
rep.setSslNotRequired(realmModel.isSslNotRequired());
|
||||||
|
|
||||||
rep.setAuthServerUrl(baseUri.toString());
|
if (applicationModel.isPublicClient() && !applicationModel.isBearerOnly()) rep.setPublicClient(true);
|
||||||
rep.setUseResourceRoleMappings(applicationModel.getRoles().size() > 0);
|
if (applicationModel.isBearerOnly()) rep.setBearerOnly(true);
|
||||||
|
if (!applicationModel.isBearerOnly()) rep.setAuthServerUrl(baseUri.toString());
|
||||||
|
if (applicationModel.getRoles().size() > 0) rep.setUseResourceRoleMappings(true);
|
||||||
|
|
||||||
rep.setResource(applicationModel.getName());
|
rep.setResource(applicationModel.getName());
|
||||||
|
|
||||||
|
if (!applicationModel.isBearerOnly() && !applicationModel.isPublicClient()) {
|
||||||
Map<String, String> creds = new HashMap<String, String>();
|
Map<String, String> creds = new HashMap<String, String>();
|
||||||
String cred = applicationModel.getSecret();
|
String cred = applicationModel.getSecret();
|
||||||
creds.put(CredentialRepresentation.SECRET, cred);
|
creds.put(CredentialRepresentation.SECRET, cred);
|
||||||
rep.setCredentials(creds);
|
rep.setCredentials(creds);
|
||||||
|
}
|
||||||
|
|
||||||
return rep;
|
return rep;
|
||||||
}
|
}
|
||||||
|
@ -254,11 +284,21 @@ public class ApplicationManager {
|
||||||
buffer.append("<secure-deployment name=\"WAR MODULE NAME.war\">\n");
|
buffer.append("<secure-deployment name=\"WAR MODULE NAME.war\">\n");
|
||||||
buffer.append(" <realm>").append(realmModel.getName()).append("</realm>\n");
|
buffer.append(" <realm>").append(realmModel.getName()).append("</realm>\n");
|
||||||
buffer.append(" <realm-public-key>").append(realmModel.getPublicKeyPem()).append("</realm-public-key>\n");
|
buffer.append(" <realm-public-key>").append(realmModel.getPublicKeyPem()).append("</realm-public-key>\n");
|
||||||
|
if (applicationModel.isBearerOnly()){
|
||||||
|
buffer.append(" <bearer-only>true</bearer-only>\n");
|
||||||
|
|
||||||
|
} else {
|
||||||
buffer.append(" <auth-server-url>").append(baseUri.toString()).append("</auth-server-url>\n");
|
buffer.append(" <auth-server-url>").append(baseUri.toString()).append("</auth-server-url>\n");
|
||||||
|
if (applicationModel.isPublicClient() && !applicationModel.isBearerOnly()) {
|
||||||
|
buffer.append(" <public-client>true</public-client>\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
buffer.append(" <ssl-not-required>").append(realmModel.isSslNotRequired()).append("</ssl-not-required>\n");
|
buffer.append(" <ssl-not-required>").append(realmModel.isSslNotRequired()).append("</ssl-not-required>\n");
|
||||||
buffer.append(" <resource>").append(applicationModel.getName()).append("</resource>\n");
|
buffer.append(" <resource>").append(applicationModel.getName()).append("</resource>\n");
|
||||||
String cred = applicationModel.getSecret();
|
String cred = applicationModel.getSecret();
|
||||||
|
if (!applicationModel.isBearerOnly() && !applicationModel.isPublicClient()) {
|
||||||
buffer.append(" <credential name=\"secret\">").append(cred).append("</credential>\n");
|
buffer.append(" <credential name=\"secret\">").append(cred).append("</credential>\n");
|
||||||
|
}
|
||||||
buffer.append("</secure-deployment>\n");
|
buffer.append("</secure-deployment>\n");
|
||||||
return buffer.toString();
|
return buffer.toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,13 +2,9 @@ package org.keycloak.services.managers;
|
||||||
|
|
||||||
import org.codehaus.jackson.annotate.JsonProperty;
|
import org.codehaus.jackson.annotate.JsonProperty;
|
||||||
import org.codehaus.jackson.annotate.JsonPropertyOrder;
|
import org.codehaus.jackson.annotate.JsonPropertyOrder;
|
||||||
import org.keycloak.models.ClaimMask;
|
|
||||||
import org.keycloak.models.Constants;
|
|
||||||
import org.keycloak.models.OAuthClientModel;
|
import org.keycloak.models.OAuthClientModel;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleModel;
|
|
||||||
import org.keycloak.models.UserCredentialModel;
|
import org.keycloak.models.UserCredentialModel;
|
||||||
import org.keycloak.models.UserModel;
|
|
||||||
import org.keycloak.representations.adapters.config.BaseRealmConfig;
|
import org.keycloak.representations.adapters.config.BaseRealmConfig;
|
||||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
import org.keycloak.representations.idm.OAuthClientRepresentation;
|
import org.keycloak.representations.idm.OAuthClientRepresentation;
|
||||||
|
@ -58,10 +54,10 @@ public class OAuthClientManager {
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(OAuthClientRepresentation rep, OAuthClientModel model)
|
public void update(OAuthClientRepresentation rep, OAuthClientModel model) {
|
||||||
{
|
|
||||||
if (rep.getName() != null) model.setClientId(rep.getName());
|
if (rep.getName() != null) model.setClientId(rep.getName());
|
||||||
if (rep.isEnabled() != null) model.setEnabled(rep.isEnabled());
|
if (rep.isEnabled() != null) model.setEnabled(rep.isEnabled());
|
||||||
|
if (rep.isPublicClient() != null) model.setPublicClient(rep.isPublicClient());
|
||||||
List<String> redirectUris = rep.getRedirectUris();
|
List<String> redirectUris = rep.getRedirectUris();
|
||||||
if (redirectUris != null) {
|
if (redirectUris != null) {
|
||||||
model.setRedirectUris(new HashSet<String>(redirectUris));
|
model.setRedirectUris(new HashSet<String>(redirectUris));
|
||||||
|
@ -87,6 +83,7 @@ public class OAuthClientManager {
|
||||||
rep.setId(model.getId());
|
rep.setId(model.getId());
|
||||||
rep.setName(model.getClientId());
|
rep.setName(model.getClientId());
|
||||||
rep.setEnabled(model.isEnabled());
|
rep.setEnabled(model.isEnabled());
|
||||||
|
rep.setPublicClient(model.isPublicClient());
|
||||||
Set<String> redirectUris = model.getRedirectUris();
|
Set<String> redirectUris = model.getRedirectUris();
|
||||||
if (redirectUris != null) {
|
if (redirectUris != null) {
|
||||||
rep.setRedirectUris(new LinkedList<String>(redirectUris));
|
rep.setRedirectUris(new LinkedList<String>(redirectUris));
|
||||||
|
@ -101,12 +98,14 @@ public class OAuthClientManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-not-required",
|
@JsonPropertyOrder({"realm", "realm-public-key", "auth-server-url", "ssl-not-required",
|
||||||
"resource", "credentials"})
|
"resource", "public-client", "credentials"})
|
||||||
public static class InstallationAdapterConfig extends BaseRealmConfig {
|
public static class InstallationAdapterConfig extends BaseRealmConfig {
|
||||||
|
@JsonProperty("public-client")
|
||||||
|
protected Boolean publicClient;
|
||||||
@JsonProperty("resource")
|
@JsonProperty("resource")
|
||||||
protected String resource;
|
protected String resource;
|
||||||
@JsonProperty("credentials")
|
@JsonProperty("credentials")
|
||||||
protected Map<String, String> credentials = new HashMap<String, String>();
|
protected Map<String, String> credentials;
|
||||||
|
|
||||||
public String getResource() {
|
public String getResource() {
|
||||||
return resource;
|
return resource;
|
||||||
|
@ -115,6 +114,7 @@ public class OAuthClientManager {
|
||||||
public void setResource(String resource) {
|
public void setResource(String resource) {
|
||||||
this.resource = resource;
|
this.resource = resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, String> getCredentials() {
|
public Map<String, String> getCredentials() {
|
||||||
return credentials;
|
return credentials;
|
||||||
}
|
}
|
||||||
|
@ -123,6 +123,13 @@ public class OAuthClientManager {
|
||||||
this.credentials = credentials;
|
this.credentials = credentials;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Boolean getPublicClient() {
|
||||||
|
return publicClient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPublicClient(Boolean publicClient) {
|
||||||
|
this.publicClient = publicClient;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -132,12 +139,15 @@ public class OAuthClientManager {
|
||||||
rep.setRealmKey(realmModel.getPublicKeyPem());
|
rep.setRealmKey(realmModel.getPublicKeyPem());
|
||||||
rep.setSslNotRequired(realmModel.isSslNotRequired());
|
rep.setSslNotRequired(realmModel.isSslNotRequired());
|
||||||
rep.setAuthServerUrl(baseUri.toString());
|
rep.setAuthServerUrl(baseUri.toString());
|
||||||
|
if (model.isPublicClient()) rep.setPublicClient(true);
|
||||||
|
|
||||||
rep.setResource(model.getClientId());
|
rep.setResource(model.getClientId());
|
||||||
|
|
||||||
|
if (!model.isPublicClient()) {
|
||||||
Map<String, String> creds = new HashMap<String, String>();
|
Map<String, String> creds = new HashMap<String, String>();
|
||||||
creds.put(CredentialRepresentation.SECRET, model.getSecret());
|
creds.put(CredentialRepresentation.SECRET, model.getSecret());
|
||||||
rep.setCredentials(creds);
|
rep.setCredentials(creds);
|
||||||
|
}
|
||||||
|
|
||||||
return rep;
|
return rep;
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,9 +31,11 @@ import org.keycloak.util.BasicAuthHelper;
|
||||||
|
|
||||||
import javax.ws.rs.BadRequestException;
|
import javax.ws.rs.BadRequestException;
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.ForbiddenException;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
import javax.ws.rs.HeaderParam;
|
import javax.ws.rs.HeaderParam;
|
||||||
import javax.ws.rs.NotAcceptableException;
|
import javax.ws.rs.NotAcceptableException;
|
||||||
|
import javax.ws.rs.NotAllowedException;
|
||||||
import javax.ws.rs.NotAuthorizedException;
|
import javax.ws.rs.NotAuthorizedException;
|
||||||
import javax.ws.rs.OPTIONS;
|
import javax.ws.rs.OPTIONS;
|
||||||
import javax.ws.rs.POST;
|
import javax.ws.rs.POST;
|
||||||
|
@ -55,6 +57,7 @@ import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -136,7 +139,12 @@ public class TokenService {
|
||||||
throw new NotAcceptableException("HTTPS required");
|
throw new NotAcceptableException("HTTPS required");
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientModel client = authorizeClient(authorizationHeader);
|
ClientModel client = authorizeClient(authorizationHeader, form);
|
||||||
|
|
||||||
|
if (client.isPublicClient()) {
|
||||||
|
// we don't allow public clients to invoke grants/access to prevent phishing attacks
|
||||||
|
throw new ForbiddenException("Public clients are not allowed to invoke grants/access");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
|
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
|
||||||
|
@ -175,7 +183,7 @@ public class TokenService {
|
||||||
throw new NotAcceptableException("HTTPS required");
|
throw new NotAcceptableException("HTTPS required");
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientModel client = authorizeClient(authorizationHeader);
|
ClientModel client = authorizeClient(authorizationHeader, form);
|
||||||
String refreshToken = form.getFirst("refresh_token");
|
String refreshToken = form.getFirst("refresh_token");
|
||||||
AccessToken accessToken = null;
|
AccessToken accessToken = null;
|
||||||
try {
|
try {
|
||||||
|
@ -361,7 +369,7 @@ public class TokenService {
|
||||||
throw new NotAuthorizedException("Realm not enabled");
|
throw new NotAuthorizedException("Realm not enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientModel client = authorizeClient(authorizationHeader);
|
ClientModel client = authorizeClient(authorizationHeader, formData);
|
||||||
|
|
||||||
String code = formData.getFirst("code");
|
String code = formData.getFirst("code");
|
||||||
if (code == null) {
|
if (code == null) {
|
||||||
|
@ -425,18 +433,29 @@ public class TokenService {
|
||||||
return Cors.add(request, Response.ok(res)).auth().allowedOrigins(client).allowedMethods("POST").build();
|
return Cors.add(request, Response.ok(res)).auth().allowedOrigins(client).allowedMethods("POST").build();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ClientModel authorizeClient(String authorizationHeader) {
|
protected ClientModel authorizeClient(String authorizationHeader, MultivaluedMap<String, String> formData) {
|
||||||
if (authorizationHeader == null) {
|
String client_id = null;
|
||||||
throw new NotAuthorizedException("No Authorization header to authenticate client", "Basic realm=\"" + realm.getName() + "\"");
|
String clientSecret = null;
|
||||||
}
|
if (authorizationHeader != null) {
|
||||||
|
|
||||||
String[] usernameSecret = BasicAuthHelper.parseHeader(authorizationHeader);
|
String[] usernameSecret = BasicAuthHelper.parseHeader(authorizationHeader);
|
||||||
if (usernameSecret == null) {
|
if (usernameSecret == null) {
|
||||||
throw new NotAuthorizedException("No Authorization header to authenticate client", "Basic realm=\"" + realm.getName() + "\"");
|
throw new NotAuthorizedException("Bad Authorization header", "Basic realm=\"" + realm.getName() + "\"");
|
||||||
|
}
|
||||||
|
client_id = usernameSecret[0];
|
||||||
|
clientSecret = usernameSecret[1];
|
||||||
|
} else {
|
||||||
|
logger.info("no authorization header");
|
||||||
|
client_id = formData.getFirst("client_id");
|
||||||
|
clientSecret = formData.getFirst("client_secret");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client_id == null) {
|
||||||
|
Map<String, String> error = new HashMap<String, String>();
|
||||||
|
error.put("error", "invalid_client");
|
||||||
|
error.put("error_description", "Could not find client");
|
||||||
|
throw new BadRequestException("Could not find client", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
|
||||||
}
|
}
|
||||||
|
|
||||||
String client_id = usernameSecret[0];
|
|
||||||
String clientSecret = usernameSecret[1];
|
|
||||||
ClientModel client = realm.findClient(client_id);
|
ClientModel client = realm.findClient(client_id);
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
Map<String, String> error = new HashMap<String, String>();
|
Map<String, String> error = new HashMap<String, String>();
|
||||||
|
@ -452,11 +471,13 @@ public class TokenService {
|
||||||
throw new BadRequestException("Client is not enabled", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
|
throw new BadRequestException("Client is not enabled", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!client.isPublicClient()) {
|
||||||
if (!client.validateSecret(clientSecret)) {
|
if (!client.validateSecret(clientSecret)) {
|
||||||
Map<String, String> error = new HashMap<String, String>();
|
Map<String, String> error = new HashMap<String, String>();
|
||||||
error.put("error", "unauthorized_client");
|
error.put("error", "unauthorized_client");
|
||||||
throw new BadRequestException("Unauthorized Client", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
|
throw new BadRequestException("Unauthorized Client", Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,15 +634,35 @@ public class TokenService {
|
||||||
return location.build();
|
return location.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean matchesRedirects(Set<String> validRedirects, String redirect) {
|
||||||
|
for (String validRedirect : validRedirects) {
|
||||||
|
if (validRedirect.endsWith("*")) {
|
||||||
|
// strip off *
|
||||||
|
int length = validRedirect.length() - 1;
|
||||||
|
validRedirect = validRedirect.substring(0, length);
|
||||||
|
if (redirect.startsWith(validRedirect)) return true;
|
||||||
|
// strip off trailing '/'
|
||||||
|
if (length - 1 > 0 && validRedirect.charAt(length - 1) == '/') length--;
|
||||||
|
validRedirect = validRedirect.substring(0, length);
|
||||||
|
if (validRedirect.equals(redirect)) return true;
|
||||||
|
} else if (validRedirect.equals(redirect)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public static String verifyRedirectUri(String redirectUri, ClientModel client) {
|
public static String verifyRedirectUri(String redirectUri, ClientModel client) {
|
||||||
if (redirectUri == null) {
|
if (redirectUri == null) {
|
||||||
return client.getRedirectUris().size() == 1 ? client.getRedirectUris().iterator().next() : null;
|
return client.getRedirectUris().size() == 1 ? client.getRedirectUris().iterator().next() : null;
|
||||||
} else if (client.getRedirectUris().isEmpty()) {
|
} else if (client.getRedirectUris().isEmpty()) {
|
||||||
|
if (client.isPublicClient()) {
|
||||||
|
logger.error("Client redirect uri must be registered for public client");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return redirectUri;
|
return redirectUri;
|
||||||
} else {
|
} else {
|
||||||
String r = redirectUri.indexOf('?') != -1 ? redirectUri.substring(0, redirectUri.indexOf('?')) : redirectUri;
|
String r = redirectUri.indexOf('?') != -1 ? redirectUri.substring(0, redirectUri.indexOf('?')) : redirectUri;
|
||||||
|
|
||||||
boolean valid = client.getRedirectUris().contains(r);
|
boolean valid = matchesRedirects(client.getRedirectUris(), r);
|
||||||
|
|
||||||
if (!valid && r.startsWith(Constants.INSTALLED_APP_URL) && r.indexOf(':', Constants.INSTALLED_APP_URL.length()) >= 0) {
|
if (!valid && r.startsWith(Constants.INSTALLED_APP_URL) && r.indexOf(':', Constants.INSTALLED_APP_URL.length()) >= 0) {
|
||||||
int i = r.indexOf(':', Constants.INSTALLED_APP_URL.length());
|
int i = r.indexOf(':', Constants.INSTALLED_APP_URL.length());
|
||||||
|
@ -636,7 +677,7 @@ public class TokenService {
|
||||||
|
|
||||||
r = sb.toString();
|
r = sb.toString();
|
||||||
|
|
||||||
valid = client.getRedirectUris().contains(r);
|
valid = matchesRedirects(client.getRedirectUris(), r);
|
||||||
}
|
}
|
||||||
|
|
||||||
return valid ? redirectUri : null;
|
return valid ? redirectUri : null;
|
||||||
|
|
|
@ -59,6 +59,9 @@ public class OAuthRedirectUriTest {
|
||||||
ApplicationModel installedApp2 = appRealm.addApplication("test-installed2");
|
ApplicationModel installedApp2 = appRealm.addApplication("test-installed2");
|
||||||
installedApp2.setEnabled(true);
|
installedApp2.setEnabled(true);
|
||||||
installedApp2.addRedirectUri(Constants.INSTALLED_APP_URL + "/myapp");
|
installedApp2.addRedirectUri(Constants.INSTALLED_APP_URL + "/myapp");
|
||||||
|
ApplicationModel installedApp3 = appRealm.addApplication("test-wildcard");
|
||||||
|
installedApp3.setEnabled(true);
|
||||||
|
installedApp3.addRedirectUri("http://example.com/foo/*");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -187,6 +190,13 @@ public class OAuthRedirectUriTest {
|
||||||
Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/app?key=value&code="));
|
Assert.assertTrue(driver.getCurrentUrl().startsWith("http://localhost:8081/app?key=value&code="));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWildcard() throws IOException {
|
||||||
|
oauth.clientId("test-wildcard");
|
||||||
|
checkRedirectUri("http://example.com", false);
|
||||||
|
checkRedirectUri("http://example.com/foo", true);
|
||||||
|
checkRedirectUri("http://example.com/foobar", false);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLocalhost() throws IOException {
|
public void testLocalhost() throws IOException {
|
||||||
|
|
Loading…
Reference in a new issue