keycloak-aplcache
Changes
admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-credentials.html 1(+1 -0)
admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-installation.html 25(+25 -0)
admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-scope-mappings.html 1(+1 -0)
examples/wildfly-demo/README.md 41(+19 -22)
forms/src/main/resources/META-INF/resources/forms/theme/default/img/customer-login-screen-bg2.jpg 0(+0 -0)
integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java 2(+1 -1)
integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSecurityContextHelper.java 6(+3 -3)
integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/OAuthAuthenticatorValve.java 4(+2 -2)
integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java 2(+1 -1)
integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java 2(+1 -1)
pom.xml 2(+1 -1)
server/src/main/webapp/index.html 50(+50 -0)
server/src/main/webapp/keycloak.css 65(+65 -0)
server/src/main/webapp/WEB-INF/web.xml 11(+11 -0)
Details
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/index.html b/admin-ui/src/main/resources/META-INF/resources/admin/index.html
index a890c6a..3ef1734 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/index.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/index.html
@@ -11,7 +11,7 @@
<link rel="stylesheet" href="/auth-server/admin-ui/css/reset.css">
<link rel="stylesheet" href="/auth-server/admin-ui/bootstrap-3.0.0-wip/css/bootstrap.css">
<link rel="stylesheet" href="/auth-server/admin-ui/css/sprites.css">
- <link rel="stylesheet" href='http://fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic,700,700italic,800,800italic'>
+ <link rel="stylesheet" href='//fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic,700,700italic,800,800italic'>
<!-- RCUE styles -->
<link rel="stylesheet" href="/auth-server/admin-ui/css/base.css">
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
index d903db0..25f7e36 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/app.js
@@ -396,7 +396,21 @@ module.config([ '$routeProvider', function($routeProvider) {
},
controller : 'OAuthClientScopeMappingCtrl'
})
-
+ .when('/realms/:realm/oauth-clients/:oauth/installation', {
+ templateUrl : 'partials/oauth-client-installation.html',
+ resolve : {
+ realm : function(RealmLoader) {
+ return RealmLoader();
+ },
+ oauth : function(OAuthClientLoader) {
+ return OAuthClientLoader();
+ },
+ installation : function(OAuthClientInstallationLoader) {
+ return OAuthClientInstallationLoader();
+ }
+ },
+ controller : 'OAuthClientInstallationCtrl'
+ })
.when('/create/oauth-client/:realm', {
templateUrl : 'partials/oauth-client-detail.html',
resolve : {
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/oauth-clients.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/oauth-clients.js
index a0a8cd9..b13bc32 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/oauth-clients.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/oauth-clients.js
@@ -294,3 +294,11 @@ module.controller('OAuthClientScopeMappingCtrl', function($scope, $http, realm,
});
+
+
+module.controller('OAuthClientInstallationCtrl', function($scope, realm, installation, oauth, OAuthClientInstallation, $routeParams) {
+ $scope.realm = realm;
+ $scope.oauth = oauth;
+ $scope.installation = installation;
+ $scope.download = OAuthClientInstallation.url({ realm: $routeParams.realm, oauth: $routeParams.oauth });
+});
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
index adcfbd9..2beafc3 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/controllers/realm.js
@@ -77,6 +77,10 @@ module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $
$scope.files = $files;
};
+ $scope.changeFileSelect = function() {
+ $scope.files = null;
+ document.getElementById('import-file').click();
+ }
$scope.uploadFile = function() {
//$files: an array of files selected, each file has name, size, and type.
@@ -440,7 +444,7 @@ module.controller('RealmRegistrationCtrl', function ($scope, Realm, realm, appli
$scope.realm.defaultRoles = [];
}
- // Populate available roles. Available roles are neither already assigned or system roles.
+ // Populate available roles. Available roles are neither already assigned
for (var i = 0; i < roles.length; i++) {
var item = roles[i].name;
@@ -504,8 +508,7 @@ module.controller('RealmRegistrationCtrl', function ($scope, Realm, realm, appli
for (var i = 0; i < appDefaultRoles.length; i++) {
var roleName = appDefaultRoles[i].name;
-
- if (systemRoles.indexOf(roleName) < 0 && $scope.application.defaultRoles.indexOf(roleName) < 0) {
+ if ($scope.application.defaultRoles.indexOf(roleName) < 0) {
$scope.availableAppRoles.push(roleName);
}
}
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js
index 7b72c48..e3d1746 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/loaders.js
@@ -152,3 +152,12 @@ module.factory('OAuthClientListLoader', function(Loader, OAuthClient, $route, $q
}
});
});
+
+module.factory('OAuthClientInstallationLoader', function(Loader, OAuthClientInstallation, $route, $q) {
+ return Loader.get(OAuthClientInstallation, function() {
+ return {
+ realm : $route.current.params.realm,
+ oauth : $route.current.params.oauth
+ }
+ });
+});
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js b/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js
index 0147362..5bccc4c 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/js/services.js
@@ -291,6 +291,22 @@ module.factory('OAuthClientApplicationScopeMapping', function($resource) {
});
});
+module.factory('OAuthClientInstallation', function($resource) {
+ var url = '/auth-server/rest/saas/admin/realms/:realm/oauth-clients/:oauth/installation';
+ var resource = $resource('/auth-server/rest/saas/admin/realms/:realm/oauth-clients/:oauth/installation', {
+ realm : '@realm',
+ oauth : '@oauth'
+ }, {
+ update : {
+ method : 'PUT'
+ }
+ });
+ resource.url = function(parameters) {
+ return url.replace(':realm', parameters.realm).replace(':oauth', parameters.oauth);
+ }
+ return resource;
+});
+
module.factory('Current', function(Realm, $route) {
var current = {};
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-credentials.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-credentials.html
index 01d63c5..2605f53 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-credentials.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-credentials.html
@@ -7,6 +7,7 @@
<li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}">Settings</a></li>
<li class="active"><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
<li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
+ <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
</ul>
</div>
<div id="content">
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-detail.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-detail.html
index 22427f3..5f3ac72 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-detail.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-detail.html
@@ -7,6 +7,7 @@
<li class="active"><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}">Settings</a></li>
<li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
<li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
+ <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
</ul>
</div>
<div class="top-nav" data-ng-show="create">
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-installation.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-installation.html
new file mode 100755
index 0000000..94708a9
--- /dev/null
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-installation.html
@@ -0,0 +1,25 @@
+<div id="wrapper" class="container">
+ <div class="row">
+ <div class="bs-sidebar col-md-3 clearfix" data-ng-include data-src="'partials/realm-menu.html'"></div>
+ <div id="content-area" class="col-md-9" role="main">
+ <div class="top-nav" data-ng-show="!create">
+ <ul class="rcue-tabs">
+ <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}">Settings</a></li>
+ <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
+ <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
+ <li class="active"><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
+ </ul>
+ </div>
+ <div class="top-nav" data-ng-show="create">
+ <ul class="rcue-tabs">
+ <li></li>
+ </ul>
+ </div>
+ <div id="content">
+ <a class="button primary" href="{{download}}" download="keycloak.json" type="submit">Download</a></br>
+ <textarea style="width: 100%;" rows="20" onclick="this.select()">{{installation | json}}</textarea>
+ </div>
+ </div>
+ <div id="container-right-bg"></div>
+ </div>
+</div>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-scope-mappings.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-scope-mappings.html
index c2d0308..0d8e856 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-scope-mappings.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/oauth-client-scope-mappings.html
@@ -7,6 +7,7 @@
<li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}">Settings</a></li>
<li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/credentials">Credentials</a></li>
<li class="active"><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/scope-mappings">Scope</a></li>
+ <li><a href="#/realms/{{realm.id}}/oauth-clients/{{oauth.id}}/installation">Installation</a></li>
</ul>
</div>
<div id="content">
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/provider/google-help.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/provider/google-help.html
index 1c2eae1..048a8ca 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/provider/google-help.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/provider/google-help.html
@@ -1,36 +1,35 @@
<p>
- Open <a href="https://code.google.com/apis/console/" target="_blank">https://code.google.com/apis/console/</a>. From
- the
- drop-down menu select <i>Create</i>.
+ Open <a href="https://cloud.google.com/console/project" target="_blank">https://cloud.google.com/console/project</a>.
+ Click <i>Create Project</i>.
</p>
-<p>Use any name that you'd like, click <i>Create Project</i>, select <i>API Access</i> and click on <i>Create an OAuth
- 2.0 client ID</i>.</p>
+<p>Use any project name and id that you'd want and click <i>Create</i>. Wait for the project to be created.</p>
-<p>Use any product name you'd like and leave the other fields empty, then click <i>Next</i>. On the next page select <i>Web
- application</i>
- as the application type. Click <i>more options</i> next to <i>Your site or hostname</i>. Fill in the form with the
- following values:</p>
+<p>Click <i>APIs & auth</i>, under <i>APIs</i> make sure <i>Google+ API</i> is <i>ON</i>.
-<ul>
- <li><b>Authorized Redirect URIs:</b> {{callbackUrl}}</li>
-</ul>
+<p>Click <i>Credentials</i> and click on <i>Create New Client ID</i>. Select <i>Web application</i> as <i>Application
+ type</i>. <i>Authorized Javascript origins</i> should be empty. Add <i>{{callbackUrl}}</i> to <i>Authorized redirect
+ URI</i>. Click <i>Create Client ID</i></p>.
-<p>Click on <i>Create client ID</i>. Insert <i>Client ID</i> and <i>Client secret</i> in the form below.</p>
+<p>Insert <i>Client ID</i> and <i>Client secret</i> in the form below.</p>
<form class="form-horizontal" name="googleHelpForm">
<div class="control-group">
<label class="control-label" for="providerHelp.key">Client ID </label>
+
<div class="controls">
- <input type="text" class="input-xlarge" id="providerHelp.key" ng-model="realm.socialProviders[helpPId+'.key']">
+ <input type="text" class="input-xlarge" id="providerHelp.key"
+ ng-model="realm.socialProviders[helpPId+'.key']">
</div>
</div>
<div class="control-group">
<label class="control-label" for="providerHelp.secret">Client secret </label>
+
<div class="controls">
- <input type="text" class="input-xlarge" id="providerHelp.secret" ng-model="realm.socialProviders[helpPId+'.secret']">
+ <input type="text" class="input-xlarge" id="providerHelp.secret"
+ ng-model="realm.socialProviders[helpPId+'.secret']">
</div>
</div>
</form>
-<p>Close the help panel and click <i>save changes</i>.</p>
+<p>Close the help panel and click <i>save changes</i>.</p>
\ No newline at end of file
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-create.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-create.html
index fa61c55..3804c25 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-create.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-create.html
@@ -8,38 +8,19 @@
<form name="uploadForm" novalidate>
<fieldset>
<legend uncollapsed><span class="text">Import Realm</span></legend>
- <div class="form-group">
- <label for="name">Choose JSON File: </label>
- <div class="controls">
- <input type="file" ng-file-select="onFileSelect($files)" >
+ <div class="form-group clearfix">
+ <label for="name">Upload JSON File </label>
+ <div class="controls button-input-file" data-ng-show="!files || files.length == 0">
+ <a href="#" class="button"><span class="icon-upload">Icon: Upload</span>Choose a JSON File...</a>
+ <input id="import-file" type="file" class="transparent" ng-file-select="onFileSelect($files)">
</div>
+ <span class="uploaded-file" data-ng-show="files.length > 0">{{files[0].name}}</span>
+ <button class="link" data-ng-show="files.length > 0" data-ng-click="changeFileSelect();">Change</button>
</div>
+
<div class="form-actions inside">
<button type="submit" data-ng-click="uploadFile()" class="primary" data-ng-show="files.length > 0">Upload</button>
</div>
-
-
- <!-- THIS APPEARS INITIALLY
-
-<div class="form-group clearfix">
- <label for="upload">Upload JSON File</label>
- <div class="controls button-input-file">
- <a class="button" href="#"><span class="icon-upload">Icon: Upload</span>Choose a JSON File...</a>
- <input type="file" ng-file-select="onFileSelect($files)" class="transparent" id="upload">
- </div>
- </div>
--->
- <!-- THE DIV ABOVE IS REPLACED BY THIS AFTER CHOOSING A FILE
-
-<div class="form-group clearfix">
- <label for="upload">Upload JSON File </label>
- <span class="uploaded-file">a-new-realm-uploaded.json</span>
- <div class="link-input-file">
- <button class="link">Change</button>
- <input type="file" ng-file-select="onFileSelect($files)" class="transparent" id="upload">
- </div>
- </div>
--->
</fieldset>
</form>
<form name="realmForm" novalidate>
diff --git a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-registration.html b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-registration.html
index d52ecdb..a84658a 100755
--- a/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-registration.html
+++ b/admin-ui/src/main/resources/META-INF/resources/admin/partials/realm-registration.html
@@ -36,7 +36,7 @@
</div>
<div class="middle-buttons">
<button type="submit" ng-click="addRealmDefaultRole()" tooltip="Move right" tooltip-placement="right"><span class="icon-arrow-right">Move right</span></button>
- <button type="submit" ng-click="rmRealmDefaultRole()" tooltip="Move left" tooltip-placement="right"><span class="icon-arrow-left">Move left</span></button>
+ <button type="submit" ng-click="deleteRealmDefaultRole()" tooltip="Move left" tooltip-placement="right"><span class="icon-arrow-left">Move left</span></button>
</div>
<div class="select-title">
<label for="assigned">Realm Default Roles</label>
diff --git a/core/src/main/java/org/keycloak/representations/JsonWebToken.java b/core/src/main/java/org/keycloak/representations/JsonWebToken.java
index 3d7252a..c5ca3f1 100755
--- a/core/src/main/java/org/keycloak/representations/JsonWebToken.java
+++ b/core/src/main/java/org/keycloak/representations/JsonWebToken.java
@@ -22,8 +22,8 @@ public class JsonWebToken implements Serializable {
protected String issuer;
@JsonProperty("aud")
protected String audience;
- @JsonProperty("prn")
- protected String principal;
+ @JsonProperty("sub")
+ protected String subject;
@JsonProperty("typ")
protected String type;
@@ -116,12 +116,12 @@ public class JsonWebToken implements Serializable {
return this;
}
- public String getPrincipal() {
- return principal;
+ public String getSubject() {
+ return subject;
}
public JsonWebToken principal(String principal) {
- this.principal = principal;
+ this.subject = principal;
return this;
}
diff --git a/core/src/main/java/org/keycloak/RSATokenVerifier.java b/core/src/main/java/org/keycloak/RSATokenVerifier.java
index 56fe140..f4d6896 100755
--- a/core/src/main/java/org/keycloak/RSATokenVerifier.java
+++ b/core/src/main/java/org/keycloak/RSATokenVerifier.java
@@ -32,7 +32,7 @@ public class RSATokenVerifier {
if (!token.isActive()) {
throw new VerificationException("Token is not active.");
}
- String user = token.getPrincipal();
+ String user = token.getSubject();
if (user == null) {
throw new VerificationException("Token user was null");
}
diff --git a/core/src/test/java/org/keycloak/RSAVerifierTest.java b/core/src/test/java/org/keycloak/RSAVerifierTest.java
index 0aacbc8..ca0f46f 100755
--- a/core/src/test/java/org/keycloak/RSAVerifierTest.java
+++ b/core/src/test/java/org/keycloak/RSAVerifierTest.java
@@ -97,7 +97,7 @@ public class RSAVerifierTest {
.rsa256(idpPair.getPrivate());
SkeletonKeyToken token = verifySkeletonKeyToken(encoded);
Assert.assertTrue(token.getResourceAccess("service").getRoles().contains("admin"));
- Assert.assertEquals("CN=Client", token.getPrincipal());
+ Assert.assertEquals("CN=Client", token.getSubject());
}
private SkeletonKeyToken verifySkeletonKeyToken(String encoded) throws VerificationException {
diff --git a/distribution/appliance-dist/assembly.xml b/distribution/appliance-dist/assembly.xml
index 329ff2a..8f6e772 100755
--- a/distribution/appliance-dist/assembly.xml
+++ b/distribution/appliance-dist/assembly.xml
@@ -16,6 +16,7 @@
<outputDirectory>keycloak</outputDirectory>
<excludes>
<exclude>**/*.sh</exclude>
+ <exclude>welcome-content/*</exclude>
</excludes>
</fileSet>
<fileSet>
@@ -34,6 +35,13 @@
<directory>${project.build.directory}/unpacked/adapter</directory>
<outputDirectory>keycloak</outputDirectory>
</fileSet>
+ <fileSet>
+ <directory>${project.build.directory}/unpacked/deployments/auth-server.war</directory>
+ <outputDirectory>keycloak/welcome-content</outputDirectory>
+ <includes>
+ <include>*.*</include>
+ </includes>
+ </fileSet>
</fileSets>
<dependencySets>
<dependencySet>
examples/wildfly-demo/README.md 41(+19 -22)
diff --git a/examples/wildfly-demo/README.md b/examples/wildfly-demo/README.md
old mode 100755
new mode 100644
index b7fb243..9425964
--- a/examples/wildfly-demo/README.md
+++ b/examples/wildfly-demo/README.md
@@ -1,4 +1,4 @@
-Login, Distributed SSO, Distributed Logout, and Oauth Token Grant Wildfly Examples
+Login, Distributed SSO, Distributed Logout, and OAuth Token Grant Wildfly Examples
===================================
The following examples requires Wildfly 8.0.0. Here's the highlights of the examples
* Delegating authentication of a web app to the remote authentication server via OAuth 2 protocols
@@ -7,12 +7,11 @@ The following examples requires Wildfly 8.0.0. Here's the highlights of the exa
* Bearer token authentication and authorization of JAX-RS services
* Obtaining bearer tokens via the OAuth2 protocol
-There are multiple WAR projects. These all will run on the same jboss instance, but pretend each one is running on a different
+There are multiple WAR projects. These will all run on the same WildFly instance, but pretend each one is running on a different
machine on the network or Internet.
-* **customer-app** A WAR applications that does remote login using OAUTH2 browser redirects with the auth server
-* **product-app** A WAR applications that does remote login using OAUTH2 browser redirects with the auth server
-* **database-service** JAX-RS services authenticated by bearer tokens only. The customer and product app invoke on it
- to get data
+* **customer-app** A WAR application that does remote login using OAuth2 browser redirects with the auth server
+* **product-app** A WAR application that does remote login using OAuth2 browser redirects with the auth server
+* **database-service** JAX-RS services authenticated by bearer tokens only. The customer and product app invoke on it to get data
* **third-party** Simple WAR that obtain a bearer token using OAuth2 using browser redirects to the auth-server.
The UI of each of these applications is very crude and exists just to show our OAuth2 implementation in action.
@@ -22,19 +21,20 @@ _This demo is meant to run on the same server instance as the Keycloak Server!_
Step 1: Make sure you've set up the Keycloak Server
--------------------------------------
-If you've downloaded the Keycloak Appliance Distribution, there is already a Wildfly distro all set up for you in the keycloak/ directory. This
-Wildfly distro has the adapter jboss modules all installed as well as the keycloak server all set up.
+If you've downloaded the Keycloak Appliance Distribution, there is already a Wildfly distro all set up for you. This
+Wildfly distro has the adapter jboss modules all installed as well as the Keycloak Server all set up.
If you want to install Keycloak Server and run the demo on an existing Wildfly instance:
Obtain latest keycloak-war-dist-all.zip. This distro is used to install keycloak onto an existing JBoss installation
-$ cd ${wildfly.home}/standalone
-$ cp -r ${keycloak-war-dist-all}/deployments .
+ $ cd ${wildfly.home}/standalone
+ $ cp -r ${keycloak-war-dist-all}/deployments .
To install the adapter:
-$ cd ${jboss.home}
-$ unzip ${keycloak-war-dist-al}/adapters/keycloak-wildfly-adapter-dist.zip
+
+ $ cd ${jboss.home}
+ $ unzip ${keycloak-war-dist-al}/adapters/keycloak-wildfly-adapter-dist.zip
Step 2: Boot Keycloak Server
---------------------------------------
@@ -44,15 +44,15 @@ From appliance:
$ cd keycloak/bin
$ ./standalone.sh
-From existin Wildfly distro
+From existing Wildfly distro
$ cd ${wildfly.home}
$ ./standalone.sh
Step 3: Import the Test Realm
---------------------------------------
Next thing you have to do is import the test realm for the demo. Clicking on the below link will bring you to the
-create realm page in the admin UI. The username/password is admin/admin to login in. Keycloak will ask you to
-create a new password admin password before you can go to the create realm page.
+create realm page in the Admin UI. The username/password is admin/admin to login in. Keycloak will ask you to
+create a new admin password before you can go to the create realm page.
[http://localhost:8080/auth-server/admin/index.html#/create/realm](http://localhost:8080/auth-server/admin/index.html#/create/realm)
@@ -69,13 +69,13 @@ next you must build and deploy
Step 5: Login and Observe Apps
---------------------------------------
-Try going to the customer app and viewing customer data:
+Try going to the customer app and view customer data:
[http://localhost:8080/customer-portal/customers/view.jsp](http://localhost:8080/customer-portal/customers/view.jsp)
This should take you to the auth-server login screen. Enter username: bburke@redhat.com and password: password.
-If you click on the products link, you'll be take to the products app and show a product listing. The redirects
+If you click on the products link, you'll be taken to the products app and show a product listing. The redirects
are still happening, but the auth-server knows you are already logged in so the login is bypassed.
If you click on the logout link of either of the product or customer app, you'll be logged out of all the applications.
@@ -83,7 +83,7 @@ If you click on the logout link of either of the product or customer app, you'll
Step 6: Traditional OAuth2 Example
----------------------------------
The customer and product apps are logins. The third-party app is the traditional OAuth2 usecase of a client wanting
-to get permission to access a user's data. To run this example
+to get permission to access a user's data. To run this example open
[http://localhost:8080/oauth-client](http://localhost:8080/oauth-client)
@@ -93,10 +93,7 @@ an oauth grant page. This page asks you if you want to grant certain permission
Admin Console
==========================
-1. Login
-
-Login:
-[http://localhost:8080/auth-server/rest/saas/login](http://localhost:8080/auth-server/rest/saas/login)
+[http://localhost:8080/auth-server/admin/index.html](http://localhost:8080/auth-server/admin/index.html)
diff --git a/forms/src/main/java/org/keycloak/forms/RealmBean.java b/forms/src/main/java/org/keycloak/forms/RealmBean.java
index 6eeabab..322580c 100755
--- a/forms/src/main/java/org/keycloak/forms/RealmBean.java
+++ b/forms/src/main/java/org/keycloak/forms/RealmBean.java
@@ -44,7 +44,7 @@ public class RealmBean {
}
public String getName() {
- return saas ? "Keycloak" : realm.getName();
+ return realm.getName();
}
public RealmModel getRealm() {
diff --git a/forms/src/main/java/org/keycloak/forms/TemplateBean.java b/forms/src/main/java/org/keycloak/forms/TemplateBean.java
index 5bdea9c..bb19d2c 100644
--- a/forms/src/main/java/org/keycloak/forms/TemplateBean.java
+++ b/forms/src/main/java/org/keycloak/forms/TemplateBean.java
@@ -51,15 +51,9 @@ public class TemplateBean {
themeConfig.put("styles", themeUrl + "/styles.css");
- // TODO move this into CSS
- if (realm.isSaas()) {
- themeConfig.put("logo", themeUrl + "/img/red-hat-logo.png");
- themeConfig.put("background", themeUrl + "/img/login-screen-background.jpg");
- themeConfig.put("displayPoweredBy", false);
- } else {
- themeConfig.put("background", themeUrl + "/img/customer-login-screen-bg2.jpg");
- themeConfig.put("displayPoweredBy", true);
- }
+ themeConfig.put("logo", themeUrl + "/img/keycloak-logo.png");
+ themeConfig.put("background", themeUrl + "/img/login-screen-background.jpg");
+ themeConfig.put("displayPoweredBy", true);
}
public String getFormsPath() {
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/img/keycloak-logo.png b/forms/src/main/resources/META-INF/resources/forms/theme/default/img/keycloak-logo.png
new file mode 100644
index 0000000..f3886aa
Binary files /dev/null and b/forms/src/main/resources/META-INF/resources/forms/theme/default/img/keycloak-logo.png differ
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/styles.css b/forms/src/main/resources/META-INF/resources/forms/theme/default/styles.css
index 161be89..2bd23a0 100644
--- a/forms/src/main/resources/META-INF/resources/forms/theme/default/styles.css
+++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/styles.css
@@ -3,7 +3,7 @@
@IMPORT url("css/forms.css");
@IMPORT url("css/zocial/zocial.css");
@IMPORT url("css/login-register.css");
-@IMPORT url("http://fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic,700,700italic,800,800italic");
+@IMPORT url("//fonts.googleapis.com/css?family=Open+Sans:400,300,300italic,400italic,600,600italic,700,700italic,800,800italic");
.zocial.google {
background-color: #dd4b39 !important;
diff --git a/forms/src/main/resources/META-INF/resources/forms/theme/default/template-login.ftl b/forms/src/main/resources/META-INF/resources/forms/theme/default/template-login.ftl
index 30f422c..1a20b3a 100644
--- a/forms/src/main/resources/META-INF/resources/forms/theme/default/template-login.ftl
+++ b/forms/src/main/resources/META-INF/resources/forms/theme/default/template-login.ftl
@@ -75,7 +75,7 @@
<#if template.themeConfig['displayPoweredBy']>
<p class="powered">
- <a href="#">${rb.getString('poweredByKeycloak')}</a>
+ <a href="http://www.keycloak.org">${rb.getString('poweredByKeycloak')}</a>
</p>
</#if>
</div>
diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java
index da95481..c75704f 100755
--- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java
+++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java
@@ -102,7 +102,7 @@ public class CatalinaBearerTokenAuthenticator {
}
surrogate = chain[0].getSubjectX500Principal().getName();
}
- SkeletonKeyPrincipal skeletonKeyPrincipal = new SkeletonKeyPrincipal(token.getPrincipal(), surrogate);
+ SkeletonKeyPrincipal skeletonKeyPrincipal = new SkeletonKeyPrincipal(token.getSubject(), surrogate);
principal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), skeletonKeyPrincipal, roles);
request.setUserPrincipal(principal);
request.setAuthType("OAUTH_BEARER");
diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSecurityContextHelper.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSecurityContextHelper.java
index b939d19..8cfbcb5 100755
--- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSecurityContextHelper.java
+++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaSecurityContextHelper.java
@@ -65,11 +65,11 @@ public class CatalinaSecurityContextHelper {
}
/**
- * Get the Principal given the authenticated Subject. Currently the first principal that is not of type {@code Group} is
- * considered or the single principal inside the CallerPrincipal group.
+ * Get the Principal given the authenticated Subject. Currently the first subject that is not of type {@code Group} is
+ * considered or the single subject inside the CallerPrincipal group.
*
* @param subject
- * @return the authenticated principal
+ * @return the authenticated subject
*/
protected Principal getPrincipal(Subject subject) {
Principal principal = null;
diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/OAuthAuthenticatorValve.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/OAuthAuthenticatorValve.java
index b8b0688..01eb9aa 100755
--- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/OAuthAuthenticatorValve.java
+++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/OAuthAuthenticatorValve.java
@@ -227,7 +227,7 @@ public class OAuthAuthenticatorValve extends FormAuthenticator implements Lifecy
SkeletonKeyToken.Access access = token.getRealmAccess();
if (access != null) roles.addAll(access.getRoles());
}
- SkeletonKeyPrincipal skp = new SkeletonKeyPrincipal(token.getPrincipal(), null);
+ SkeletonKeyPrincipal skp = new SkeletonKeyPrincipal(token.getSubject(), null);
GenericPrincipal principal = new CatalinaSecurityContextHelper().createPrincipal(context.getRealm(), skp, roles);
Session session = request.getSessionInternal(true);
session.setPrincipal(principal);
@@ -235,7 +235,7 @@ public class OAuthAuthenticatorValve extends FormAuthenticator implements Lifecy
SkeletonKeySession skSession = new SkeletonKeySession(oauth.getTokenString(), token, realmConfiguration.getMetadata());
session.setNote(SkeletonKeySession.class.getName(), skSession);
- String username = token.getPrincipal();
+ String username = token.getSubject();
log.debug("userSessionManage.login: " + username);
userSessionManagement.login(session, username);
}
diff --git a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java
index 319b5ac..6a5cb02 100755
--- a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java
+++ b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java
@@ -71,7 +71,7 @@ public class JaxrsBearerTokenFilter implements ContainerRequestFilter {
ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
String callerPrincipal = securityContext.getUserPrincipal() != null ? securityContext.getUserPrincipal().getName() : null;
- final SkeletonKeyPrincipal principal = new SkeletonKeyPrincipal(token.getPrincipal(), callerPrincipal);
+ final SkeletonKeyPrincipal principal = new SkeletonKeyPrincipal(token.getSubject(), callerPrincipal);
final boolean isSecure = securityContext.isSecure();
final SkeletonKeyToken.Access access;
if (resourceMetadata.getResourceName() != null) {
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java
index 120546f..8f0df9d 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java
@@ -98,7 +98,7 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism
}
protected SkeletonKeyPrincipal completeAuthentication(SecurityContext securityContext, SkeletonKeyToken token, String surrogate) {
- final SkeletonKeyPrincipal skeletonKeyPrincipal = new SkeletonKeyPrincipal(token.getPrincipal(), surrogate);
+ final SkeletonKeyPrincipal skeletonKeyPrincipal = new SkeletonKeyPrincipal(token.getSubject(), surrogate);
Set<String> roles = null;
if (adapterConfig.isUseResourceRoleMappings()) {
SkeletonKeyToken.Access access = token.getResourceAccess(resourceMetadata.getResourceName());
pom.xml 2(+1 -1)
diff --git a/pom.xml b/pom.xml
index 80813f6..4824659 100755
--- a/pom.xml
+++ b/pom.xml
@@ -14,7 +14,7 @@
<properties>
<keycloak.apache.httpcomponents.version>4.1.2</keycloak.apache.httpcomponents.version>
<resteasy.version>3.0.5.Final</resteasy.version>
- <undertow.version>1.0.0.Beta28</undertow.version>
+ <undertow.version>1.0.0.Beta30</undertow.version>
<picketlink.version>2.5.0.Beta6</picketlink.version>
<mongo.driver.version>2.11.2</mongo.driver.version>
<jboss.logging.version>3.1.1.GA</jboss.logging.version>
server/src/main/webapp/index.html 50(+50 -0)
diff --git a/server/src/main/webapp/index.html b/server/src/main/webapp/index.html
new file mode 100644
index 0000000..805dc19
--- /dev/null
+++ b/server/src/main/webapp/index.html
@@ -0,0 +1,50 @@
+<!--
+ ~ JBoss, Home of Professional Open Source.
+ ~ Copyright (c) 2011, Red Hat, Inc., and individual contributors
+ ~ as indicated by the @author tags. See the copyright.txt file in the
+ ~ distribution for a full listing of individual contributors.
+ ~
+ ~ This is free software; you can redistribute it and/or modify it
+ ~ under the terms of the GNU Lesser General Public License as
+ ~ published by the Free Software Foundation; either version 2.1 of
+ ~ the License, or (at your option) any later version.
+ ~
+ ~ This software is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ ~ Lesser General Public License for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public
+ ~ License along with this software; if not, write to the Free
+ ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ -->
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+ <title>Welcome to WildFly Application Server 8</title>
+ <link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
+ <link rel="StyleSheet" href="keycloak.css" type="text/css">
+</head>
+
+<body>
+<div class="wrapper">
+ <div class="content">
+ <div class="logo">
+ <img src="keycloak_logo.png" alt="Keycloak" border="0" />
+ </div>
+ <h1>Welcome to Keycloak</h1>
+
+ <h3>Your Keycloak is running.</h3>
+
+ <p><a href="http://www.keycloak.org/documentation">Documentation</a> | <a href="/auth-server/admin/index.html">Administration Console</a> </p>
+
+ <p><a href="http://www.keycloak.org">Keycloak Project</a> |
+ <a href="https://lists.jboss.org/mailman/listinfo/keycloak-user">Mailing List</a> |
+ <a href="https://issues.jboss.org/browse/KEYCLOAK">Report an issue</a></p>
+ <p class="logos"><a href="http://www.jboss.org"><img src="jboss_community.png" alt="JBoss and JBoss Community" width="254" height="31" border="0"></a></p>
+ </div>
+</div>
+</body>
+</html>
diff --git a/server/src/main/webapp/jboss_community.png b/server/src/main/webapp/jboss_community.png
new file mode 100644
index 0000000..946e8f9
Binary files /dev/null and b/server/src/main/webapp/jboss_community.png differ
server/src/main/webapp/keycloak.css 65(+65 -0)
diff --git a/server/src/main/webapp/keycloak.css b/server/src/main/webapp/keycloak.css
new file mode 100644
index 0000000..5152862
--- /dev/null
+++ b/server/src/main/webapp/keycloak.css
@@ -0,0 +1,65 @@
+/*
+ ~ JBoss, Home of Professional Open Source.
+ ~ Copyright (c) 2011, Red Hat, Inc., and individual contributors
+ ~ as indicated by the @author tags. See the copyright.txt file in the
+ ~ distribution for a full listing of individual contributors.
+ ~
+ ~ This is free software; you can redistribute it and/or modify it
+ ~ under the terms of the GNU Lesser General Public License as
+ ~ published by the Free Software Foundation; either version 2.1 of
+ ~ the License, or (at your option) any later version.
+ ~
+ ~ This software is distributed in the hope that it will be useful,
+ ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ ~ Lesser General Public License for more details.
+ ~
+ ~ You should have received a copy of the GNU Lesser General Public
+ ~ License along with this software; if not, write to the Free
+ ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+
+body {
+ /*background: url(bkg.gif) repeat-x;*/
+ color: #5B5B5B;
+ font-family: "Lucida Sans Unicode", "Lucida Grande", Geneva, Verdana, Arial, sans-serif;
+ margin-top: 100px;
+ text-align: center;
+}
+.wrapper {
+ margin-left: auto;
+ margin-right: auto;
+ width: 50em;
+ text-align: left;
+}
+a {
+ text-decoration: none;
+ color: #5e8a9a;
+}
+h1 {
+ padding-top: 20px;
+ color: #7b1e1e;
+}
+a:hover {
+ text-decoration: underline;
+ color: #8ec6d9;
+}
+.content {
+ margin: 0;
+ padding: 0;
+}
+.dualbrand {
+ padding-top: 20px;
+}
+.wildfly {
+ float:left;
+ margin-left: 10px;
+}
+.logo{
+ margin-bottom: 10px;
+}
+.note {
+ font-size: 8pt;
+ color: #aaaaaa;
+}
diff --git a/server/src/main/webapp/keycloak_logo.png b/server/src/main/webapp/keycloak_logo.png
new file mode 100644
index 0000000..1f62687
Binary files /dev/null and b/server/src/main/webapp/keycloak_logo.png differ
server/src/main/webapp/WEB-INF/web.xml 11(+11 -0)
diff --git a/server/src/main/webapp/WEB-INF/web.xml b/server/src/main/webapp/WEB-INF/web.xml
index f800f47..0b1e810 100755
--- a/server/src/main/webapp/WEB-INF/web.xml
+++ b/server/src/main/webapp/WEB-INF/web.xml
@@ -21,6 +21,11 @@
<async-supported>true</async-supported>
</servlet>
+ <servlet>
+ <servlet-name>TmpAdminRedirectServlet</servlet-name>
+ <servlet-class>org.keycloak.services.tmp.TmpAdminRedirectServlet</servlet-class>
+ </servlet>
+
<listener>
<listener-class>org.keycloak.services.listeners.KeycloakSessionDestroyListener</listener-class>
</listener>
@@ -44,6 +49,12 @@
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
+ <servlet-mapping>
+ <servlet-name>TmpAdminRedirectServlet</servlet-name>
+ <url-pattern>/admin</url-pattern>
+ <url-pattern>/admin/</url-pattern>
+ </servlet-mapping>
+
<!--
<security-constraint>
diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
index a42b93a..6b6545b 100755
--- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java
@@ -172,7 +172,7 @@ public class AuthenticationManager {
Auth auth = new Auth(token);
- UserModel user = realm.getUser(token.getPrincipal());
+ UserModel user = realm.getUser(token.getSubject());
if (user == null || !user.isEnabled()) {
logger.debug("Unknown user in identity cookie");
expireIdentityCookie(realm, uriInfo);
@@ -219,7 +219,7 @@ public class AuthenticationManager {
Auth auth = new Auth(token);
- UserModel user = realm.getUser(token.getPrincipal());
+ UserModel user = realm.getUser(token.getSubject());
if (user == null || !user.isEnabled()) {
throw new NotAuthorizedException("invalid_user");
}
diff --git a/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java b/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java
index 651db2f..fa99940 100755
--- a/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java
+++ b/services/src/main/java/org/keycloak/services/managers/OAuthClientManager.java
@@ -1,17 +1,23 @@
package org.keycloak.services.managers;
+import org.keycloak.models.ApplicationModel;
import org.keycloak.models.Constants;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel;
+import org.keycloak.representations.adapters.config.BaseAdapterConfig;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.OAuthClientRepresentation;
+import org.keycloak.services.resources.flows.Urls;
+import java.net.URI;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.Set;
/**
@@ -76,4 +82,26 @@ public class OAuthClientManager {
}
return rep;
}
+
+ public BaseAdapterConfig toInstallationRepresentation(RealmModel realmModel, OAuthClientModel model, URI baseUri) {
+ BaseAdapterConfig rep = new BaseAdapterConfig();
+ rep.setRealm(realmModel.getId());
+ rep.setRealmKey(realmModel.getPublicKeyPem());
+ rep.setSslNotRequired(realmModel.isSslNotRequired());
+
+ rep.setAuthUrl(Urls.realmLoginPage(baseUri, realmModel.getId()).toString());
+ rep.setCodeUrl(Urls.realmCode(baseUri, realmModel.getId()).toString());
+ rep.setUseResourceRoleMappings(false);
+
+ rep.setResource(model.getOAuthAgent().getLoginName());
+
+ Map<String, String> creds = new HashMap<String, String>();
+ creds.put(CredentialRepresentation.PASSWORD, "INSERT CLIENT PASSWORD");
+ if (model.getOAuthAgent().isTotp()) {
+ creds.put(CredentialRepresentation.TOTP, "INSERT CLIENT TOTP");
+ }
+ rep.setCredentials(creds);
+
+ return rep;
+ }
}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java
index 138bc3a..4cafbc7 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientResource.java
@@ -6,10 +6,13 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.OAuthClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserCredentialModel;
+import org.keycloak.representations.adapters.config.BaseAdapterConfig;
import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.OAuthClientRepresentation;
+import org.keycloak.services.managers.ApplicationManager;
import org.keycloak.services.managers.OAuthClientManager;
import org.keycloak.services.managers.RealmManager;
+import org.keycloak.util.JsonSerialization;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
@@ -17,7 +20,10 @@ import javax.ws.rs.GET;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriInfo;
+import java.io.IOException;
import java.util.List;
/**
@@ -29,6 +35,8 @@ public class OAuthClientResource {
protected RealmModel realm;
protected OAuthClientModel oauthClient;
protected KeycloakSession session;
+ @Context
+ protected UriInfo uriInfo;
public OAuthClientResource(RealmModel realm, OAuthClientModel oauthClient, KeycloakSession session) {
this.realm = realm;
@@ -51,6 +59,18 @@ public class OAuthClientResource {
return OAuthClientManager.toRepresentation(oauthClient);
}
+ @GET
+ @NoCache
+ @Path("installation")
+ @Produces(MediaType.APPLICATION_JSON)
+ public String getInstallation() throws IOException {
+ OAuthClientManager manager = new OAuthClientManager(realm);
+ BaseAdapterConfig rep = manager.toInstallationRepresentation(realm, oauthClient, uriInfo.getBaseUri());
+
+ // TODO Temporary solution to pretty-print
+ return JsonSerialization.mapper.writerWithDefaultPrettyPrinter().writeValueAsString(rep);
+ }
+
@DELETE
@NoCache
public void deleteOAuthClient() {
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java
index 6e4101b..eaacae6 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/OAuthClientsResource.java
@@ -15,6 +15,7 @@ import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
+import javax.ws.rs.container.ResourceContext;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@@ -32,6 +33,9 @@ public class OAuthClientsResource {
protected KeycloakSession session;
+ @Context
+ protected ResourceContext resourceContext;
+
public OAuthClientsResource(RealmModel realm, KeycloakSession session) {
this.realm = realm;
this.session = session;
@@ -64,6 +68,7 @@ public class OAuthClientsResource {
throw new NotFoundException();
}
OAuthClientResource oAuthClientResource = new OAuthClientResource(realm, oauth, session);
+ resourceContext.initResource(oAuthClientResource);
return oAuthClientResource;
}
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index a7f06ce..ab8cc39 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -43,6 +43,7 @@ public class RealmAdminResource extends RoleContainerResource {
@Path("oauth-clients")
public OAuthClientsResource getOAuthClients() {
OAuthClientsResource oauth = new OAuthClientsResource(realm, session);
+ resourceContext.initResource(oauth);
return oauth;
}
diff --git a/services/src/main/java/org/keycloak/services/resources/TokenService.java b/services/src/main/java/org/keycloak/services/resources/TokenService.java
index 37cbec3..36bd3f4 100755
--- a/services/src/main/java/org/keycloak/services/resources/TokenService.java
+++ b/services/src/main/java/org/keycloak/services/resources/TokenService.java
@@ -32,6 +32,7 @@ import org.keycloak.services.validation.Validation;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
+import javax.ws.rs.NotAcceptableException;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
@@ -129,6 +130,10 @@ public class TokenService {
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
public Response grantIdentityToken(final MultivaluedMap<String, String> form) {
+ if (!checkSsl()) {
+ throw new NotAcceptableException("HTTPS required");
+ }
+
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
if (username == null) {
throw new NotAuthorizedException("No user");
@@ -155,6 +160,10 @@ public class TokenService {
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON)
public Response grantAccessToken(final MultivaluedMap<String, String> form) {
+ if (!checkSsl()) {
+ throw new NotAcceptableException("HTTPS required");
+ }
+
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
if (username == null) {
throw new NotAuthorizedException("No user");
@@ -187,6 +196,10 @@ public class TokenService {
logger.debug("TokenService.processLogin");
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
+ if (!checkSsl()) {
+ return oauth.forwardToSecurityFailure("HTTPS required");
+ }
+
if (!realm.isEnabled()) {
return oauth.forwardToSecurityFailure("Realm not enabled.");
}
@@ -360,6 +373,11 @@ public class TokenService {
@Produces("application/json")
public Response accessCodeToToken(final MultivaluedMap<String, String> formData) {
logger.debug("accessRequest <---");
+
+ if (!checkSsl()) {
+ throw new NotAcceptableException("HTTPS required");
+ }
+
if (!realm.isEnabled()) {
throw new NotAuthorizedException("Realm not enabled");
}
@@ -480,6 +498,10 @@ public class TokenService {
logger.info("TokenService.loginPage");
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
+ if (!checkSsl()) {
+ return oauth.forwardToSecurityFailure("HTTPS required");
+ }
+
if (!realm.isEnabled()) {
logger.warn("Realm not enabled");
return oauth.forwardToSecurityFailure("Realm not enabled");
@@ -529,6 +551,10 @@ public class TokenService {
logger.info("**********registerPage()");
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
+ if (!checkSsl()) {
+ return oauth.forwardToSecurityFailure("HTTPS required");
+ }
+
if (!realm.isEnabled()) {
logger.warn("Realm not enabled");
return oauth.forwardToSecurityFailure("Realm not enabled");
@@ -581,6 +607,10 @@ public class TokenService {
public Response processOAuth(final MultivaluedMap<String, String> formData) {
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
+ if (!checkSsl()) {
+ return oauth.forwardToSecurityFailure("HTTPS required");
+ }
+
String code = formData.getFirst("code");
JWSInput input = new JWSInput(code);
boolean verifiedCode = false;
@@ -628,4 +658,20 @@ public class TokenService {
}
}
+ private boolean checkSsl() {
+ if (realm.isSslNotRequired()) {
+ return true;
+ }
+
+ if (uriInfo.getBaseUri().getScheme().equals("https")) {
+ return true;
+ }
+
+ if ("https".equals(headers.getHeaderString("X-Forwarded-Proto"))) {
+ return true;
+ }
+
+ return false;
+ }
+
}
diff --git a/services/src/main/java/org/keycloak/services/tmp/TmpAdminRedirectServlet.java b/services/src/main/java/org/keycloak/services/tmp/TmpAdminRedirectServlet.java
new file mode 100644
index 0000000..f00be8d
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/tmp/TmpAdminRedirectServlet.java
@@ -0,0 +1,21 @@
+package org.keycloak.services.tmp;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * TODO Remove once fixed in WildFly (https://issues.jboss.org/browse/WFLY-2687)
+ *
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class TmpAdminRedirectServlet extends HttpServlet {
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ resp.sendRedirect(req.getContextPath() + "/admin/index.html");
+ }
+
+}
diff --git a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
index ab3e4bf..f6affa3 100755
--- a/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
+++ b/testsuite/integration/src/main/java/org/keycloak/testutils/KeycloakServer.java
@@ -33,9 +33,11 @@ import io.undertow.servlet.Servlets;
import io.undertow.servlet.api.DefaultServletConfig;
import io.undertow.servlet.api.DeploymentInfo;
import io.undertow.servlet.api.FilterInfo;
+import io.undertow.servlet.api.ServletInfo;
import org.jboss.resteasy.logging.Logger;
import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer;
import org.jboss.resteasy.spi.ResteasyDeployment;
+import org.keycloak.services.tmp.TmpAdminRedirectServlet;
import org.keycloak.util.JsonSerialization;
import org.keycloak.models.Constants;
import org.keycloak.models.KeycloakSession;
@@ -259,6 +261,10 @@ public class KeycloakServer {
di.addFilter(filter);
di.addFilterUrlMapping("SessionFilter", "/rest/*", DispatcherType.REQUEST);
+ ServletInfo tmpAdminRedirectServlet = Servlets.servlet("TmpAdminRedirectServlet", TmpAdminRedirectServlet.class);
+ tmpAdminRedirectServlet.addMappings("/admin", "/admin/");
+ di.addServlet(tmpAdminRedirectServlet);
+
server.deploy(di);
factory = KeycloakApplication.createSessionFactory();
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
index 0b25e48..2dfdde3 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/oauth/AccessTokenTest.java
@@ -69,7 +69,7 @@ public class AccessTokenTest {
SkeletonKeyToken token = oauth.verifyToken(response.getAccessToken());
- Assert.assertEquals("test-user@localhost", token.getPrincipal());
+ Assert.assertEquals("test-user@localhost", token.getSubject());
Assert.assertEquals(1, token.getRealmAccess().getRoles().size());
Assert.assertTrue(token.getRealmAccess().isUserInRole("user"));
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/social/SocialLoginTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/social/SocialLoginTest.java
index e4c3c6f..d247d39 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/social/SocialLoginTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/social/SocialLoginTest.java
@@ -102,7 +102,7 @@ public class SocialLoginTest {
SkeletonKeyToken token = oauth.verifyToken(response.getAccessToken());
- Assert.assertEquals("dummy-user", token.getPrincipal());
+ Assert.assertEquals("dummy-user", token.getSubject());
}
@Test