commit
67be783503
54 changed files with 1268 additions and 1318 deletions
|
@ -29,15 +29,10 @@
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||||
<artifactId>servlet-api</artifactId>
|
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.jboss.resteasy</groupId>
|
|
||||||
<artifactId>tjws</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>junit</groupId>
|
<groupId>junit</groupId>
|
||||||
<artifactId>junit</artifactId>
|
<artifactId>junit</artifactId>
|
||||||
|
|
|
@ -23,9 +23,9 @@
|
||||||
</repositories>
|
</repositories>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||||
<artifactId>servlet-api</artifactId>
|
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -24,8 +24,8 @@
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||||
<artifactId>servlet-api</artifactId>
|
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
|
@ -11,6 +11,8 @@ import org.keycloak.services.resources.KeycloakApplication;
|
||||||
import org.keycloak.services.resources.SaasService;
|
import org.keycloak.services.resources.SaasService;
|
||||||
import org.keycloak.services.resources.SaasService;
|
import org.keycloak.services.resources.SaasService;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.ws.rs.core.Context;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
@ -20,8 +22,8 @@ import java.io.InputStream;
|
||||||
*/
|
*/
|
||||||
public class DemoApplication extends KeycloakApplication {
|
public class DemoApplication extends KeycloakApplication {
|
||||||
|
|
||||||
public DemoApplication() {
|
public DemoApplication(@Context ServletContext servletContext) {
|
||||||
super();
|
super(servletContext);
|
||||||
KeycloakSession session = factory.createSession();
|
KeycloakSession session = factory.createSession();
|
||||||
session.getTransaction().begin();
|
session.getTransaction().begin();
|
||||||
RealmManager realmManager = new RealmManager(session);
|
RealmManager realmManager = new RealmManager(session);
|
||||||
|
|
|
@ -21,6 +21,16 @@
|
||||||
<async-supported>true</async-supported>
|
<async-supported>true</async-supported>
|
||||||
</servlet>
|
</servlet>
|
||||||
|
|
||||||
|
<filter>
|
||||||
|
<filter-name>Keycloak Session Management</filter-name>
|
||||||
|
<filter-class>org.keycloak.services.filters.KeycloakSessionServletFilter</filter-class>
|
||||||
|
</filter>
|
||||||
|
|
||||||
|
<filter-mapping>
|
||||||
|
<filter-name>Keycloak Session Management</filter-name>
|
||||||
|
<url-pattern>/rest/*</url-pattern>
|
||||||
|
</filter-mapping>
|
||||||
|
|
||||||
<servlet-mapping>
|
<servlet-mapping>
|
||||||
<servlet-name>Resteasy</servlet-name>
|
<servlet-name>Resteasy</servlet-name>
|
||||||
<url-pattern>/rest/*</url-pattern>
|
<url-pattern>/rest/*</url-pattern>
|
||||||
|
|
|
@ -55,11 +55,8 @@ module.config([ '$routeProvider', function($routeProvider) {
|
||||||
resolve : {
|
resolve : {
|
||||||
realm : function(RealmLoader) {
|
realm : function(RealmLoader) {
|
||||||
return RealmLoader();
|
return RealmLoader();
|
||||||
},
|
|
||||||
users : function(UserListLoader) {
|
|
||||||
return UserListLoader();
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
controller : 'UserListCtrl'
|
controller : 'UserListCtrl'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -181,15 +181,39 @@ module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, $ht
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
module.controller('UserListCtrl', function($scope, realm, users) {
|
module.controller('UserListCtrl', function($scope, realm, User) {
|
||||||
$scope.realm = realm;
|
$scope.realm = realm;
|
||||||
$scope.users = users;
|
$scope.users = [];
|
||||||
|
$scope.query = "*";
|
||||||
|
$scope.attribute = {};
|
||||||
|
var params = {};
|
||||||
|
|
||||||
|
$scope.addAttribute = function() {
|
||||||
|
console.log('queryAttribute');
|
||||||
|
params[$scope.attribute.name] = $scope.attribute.value;
|
||||||
|
for (var key in params) {
|
||||||
|
$scope.query = " " + key + "=" +params[key];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.executeQuery = function() {
|
||||||
|
console.log('executeQuery');
|
||||||
|
var parameters = angular.copy(params);
|
||||||
|
parameters["realm"] = realm.id;
|
||||||
|
$scope.users = User.query(parameters);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.clearQuery = function() {
|
||||||
|
params = {};
|
||||||
|
$scopre.query = "*";
|
||||||
|
$scope.users = [];
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
module.controller('UserDetailCtrl', function($scope, realm, user, User, $location, Dialog, Notifications) {
|
module.controller('UserDetailCtrl', function($scope, realm, user, User, $location, Dialog, Notifications) {
|
||||||
$scope.realm = realm;
|
$scope.realm = realm;
|
||||||
$scope.user = angular.copy(user);
|
$scope.user = angular.copy(user);
|
||||||
$scope.create = !user.userId;
|
$scope.create = !user.username;
|
||||||
|
|
||||||
$scope.changed = $scope.create;
|
$scope.changed = $scope.create;
|
||||||
|
|
||||||
|
@ -201,23 +225,28 @@ module.controller('UserDetailCtrl', function($scope, realm, user, User, $locatio
|
||||||
|
|
||||||
$scope.save = function() {
|
$scope.save = function() {
|
||||||
if ($scope.userForm.$valid) {
|
if ($scope.userForm.$valid) {
|
||||||
|
if ($scope.create) {
|
||||||
|
User.save({
|
||||||
|
realm: realm.id
|
||||||
|
}, $scope.user, function () {
|
||||||
|
$scope.changed = false;
|
||||||
|
user = angular.copy($scope.user);
|
||||||
|
|
||||||
|
$location.url("/realms/" + realm.id + "/users/" + $scope.user.username);
|
||||||
|
Notifications.success("Created user");
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
User.update({
|
||||||
|
realm: realm.id,
|
||||||
|
userId: $scope.user.username
|
||||||
|
}, $scope.user, function () {
|
||||||
|
$scope.changed = false;
|
||||||
|
user = angular.copy($scope.user);
|
||||||
|
Notifications.success("Saved changes to user");
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
User.save({
|
} else {
|
||||||
realm : realm.id
|
|
||||||
}, $scope.user, function() {
|
|
||||||
$scope.changed = false;
|
|
||||||
user = angular.copy($scope.user);
|
|
||||||
|
|
||||||
if ($scope.create) {
|
|
||||||
$location.url("/realms/" + realm.id + "/users/" + $scope.user.userId);
|
|
||||||
Notifications.success("Created user");
|
|
||||||
} else {
|
|
||||||
Notifications.success("Saved changes to user");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
$scope.userForm.showErrors = true;
|
$scope.userForm.showErrors = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -236,7 +265,7 @@ module.controller('UserDetailCtrl', function($scope, realm, user, User, $locatio
|
||||||
Dialog.confirmDelete($scope.user.userId, 'user', function() {
|
Dialog.confirmDelete($scope.user.userId, 'user', function() {
|
||||||
$scope.user.$remove({
|
$scope.user.$remove({
|
||||||
realm : realm.id,
|
realm : realm.id,
|
||||||
userId : $scope.user.userId
|
userId : $scope.user.username
|
||||||
}, function() {
|
}, function() {
|
||||||
$location.url("/realms/" + realm.id + "/users");
|
$location.url("/realms/" + realm.id + "/users");
|
||||||
Notifications.success("Deleted user");
|
Notifications.success("Deleted user");
|
||||||
|
|
|
@ -110,11 +110,11 @@ module.factory('RoleMapping', function($resource) {
|
||||||
});
|
});
|
||||||
|
|
||||||
module.factory('User', function($resource) {
|
module.factory('User', function($resource) {
|
||||||
return $resource('/keycloak-server/ui/api/realms/:realm/users/:userId', {
|
return $resource('/auth-server/rest/saas/admin/realms/:realm/users/:userId', {
|
||||||
realm : '@realm',
|
realm : '@realm',
|
||||||
userId : '@userId'
|
userId : '@userId'
|
||||||
}, {
|
}, {
|
||||||
save : {
|
update : {
|
||||||
method : 'PUT'
|
method : 'PUT'
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<li data-ng-class="path[0] == 'create' && path[1] == 'user' && 'active'"><a
|
<li data-ng-class="path[0] == 'create' && path[1] == 'user' && 'active'"><a
|
||||||
href="#/create/user/{{realm.id}}">New User</a></li>
|
href="#/create/user/{{realm.id}}">New User</a></li>
|
||||||
<li data-ng-class="path[0] == 'find' && path[1] == 'user' && 'active'"><a
|
<li data-ng-class="path[0] == 'find' && path[1] == 'user' && 'active'"><a
|
||||||
href="#/find/user/{{realm.id}}">Find User</a></li>
|
href="#/realms/{{realm.id}}/users">Find User</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li data-ng-class="path[2] == 'roles' && 'active'"><a href="#/realms/{{realm.id}}/roles">Roles</a>
|
<li data-ng-class="path[2] == 'roles' && 'active'"><a href="#/realms/{{realm.id}}/roles">Roles</a>
|
||||||
|
|
|
@ -13,13 +13,13 @@
|
||||||
<div data-ng-show="roleForm.showErrors && roleForm.$error.required" class="alert alert-error">Please fill in
|
<div data-ng-show="roleForm.showErrors && roleForm.$error.required" class="alert alert-error">Please fill in
|
||||||
all required fields
|
all required fields
|
||||||
</div>
|
</div>
|
||||||
<p class="subtitle subtitle-right"><span class="required">*</span> Required fields</p>
|
<p class="subtitle subtitle-right" data-ng-show="create"><span class="required">*</span> Required fields</p>
|
||||||
|
|
||||||
<form class="form-horizontal" name="roleForm" novalidate>
|
<form class="form-horizontal" name="roleForm" novalidate>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Details</legend>
|
<legend>Details</legend>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label" for="name">Role name <span class="required">*</span></label>
|
<label class="control-label" for="name">Role name <span class="required" data-ng-show="create">*</span></label>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" class="input-xlarge" id="name" name="name" data-ng-model="role.name"
|
<input type="text" class="input-xlarge" id="name" name="name" data-ng-model="role.name"
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
<div id="actions-bg"></div>
|
<div id="actions-bg"></div>
|
||||||
|
|
||||||
<div id="container-right" class="span9">
|
<div id="container-right" class="span9">
|
||||||
<a class="btn btn-small pull-right" href="#/create/role/{{realm.id}}">Add Role</a>
|
|
||||||
|
|
||||||
<h1>
|
<h1>
|
||||||
<span class="gray">Realm Roles</span>
|
<span class="gray">Realm Roles</span>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
|
@ -7,26 +7,35 @@
|
||||||
<h1 data-ng-show="create"><span class="gray">New User</span></h1>
|
<h1 data-ng-show="create"><span class="gray">New User</span></h1>
|
||||||
|
|
||||||
<h1 data-ng-hide="create">
|
<h1 data-ng-hide="create">
|
||||||
<span class="gray">{{user.userId}}</span> configuration
|
<span class="gray">User {{user.username}}</span>
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<div data-ng-show="userForm.showErrors && userForm.$error.required" class="alert alert-error">Please fill in
|
<div data-ng-show="userForm.showErrors && userForm.$error.required" class="alert alert-error">Please fill in
|
||||||
all required fields
|
all required fields
|
||||||
</div>
|
</div>
|
||||||
<p class="subtitle subtitle-right"><span class="required">*</span> Required fields</p>
|
<p class="subtitle subtitle-right" data-ng-show="create"><span class="required">*</span> Required fields</p>
|
||||||
|
|
||||||
<form class="form-horizontal" name="userForm" novalidate>
|
<form class="form-horizontal" name="userForm" novalidate>
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Details</legend>
|
<legend>Details</legend>
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label" for="name">Username <span class="required">*</span></label>
|
<label class="control-label" for="name">Username <span class="required" data-ng-show="create">*</span></label>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<input type="text" class="input-xlarge" id="name" name="name" data-ng-model="user.userId"
|
<input type="text" class="input-xlarge" id="name" name="name" data-ng-model="user.username"
|
||||||
autofocus required data-ng-readonly="!create">
|
autofocus required data-ng-readonly="!create">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label">Enabled</label>
|
||||||
|
|
||||||
|
<div class="controls">
|
||||||
|
<input class="input-xlarge" type="checkbox" name="enabled"
|
||||||
|
data-ng-model="realm.enabled">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label class="control-label" for="email">Email </label>
|
<label class="control-label" for="email">Email </label>
|
||||||
|
|
||||||
|
@ -52,15 +61,6 @@
|
||||||
<input type="text" class="input-xlarge" id="lastName" data-ng-model="user.lastName">
|
<input type="text" class="input-xlarge" id="lastName" data-ng-model="user.lastName">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
|
||||||
<label class="control-label" for="password">Password <span class="required">*</span></label>
|
|
||||||
|
|
||||||
<div class="controls">
|
|
||||||
<input type="password" class="input-xlarge" id="password" name="password"
|
|
||||||
data-ng-model="user.password" data-ng-required="create">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<fieldset data-ng-show="user.attributes.length > 0">
|
<fieldset data-ng-show="user.attributes.length > 0">
|
||||||
|
@ -94,7 +94,6 @@
|
||||||
</button>
|
</button>
|
||||||
<button type="submit" data-ng-click="reset()" class="btn" data-ng-show="changed">Clear changes
|
<button type="submit" data-ng-click="reset()" class="btn" data-ng-show="changed">Clear changes
|
||||||
</button>
|
</button>
|
||||||
<a href="#/realms/{{realm.id}}/users" data-ng-hide="changed">View users »</a>
|
|
||||||
<button type="submit" data-ng-click="remove()" class="btn btn-danger" data-ng-hide="changed">
|
<button type="submit" data-ng-click="remove()" class="btn btn-danger" data-ng-hide="changed">
|
||||||
Delete
|
Delete
|
||||||
</button>
|
</button>
|
||||||
|
|
|
@ -3,13 +3,42 @@
|
||||||
<aside class="span3" data-ng-include data-src="'partials/realm-menu.html'"></aside>
|
<aside class="span3" data-ng-include data-src="'partials/realm-menu.html'"></aside>
|
||||||
<div id="actions-bg"></div>
|
<div id="actions-bg"></div>
|
||||||
|
|
||||||
|
|
||||||
<div id="container-right" class="span9">
|
<div id="container-right" class="span9">
|
||||||
<a class="btn btn-small pull-right" href="#/create/user/{{realm.id}}">Add User</a>
|
<form class="form-horizontal" name="queryForm" novalidate>
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label">Query </label>
|
||||||
|
|
||||||
<h1>
|
<div class="controls">
|
||||||
<span class="gray">{{realm.name}}</span> users
|
<input type="text" class="input-xlarge" id="query" name="query" data-ng-model="query"
|
||||||
</h1>
|
autofocus required readonly>
|
||||||
|
<button type="submit" data-ng-click="executeQuery()" class="btn btn-primary">Execute Query
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form class="form-horizontal" name="queryAttribute" novalidate>
|
||||||
|
<fieldset>
|
||||||
|
<div class="control-group">
|
||||||
|
<label class="control-label">Predefined Attribute</label>
|
||||||
|
|
||||||
|
<div class="controls">
|
||||||
|
<select style="width: auto;" name="name"
|
||||||
|
data-ng-model="attribute.name">
|
||||||
|
<option value="loginName">Login name</option>
|
||||||
|
<option value="lastName">Last name</option>
|
||||||
|
<option value="firstName">First name</option>
|
||||||
|
<option value="email">Email</option>
|
||||||
|
</select>
|
||||||
|
<input class="input-small" type="text" name="value"
|
||||||
|
data-ng-model="attribute.value">
|
||||||
|
<button type="submit" data-ng-click="addAttribute()" class="btn btn-primary">Add Attribute
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
<table class="table table-striped table-bordered">
|
<table class="table table-striped table-bordered">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -20,7 +49,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tr data-ng-repeat="user in users">
|
<tr data-ng-repeat="user in users">
|
||||||
<td><a href="#/realms/{{realm.id}}/users/{{user.userId}}">{{user.userId}}</a></td>
|
<td><a href="#/realms/{{realm.id}}/users/{{user.username}}">{{user.username}}</a></td>
|
||||||
<td>{{user.firstName}}</td>
|
<td>{{user.firstName}}</td>
|
||||||
<td>{{user.lastName}}</td>
|
<td>{{user.lastName}}</td>
|
||||||
<td>{{user.email}}</td>
|
<td>{{user.email}}</td>
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jboss.spec.javax.servlet</groupId>
|
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||||
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||||
<version>1.0.0.Final</version>
|
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|
25
pom.xml
25
pom.xml
|
@ -9,7 +9,8 @@
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<resteasy.version>3.0.2.Final</resteasy.version>
|
<resteasy.version>3.0.4.Final</resteasy.version>
|
||||||
|
<undertow.version>1.0.0.Beta12</undertow.version>
|
||||||
<picketlink.version>2.5.0.Beta6</picketlink.version>
|
<picketlink.version>2.5.0.Beta6</picketlink.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
@ -108,7 +109,21 @@
|
||||||
<groupId>org.jboss.resteasy</groupId>
|
<groupId>org.jboss.resteasy</groupId>
|
||||||
<artifactId>tjws</artifactId>
|
<artifactId>tjws</artifactId>
|
||||||
<version>${resteasy.version}</version>
|
<version>${resteasy.version}</version>
|
||||||
<scope>provided</scope>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jboss.resteasy</groupId>
|
||||||
|
<artifactId>resteasy-undertow</artifactId>
|
||||||
|
<version>${resteasy.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.undertow</groupId>
|
||||||
|
<artifactId>undertow-servlet</artifactId>
|
||||||
|
<version>${undertow.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.undertow</groupId>
|
||||||
|
<artifactId>undertow-core</artifactId>
|
||||||
|
<version>${undertow.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.codehaus.jackson</groupId>
|
<groupId>org.codehaus.jackson</groupId>
|
||||||
|
@ -131,9 +146,9 @@
|
||||||
<version>1.9.12</version>
|
<version>1.9.12</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||||
<artifactId>servlet-api</artifactId>
|
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||||
<version>2.5</version>
|
<version>1.0.1.Final</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jboss.resteasy</groupId>
|
<groupId>org.jboss.resteasy</groupId>
|
||||||
|
|
|
@ -79,12 +79,7 @@
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jboss.resteasy</groupId>
|
|
||||||
<artifactId>tjws</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jboss.resteasy</groupId>
|
<groupId>org.jboss.resteasy</groupId>
|
||||||
<artifactId>jaxrs-api</artifactId>
|
<artifactId>jaxrs-api</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
|
@ -105,13 +100,18 @@
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>org.jboss.resteasy</groupId>
|
||||||
<artifactId>servlet-api</artifactId>
|
<artifactId>resteasy-undertow</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jboss.resteasy</groupId>
|
<groupId>io.undertow</groupId>
|
||||||
<artifactId>tjws</artifactId>
|
<artifactId>undertow-servlet</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.undertow</groupId>
|
||||||
|
<artifactId>undertow-core</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
@ -124,6 +124,11 @@
|
||||||
<artifactId>jackson-mapper-asl</artifactId>
|
<artifactId>jackson-mapper-asl</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.jboss.spec.javax.servlet</groupId>
|
||||||
|
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.codehaus.jackson</groupId>
|
<groupId>org.codehaus.jackson</groupId>
|
||||||
<artifactId>jackson-xc</artifactId>
|
<artifactId>jackson-xc</artifactId>
|
||||||
|
|
|
@ -7,8 +7,6 @@ import org.keycloak.services.models.KeycloakSessionFactory;
|
||||||
|
|
||||||
import javax.ws.rs.container.ContainerRequestContext;
|
import javax.ws.rs.container.ContainerRequestContext;
|
||||||
import javax.ws.rs.container.ContainerRequestFilter;
|
import javax.ws.rs.container.ContainerRequestFilter;
|
||||||
import javax.ws.rs.container.ContainerResponseContext;
|
|
||||||
import javax.ws.rs.container.ContainerResponseFilter;
|
|
||||||
import javax.ws.rs.container.PreMatching;
|
import javax.ws.rs.container.PreMatching;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
package org.keycloak.services.filters;
|
||||||
|
|
||||||
|
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||||
|
import org.keycloak.services.models.KeycloakSession;
|
||||||
|
import org.keycloak.services.models.KeycloakSessionFactory;
|
||||||
|
import org.keycloak.services.models.KeycloakTransaction;
|
||||||
|
|
||||||
|
import javax.servlet.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class KeycloakSessionServletFilter implements Filter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(FilterConfig filterConfig) throws ServletException {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
|
||||||
|
KeycloakSessionFactory factory = (KeycloakSessionFactory)servletRequest.getServletContext().getAttribute(KeycloakSessionFactory.class.getName());
|
||||||
|
if (factory == null) throw new ServletException("Factory was null");
|
||||||
|
KeycloakSession session = factory.createSession();
|
||||||
|
ResteasyProviderFactory.pushContext(KeycloakSession.class, session);
|
||||||
|
KeycloakTransaction tx = session.getTransaction();
|
||||||
|
ResteasyProviderFactory.pushContext(KeycloakTransaction.class, tx);
|
||||||
|
tx.begin();
|
||||||
|
try {
|
||||||
|
filterChain.doFilter(servletRequest, servletResponse);
|
||||||
|
if (tx.isActive()) {
|
||||||
|
if (tx.getRollbackOnly()) tx.rollback();
|
||||||
|
else tx.commit();
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
if (tx.isActive()) tx.rollback();
|
||||||
|
throw ex;
|
||||||
|
} catch (ServletException ex) {
|
||||||
|
if (tx.isActive()) tx.rollback();
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
catch (RuntimeException ex) {
|
||||||
|
if (tx.isActive()) tx.rollback();
|
||||||
|
throw ex;
|
||||||
|
} finally {
|
||||||
|
session.close();
|
||||||
|
ResteasyProviderFactory.clearContextData();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,11 +16,7 @@ import org.keycloak.services.resources.RealmsResource;
|
||||||
import org.keycloak.services.resources.SaasService;
|
import org.keycloak.services.resources.SaasService;
|
||||||
|
|
||||||
import javax.ws.rs.NotAuthorizedException;
|
import javax.ws.rs.NotAuthorizedException;
|
||||||
import javax.ws.rs.core.Cookie;
|
import javax.ws.rs.core.*;
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
|
||||||
import javax.ws.rs.core.NewCookie;
|
|
||||||
import javax.ws.rs.core.UriInfo;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
|
@ -7,7 +7,10 @@ import org.keycloak.services.models.*;
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.KeyPairGenerator;
|
import java.security.KeyPairGenerator;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.*;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,8 +5,8 @@ import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||||
import org.jboss.resteasy.logging.Logger;
|
import org.jboss.resteasy.logging.Logger;
|
||||||
import org.keycloak.TokenIdGenerator;
|
import org.keycloak.TokenIdGenerator;
|
||||||
import org.keycloak.representations.idm.admin.LogoutAction;
|
import org.keycloak.representations.idm.admin.LogoutAction;
|
||||||
import org.keycloak.services.models.RealmModel;
|
|
||||||
import org.keycloak.services.models.ApplicationModel;
|
import org.keycloak.services.models.ApplicationModel;
|
||||||
|
import org.keycloak.services.models.RealmModel;
|
||||||
|
|
||||||
import javax.ws.rs.client.Entity;
|
import javax.ws.rs.client.Entity;
|
||||||
import javax.ws.rs.core.Form;
|
import javax.ws.rs.core.Form;
|
||||||
|
|
|
@ -1,12 +1,7 @@
|
||||||
package org.keycloak.services.managers;
|
package org.keycloak.services.managers;
|
||||||
|
|
||||||
import org.keycloak.representations.idm.*;
|
import org.keycloak.representations.idm.*;
|
||||||
import org.keycloak.representations.idm.ApplicationRepresentation;
|
import org.keycloak.services.models.*;
|
||||||
import org.keycloak.services.models.RealmModel;
|
|
||||||
import org.keycloak.services.models.ApplicationModel;
|
|
||||||
import org.keycloak.services.models.RoleModel;
|
|
||||||
import org.keycloak.services.models.UserCredentialModel;
|
|
||||||
import org.keycloak.services.models.UserModel;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
|
|
@ -5,8 +5,8 @@ import org.jboss.resteasy.jose.jws.JWSBuilder;
|
||||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||||
import org.keycloak.representations.SkeletonKeyScope;
|
import org.keycloak.representations.SkeletonKeyScope;
|
||||||
import org.keycloak.representations.SkeletonKeyToken;
|
import org.keycloak.representations.SkeletonKeyToken;
|
||||||
import org.keycloak.services.models.RealmModel;
|
|
||||||
import org.keycloak.services.models.ApplicationModel;
|
import org.keycloak.services.models.ApplicationModel;
|
||||||
|
import org.keycloak.services.models.RealmModel;
|
||||||
import org.keycloak.services.models.RoleModel;
|
import org.keycloak.services.models.RoleModel;
|
||||||
import org.keycloak.services.models.UserModel;
|
import org.keycloak.services.models.UserModel;
|
||||||
|
|
||||||
|
|
89
services/src/main/java/org/keycloak/services/managers/UserManager.java
Executable file
89
services/src/main/java/org/keycloak/services/managers/UserManager.java
Executable file
|
@ -0,0 +1,89 @@
|
||||||
|
package org.keycloak.services.managers;
|
||||||
|
|
||||||
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
|
import org.keycloak.services.models.RealmModel;
|
||||||
|
import org.keycloak.services.models.UserCredentialModel;
|
||||||
|
import org.keycloak.services.models.UserModel;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class UserManager {
|
||||||
|
|
||||||
|
public static UserRepresentation toRepresentation(UserModel user) {
|
||||||
|
UserRepresentation rep = new UserRepresentation();
|
||||||
|
rep.setEmail(user.getEmail());
|
||||||
|
rep.setLastName(user.getLastName());
|
||||||
|
rep.setFirstName(user.getFirstName());
|
||||||
|
rep.setEnabled(user.isEnabled());
|
||||||
|
rep.setUsername(user.getLoginName());
|
||||||
|
for (Map.Entry<String, String> entry : user.getAttributes().entrySet()) {
|
||||||
|
rep.attribute(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
return rep;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserModel createUser(RealmModel newRealm, UserRepresentation userRep) {
|
||||||
|
UserModel user = newRealm.addUser(userRep.getUsername());
|
||||||
|
user.setEnabled(userRep.isEnabled());
|
||||||
|
user.setEmail(userRep.getEmail());
|
||||||
|
user.setFirstName(userRep.getFirstName());
|
||||||
|
user.setLastName(userRep.getLastName());
|
||||||
|
if (userRep.getAttributes() != null) {
|
||||||
|
for (Map.Entry<String, String> entry : userRep.getAttributes().entrySet()) {
|
||||||
|
user.setAttribute(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (userRep.getCredentials() != null) {
|
||||||
|
for (CredentialRepresentation cred : userRep.getCredentials()) {
|
||||||
|
UserCredentialModel credential = new UserCredentialModel();
|
||||||
|
credential.setType(cred.getType());
|
||||||
|
credential.setValue(cred.getValue());
|
||||||
|
newRealm.updateCredential(user, credential);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Doesn't allow you to change loginname.
|
||||||
|
*
|
||||||
|
* @param user
|
||||||
|
* @param userRep
|
||||||
|
*/
|
||||||
|
public void updateUserAsAdmin(UserModel user, UserRepresentation userRep) {
|
||||||
|
user.setEnabled(userRep.isEnabled());
|
||||||
|
user.setEmail(userRep.getEmail());
|
||||||
|
user.setFirstName(userRep.getFirstName());
|
||||||
|
user.setLastName(userRep.getLastName());
|
||||||
|
if (userRep.getAttributes() != null) {
|
||||||
|
for (Map.Entry<String, String> entry : userRep.getAttributes().entrySet()) {
|
||||||
|
user.setAttribute(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Doesn't allow you to change loginname.
|
||||||
|
* Doesn't allow you to change enable
|
||||||
|
*
|
||||||
|
* @param user
|
||||||
|
* @param userRep
|
||||||
|
*/
|
||||||
|
public void updateUserAsUser(UserModel user, UserRepresentation userRep) {
|
||||||
|
user.setEmail(userRep.getEmail());
|
||||||
|
user.setFirstName(userRep.getFirstName());
|
||||||
|
user.setLastName(userRep.getLastName());
|
||||||
|
if (userRep.getAttributes() != null) {
|
||||||
|
for (Map.Entry<String, String> entry : userRep.getAttributes().entrySet()) {
|
||||||
|
user.setAttribute(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -7,6 +7,10 @@ import java.util.Map;
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public interface UserModel {
|
public interface UserModel {
|
||||||
|
public static final String LAST_NAME = "lastName";
|
||||||
|
public static final String FIRST_NAME = "firstName";
|
||||||
|
public static final String EMAIL = "email";
|
||||||
|
|
||||||
String getLoginName();
|
String getLoginName();
|
||||||
|
|
||||||
boolean isEnabled();
|
boolean isEnabled();
|
||||||
|
|
|
@ -1,13 +1,7 @@
|
||||||
package org.keycloak.services.models.jpa.entities;
|
package org.keycloak.services.models.jpa.entities;
|
||||||
|
|
||||||
|
|
||||||
import javax.persistence.CascadeType;
|
import javax.persistence.*;
|
||||||
import javax.persistence.Column;
|
|
||||||
import javax.persistence.FetchType;
|
|
||||||
import javax.persistence.GeneratedValue;
|
|
||||||
import javax.persistence.Id;
|
|
||||||
import javax.persistence.MapKey;
|
|
||||||
import javax.persistence.OneToMany;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,13 +1,6 @@
|
||||||
package org.keycloak.services.models.jpa.entities;
|
package org.keycloak.services.models.jpa.entities;
|
||||||
|
|
||||||
import javax.persistence.CascadeType;
|
import javax.persistence.*;
|
||||||
import javax.persistence.Entity;
|
|
||||||
import javax.persistence.FetchType;
|
|
||||||
import javax.persistence.GeneratedValue;
|
|
||||||
import javax.persistence.Id;
|
|
||||||
import javax.persistence.ManyToOne;
|
|
||||||
import javax.persistence.OneToMany;
|
|
||||||
import javax.persistence.OneToOne;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -4,7 +4,6 @@ import javax.persistence.Entity;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.OneToOne;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
|
|
@ -3,7 +3,6 @@ package org.keycloak.services.models.picketlink;
|
||||||
import org.keycloak.services.models.UserModel;
|
import org.keycloak.services.models.UserModel;
|
||||||
import org.picketlink.idm.IdentityManager;
|
import org.picketlink.idm.IdentityManager;
|
||||||
import org.picketlink.idm.model.Attribute;
|
import org.picketlink.idm.model.Attribute;
|
||||||
import org.picketlink.idm.model.annotation.AttributeProperty;
|
|
||||||
import org.picketlink.idm.model.sample.User;
|
import org.picketlink.idm.model.sample.User;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.keycloak.services.models.picketlink.mappings;
|
package org.keycloak.services.models.picketlink.mappings;
|
||||||
|
|
||||||
import org.picketlink.idm.jpa.annotations.AttributeValue;
|
|
||||||
import org.picketlink.idm.model.AbstractPartition;
|
import org.picketlink.idm.model.AbstractPartition;
|
||||||
import org.picketlink.idm.model.annotation.AttributeProperty;
|
import org.picketlink.idm.model.annotation.AttributeProperty;
|
||||||
import org.picketlink.idm.model.sample.User;
|
import org.picketlink.idm.model.sample.User;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.keycloak.services.models.picketlink.mappings;
|
package org.keycloak.services.models.picketlink.mappings;
|
||||||
|
|
||||||
import org.picketlink.idm.jpa.annotations.AttributeValue;
|
|
||||||
import org.picketlink.idm.model.AbstractPartition;
|
import org.picketlink.idm.model.AbstractPartition;
|
||||||
import org.picketlink.idm.model.annotation.AttributeProperty;
|
import org.picketlink.idm.model.annotation.AttributeProperty;
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
package org.keycloak.services.models.picketlink.relationships;
|
package org.keycloak.services.models.picketlink.relationships;
|
||||||
|
|
||||||
import org.keycloak.services.models.picketlink.mappings.RealmData;
|
|
||||||
import org.picketlink.idm.model.AbstractAttributedType;
|
import org.picketlink.idm.model.AbstractAttributedType;
|
||||||
import org.picketlink.idm.model.Attribute;
|
import org.picketlink.idm.model.Attribute;
|
||||||
import org.picketlink.idm.model.Relationship;
|
import org.picketlink.idm.model.Relationship;
|
||||||
import org.picketlink.idm.model.annotation.AttributeProperty;
|
|
||||||
import org.picketlink.idm.model.sample.User;
|
import org.picketlink.idm.model.sample.User;
|
||||||
import org.picketlink.idm.query.AttributeParameter;
|
import org.picketlink.idm.query.AttributeParameter;
|
||||||
import org.picketlink.idm.query.RelationshipQueryParameter;
|
import org.picketlink.idm.query.RelationshipQueryParameter;
|
||||||
|
|
250
services/src/main/java/org/keycloak/services/resources/AccountService.java
Normal file → Executable file
250
services/src/main/java/org/keycloak/services/resources/AccountService.java
Normal file → Executable file
|
@ -21,18 +21,6 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.services.resources;
|
package org.keycloak.services.resources;
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
|
||||||
import javax.ws.rs.GET;
|
|
||||||
import javax.ws.rs.POST;
|
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.core.Context;
|
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import javax.ws.rs.core.UriInfo;
|
|
||||||
import javax.ws.rs.core.Response.Status;
|
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.jboss.resteasy.spi.HttpRequest;
|
||||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
import org.keycloak.services.managers.AuthenticationManager;
|
import org.keycloak.services.managers.AuthenticationManager;
|
||||||
|
@ -45,6 +33,13 @@ import org.keycloak.services.resources.flows.FormFlows;
|
||||||
import org.keycloak.services.validation.Validation;
|
import org.keycloak.services.validation.Validation;
|
||||||
import org.picketlink.idm.credential.util.TimeBasedOTP;
|
import org.picketlink.idm.credential.util.TimeBasedOTP;
|
||||||
|
|
||||||
|
import javax.ws.rs.Consumes;
|
||||||
|
import javax.ws.rs.GET;
|
||||||
|
import javax.ws.rs.POST;
|
||||||
|
import javax.ws.rs.Path;
|
||||||
|
import javax.ws.rs.core.*;
|
||||||
|
import javax.ws.rs.core.Response.Status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
|
@ -70,184 +65,151 @@ public class AccountService {
|
||||||
@Path("access")
|
@Path("access")
|
||||||
@GET
|
@GET
|
||||||
public Response accessPage() {
|
public Response accessPage() {
|
||||||
return new Transaction<Response>() {
|
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
||||||
protected Response callImpl() {
|
if (user != null) {
|
||||||
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
return Flows.forms(realm, request).setUser(user).forwardToAccess();
|
||||||
if (user != null) {
|
} else {
|
||||||
return Flows.forms(realm, request).setUser(user).forwardToAccess();
|
return Response.status(Status.FORBIDDEN).build();
|
||||||
} else {
|
}
|
||||||
return Response.status(Status.FORBIDDEN).build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("")
|
@Path("")
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
public Response processAccountUpdate(final MultivaluedMap<String, String> formData) {
|
public Response processAccountUpdate(final MultivaluedMap<String, String> formData) {
|
||||||
return new Transaction<Response>() {
|
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
||||||
protected Response callImpl() {
|
if (user != null) {
|
||||||
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
user.setFirstName(formData.getFirst("firstName"));
|
||||||
if (user != null) {
|
user.setLastName(formData.getFirst("lastName"));
|
||||||
user.setFirstName(formData.getFirst("firstName"));
|
user.setEmail(formData.getFirst("email"));
|
||||||
user.setLastName(formData.getFirst("lastName"));
|
|
||||||
user.setEmail(formData.getFirst("email"));
|
|
||||||
|
|
||||||
return Flows.forms(realm, request).setUser(user).forwardToAccount();
|
return Flows.forms(realm, request).setUser(user).forwardToAccount();
|
||||||
} else {
|
} else {
|
||||||
return Response.status(Status.FORBIDDEN).build();
|
return Response.status(Status.FORBIDDEN).build();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("totp")
|
@Path("totp")
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
public Response processTotpUpdate(final MultivaluedMap<String, String> formData) {
|
public Response processTotpUpdate(final MultivaluedMap<String, String> formData) {
|
||||||
return new Transaction<Response>() {
|
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
||||||
protected Response callImpl() {
|
if (user != null) {
|
||||||
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
FormFlows forms = Flows.forms(realm, request);
|
||||||
if (user != null) {
|
|
||||||
FormFlows forms = Flows.forms(realm, request);
|
|
||||||
|
|
||||||
String totp = formData.getFirst("totp");
|
String totp = formData.getFirst("totp");
|
||||||
String totpSecret = formData.getFirst("totpSecret");
|
String totpSecret = formData.getFirst("totpSecret");
|
||||||
|
|
||||||
String error = null;
|
String error = null;
|
||||||
|
|
||||||
if (Validation.isEmpty(totp)) {
|
if (Validation.isEmpty(totp)) {
|
||||||
error = Messages.MISSING_TOTP;
|
error = Messages.MISSING_TOTP;
|
||||||
} else if (!new TimeBasedOTP().validate(totp, totpSecret.getBytes())) {
|
} else if (!new TimeBasedOTP().validate(totp, totpSecret.getBytes())) {
|
||||||
error = Messages.INVALID_TOTP;
|
error = Messages.INVALID_TOTP;
|
||||||
}
|
|
||||||
|
|
||||||
if (error != null) {
|
|
||||||
return forms.setError(error).forwardToTotp();
|
|
||||||
}
|
|
||||||
|
|
||||||
UserCredentialModel credentials = new UserCredentialModel();
|
|
||||||
credentials.setType(CredentialRepresentation.TOTP);
|
|
||||||
credentials.setValue(formData.getFirst("totpSecret"));
|
|
||||||
realm.updateCredential(user, credentials);
|
|
||||||
|
|
||||||
if (!user.isEnabled() && "REQUIRED".equals(user.getAttribute("KEYCLOAK_TOTP"))) {
|
|
||||||
user.setEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
user.setAttribute("KEYCLOAK_TOTP", "ENABLED");
|
|
||||||
|
|
||||||
return Flows.forms(realm, request).setUser(user).forwardToTotp();
|
|
||||||
} else {
|
|
||||||
return Response.status(Status.FORBIDDEN).build();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}.call();
|
|
||||||
|
if (error != null) {
|
||||||
|
return forms.setError(error).forwardToTotp();
|
||||||
|
}
|
||||||
|
|
||||||
|
UserCredentialModel credentials = new UserCredentialModel();
|
||||||
|
credentials.setType(CredentialRepresentation.TOTP);
|
||||||
|
credentials.setValue(formData.getFirst("totpSecret"));
|
||||||
|
realm.updateCredential(user, credentials);
|
||||||
|
|
||||||
|
if (!user.isEnabled() && "REQUIRED".equals(user.getAttribute("KEYCLOAK_TOTP"))) {
|
||||||
|
user.setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
user.setAttribute("KEYCLOAK_TOTP", "ENABLED");
|
||||||
|
|
||||||
|
return Flows.forms(realm, request).setUser(user).forwardToTotp();
|
||||||
|
} else {
|
||||||
|
return Response.status(Status.FORBIDDEN).build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("password")
|
@Path("password")
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
public Response processPasswordUpdate(final MultivaluedMap<String, String> formData) {
|
public Response processPasswordUpdate(final MultivaluedMap<String, String> formData) {
|
||||||
return new Transaction<Response>() {
|
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
||||||
protected Response callImpl() {
|
if (user != null) {
|
||||||
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
FormFlows forms = Flows.forms(realm, request).setUser(user);
|
||||||
if (user != null) {
|
|
||||||
FormFlows forms = Flows.forms(realm, request).setUser(user);
|
|
||||||
|
|
||||||
String password = formData.getFirst("password");
|
String password = formData.getFirst("password");
|
||||||
String passwordNew = formData.getFirst("password-new");
|
String passwordNew = formData.getFirst("password-new");
|
||||||
String passwordConfirm = formData.getFirst("password-confirm");
|
String passwordConfirm = formData.getFirst("password-confirm");
|
||||||
|
|
||||||
String error = null;
|
String error = null;
|
||||||
|
|
||||||
if (Validation.isEmpty(password)) {
|
if (Validation.isEmpty(password)) {
|
||||||
error = Messages.MISSING_PASSWORD;
|
error = Messages.MISSING_PASSWORD;
|
||||||
} else if (Validation.isEmpty(passwordNew)) {
|
} else if (Validation.isEmpty(passwordNew)) {
|
||||||
error = Messages.MISSING_PASSWORD;
|
error = Messages.MISSING_PASSWORD;
|
||||||
} else if (!passwordNew.equals(passwordConfirm)) {
|
} else if (!passwordNew.equals(passwordConfirm)) {
|
||||||
error = Messages.INVALID_PASSWORD_CONFIRM;
|
error = Messages.INVALID_PASSWORD_CONFIRM;
|
||||||
} else if (!realm.validatePassword(user, password)) {
|
} else if (!realm.validatePassword(user, password)) {
|
||||||
error = Messages.INVALID_PASSWORD_EXISTING;
|
error = Messages.INVALID_PASSWORD_EXISTING;
|
||||||
}
|
|
||||||
|
|
||||||
if (error != null) {
|
|
||||||
return forms.setError(error).forwardToPassword();
|
|
||||||
}
|
|
||||||
|
|
||||||
UserCredentialModel credentials = new UserCredentialModel();
|
|
||||||
credentials.setType(CredentialRepresentation.PASSWORD);
|
|
||||||
credentials.setValue(passwordNew);
|
|
||||||
|
|
||||||
realm.updateCredential(user, credentials);
|
|
||||||
|
|
||||||
return Flows.forms(realm, request).setUser(user).forwardToPassword();
|
|
||||||
} else {
|
|
||||||
return Response.status(Status.FORBIDDEN).build();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}.call();
|
|
||||||
|
if (error != null) {
|
||||||
|
return forms.setError(error).forwardToPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
UserCredentialModel credentials = new UserCredentialModel();
|
||||||
|
credentials.setType(CredentialRepresentation.PASSWORD);
|
||||||
|
credentials.setValue(passwordNew);
|
||||||
|
|
||||||
|
realm.updateCredential(user, credentials);
|
||||||
|
|
||||||
|
return Flows.forms(realm, request).setUser(user).forwardToPassword();
|
||||||
|
} else {
|
||||||
|
return Response.status(Status.FORBIDDEN).build();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("")
|
@Path("")
|
||||||
@GET
|
@GET
|
||||||
public Response accountPage() {
|
public Response accountPage() {
|
||||||
return new Transaction<Response>() {
|
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
||||||
protected Response callImpl() {
|
if (user != null) {
|
||||||
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
return Flows.forms(realm, request).setUser(user).forwardToAccount();
|
||||||
if (user != null) {
|
} else {
|
||||||
return Flows.forms(realm, request).setUser(user).forwardToAccount();
|
return Response.status(Status.FORBIDDEN).build();
|
||||||
} else {
|
}
|
||||||
return Response.status(Status.FORBIDDEN).build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("social")
|
@Path("social")
|
||||||
@GET
|
@GET
|
||||||
public Response socialPage() {
|
public Response socialPage() {
|
||||||
return new Transaction<Response>() {
|
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
||||||
protected Response callImpl() {
|
if (user != null) {
|
||||||
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
return Flows.forms(realm, request).setUser(user).forwardToSocial();
|
||||||
if (user != null) {
|
} else {
|
||||||
return Flows.forms(realm, request).setUser(user).forwardToSocial();
|
return Response.status(Status.FORBIDDEN).build();
|
||||||
} else {
|
}
|
||||||
return Response.status(Status.FORBIDDEN).build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("totp")
|
@Path("totp")
|
||||||
@GET
|
@GET
|
||||||
public Response totpPage() {
|
public Response totpPage() {
|
||||||
return new Transaction<Response>() {
|
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
||||||
protected Response callImpl() {
|
if (user != null) {
|
||||||
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
return Flows.forms(realm, request).setUser(user).forwardToTotp();
|
||||||
if (user != null) {
|
} else {
|
||||||
return Flows.forms(realm, request).setUser(user).forwardToTotp();
|
return Response.status(Status.FORBIDDEN).build();
|
||||||
} else {
|
}
|
||||||
return Response.status(Status.FORBIDDEN).build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("password")
|
@Path("password")
|
||||||
@GET
|
@GET
|
||||||
public Response passwordPage() {
|
public Response passwordPage() {
|
||||||
return new Transaction<Response>() {
|
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
||||||
protected Response callImpl() {
|
if (user != null) {
|
||||||
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
return Flows.forms(realm, request).setUser(user).forwardToPassword();
|
||||||
if (user != null) {
|
} else {
|
||||||
return Flows.forms(realm, request).setUser(user).forwardToPassword();
|
return Response.status(Status.FORBIDDEN).build();
|
||||||
} else {
|
}
|
||||||
return Response.status(Status.FORBIDDEN).build();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package org.keycloak.services.resources;
|
package org.keycloak.services.resources;
|
||||||
|
|
||||||
import org.keycloak.SkeletonKeyContextResolver;
|
import org.keycloak.SkeletonKeyContextResolver;
|
||||||
import org.keycloak.services.filters.KeycloakSessionCleanupFilter;
|
|
||||||
import org.keycloak.services.managers.TokenManager;
|
import org.keycloak.services.managers.TokenManager;
|
||||||
import org.keycloak.services.models.KeycloakSessionFactory;
|
import org.keycloak.services.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.services.models.picketlink.PicketlinkKeycloakSession;
|
import org.keycloak.services.models.picketlink.PicketlinkKeycloakSession;
|
||||||
|
@ -13,25 +12,15 @@ import org.picketlink.idm.PartitionManager;
|
||||||
import org.picketlink.idm.config.IdentityConfigurationBuilder;
|
import org.picketlink.idm.config.IdentityConfigurationBuilder;
|
||||||
import org.picketlink.idm.internal.DefaultPartitionManager;
|
import org.picketlink.idm.internal.DefaultPartitionManager;
|
||||||
import org.picketlink.idm.jpa.internal.JPAContextInitializer;
|
import org.picketlink.idm.jpa.internal.JPAContextInitializer;
|
||||||
import org.picketlink.idm.jpa.model.sample.simple.AccountTypeEntity;
|
import org.picketlink.idm.jpa.model.sample.simple.*;
|
||||||
import org.picketlink.idm.jpa.model.sample.simple.AttributeTypeEntity;
|
|
||||||
import org.picketlink.idm.jpa.model.sample.simple.AttributedTypeEntity;
|
|
||||||
import org.picketlink.idm.jpa.model.sample.simple.DigestCredentialTypeEntity;
|
|
||||||
import org.picketlink.idm.jpa.model.sample.simple.GroupTypeEntity;
|
|
||||||
import org.picketlink.idm.jpa.model.sample.simple.IdentityTypeEntity;
|
|
||||||
import org.picketlink.idm.jpa.model.sample.simple.OTPCredentialTypeEntity;
|
|
||||||
import org.picketlink.idm.jpa.model.sample.simple.PartitionTypeEntity;
|
|
||||||
import org.picketlink.idm.jpa.model.sample.simple.PasswordCredentialTypeEntity;
|
|
||||||
import org.picketlink.idm.jpa.model.sample.simple.RelationshipIdentityTypeEntity;
|
|
||||||
import org.picketlink.idm.jpa.model.sample.simple.RelationshipTypeEntity;
|
|
||||||
import org.picketlink.idm.jpa.model.sample.simple.RoleTypeEntity;
|
|
||||||
import org.picketlink.idm.jpa.model.sample.simple.X509CredentialTypeEntity;
|
|
||||||
|
|
||||||
import javax.annotation.PreDestroy;
|
import javax.annotation.PreDestroy;
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.EntityManagerFactory;
|
import javax.persistence.EntityManagerFactory;
|
||||||
import javax.persistence.Persistence;
|
import javax.persistence.Persistence;
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
import javax.ws.rs.core.Application;
|
import javax.ws.rs.core.Application;
|
||||||
|
import javax.ws.rs.core.Context;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
@ -45,10 +34,11 @@ public class KeycloakApplication extends Application {
|
||||||
|
|
||||||
protected KeycloakSessionFactory factory;
|
protected KeycloakSessionFactory factory;
|
||||||
|
|
||||||
public KeycloakApplication() {
|
public KeycloakApplication(@Context ServletContext context) {
|
||||||
KeycloakSessionFactory f = createSessionFactory();
|
KeycloakSessionFactory f = createSessionFactory();
|
||||||
this.factory = f;
|
this.factory = f;
|
||||||
classes.add(KeycloakSessionCleanupFilter.class);
|
context.setAttribute(KeycloakSessionFactory.class.getName(), factory);
|
||||||
|
//classes.add(KeycloakSessionCleanupFilter.class);
|
||||||
|
|
||||||
TokenManager tokenManager = new TokenManager();
|
TokenManager tokenManager = new TokenManager();
|
||||||
|
|
||||||
|
@ -56,6 +46,7 @@ public class KeycloakApplication extends Application {
|
||||||
singletons.add(new SocialResource(tokenManager, new SocialRequestManager()));
|
singletons.add(new SocialResource(tokenManager, new SocialRequestManager()));
|
||||||
classes.add(SkeletonKeyContextResolver.class);
|
classes.add(SkeletonKeyContextResolver.class);
|
||||||
classes.add(SaasService.class);
|
classes.add(SaasService.class);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected KeycloakSessionFactory createSessionFactory() {
|
protected KeycloakSessionFactory createSessionFactory() {
|
||||||
|
|
|
@ -3,7 +3,6 @@ package org.keycloak.services.resources;
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
import org.jboss.resteasy.logging.Logger;
|
import org.jboss.resteasy.logging.Logger;
|
||||||
import org.keycloak.representations.idm.PublishedRealmRepresentation;
|
import org.keycloak.representations.idm.PublishedRealmRepresentation;
|
||||||
import org.keycloak.services.models.KeycloakSession;
|
|
||||||
import org.keycloak.services.models.RealmModel;
|
import org.keycloak.services.models.RealmModel;
|
||||||
|
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.GET;
|
||||||
|
@ -41,11 +40,7 @@ public class PublicRealmResource {
|
||||||
@NoCache
|
@NoCache
|
||||||
@Produces("application/json")
|
@Produces("application/json")
|
||||||
public PublishedRealmRepresentation getRealm(@PathParam("realm") String id) {
|
public PublishedRealmRepresentation getRealm(@PathParam("realm") String id) {
|
||||||
return new Transaction<PublishedRealmRepresentation>() {
|
return realmRep(realm, uriInfo);
|
||||||
protected PublishedRealmRepresentation callImpl() {
|
|
||||||
return realmRep(realm, uriInfo);
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
|
@ -53,26 +48,22 @@ public class PublicRealmResource {
|
||||||
@Path("html")
|
@Path("html")
|
||||||
@Produces("text/html")
|
@Produces("text/html")
|
||||||
public String getRealmHtml(@PathParam("realm") String id) {
|
public String getRealmHtml(@PathParam("realm") String id) {
|
||||||
return new Transaction<String>() {
|
StringBuffer html = new StringBuffer();
|
||||||
protected String callImpl() {
|
|
||||||
StringBuffer html = new StringBuffer();
|
|
||||||
|
|
||||||
String authUri = TokenService.loginPageUrl(uriInfo).build(realm.getId()).toString();
|
String authUri = TokenService.loginPageUrl(uriInfo).build(realm.getId()).toString();
|
||||||
String codeUri = TokenService.accessCodeToTokenUrl(uriInfo).build(realm.getId()).toString();
|
String codeUri = TokenService.accessCodeToTokenUrl(uriInfo).build(realm.getId()).toString();
|
||||||
String grantUrl = TokenService.grantAccessTokenUrl(uriInfo).build(realm.getId()).toString();
|
String grantUrl = TokenService.grantAccessTokenUrl(uriInfo).build(realm.getId()).toString();
|
||||||
String idGrantUrl = TokenService.grantIdentityTokenUrl(uriInfo).build(realm.getId()).toString();
|
String idGrantUrl = TokenService.grantIdentityTokenUrl(uriInfo).build(realm.getId()).toString();
|
||||||
|
|
||||||
html.append("<html><body><h1>Realm: ").append(realm.getName()).append("</h1>");
|
html.append("<html><body><h1>Realm: ").append(realm.getName()).append("</h1>");
|
||||||
html.append("<p>auth: ").append(authUri).append("</p>");
|
html.append("<p>auth: ").append(authUri).append("</p>");
|
||||||
html.append("<p>code: ").append(codeUri).append("</p>");
|
html.append("<p>code: ").append(codeUri).append("</p>");
|
||||||
html.append("<p>grant: ").append(grantUrl).append("</p>");
|
html.append("<p>grant: ").append(grantUrl).append("</p>");
|
||||||
html.append("<p>identity grant: ").append(idGrantUrl).append("</p>");
|
html.append("<p>identity grant: ").append(idGrantUrl).append("</p>");
|
||||||
html.append("<p>public key: ").append(realm.getPublicKeyPem()).append("</p>");
|
html.append("<p>public key: ").append(realm.getPublicKeyPem()).append("</p>");
|
||||||
html.append("</body></html>");
|
html.append("</body></html>");
|
||||||
|
|
||||||
return html.toString();
|
return html.toString();
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,17 @@
|
||||||
package org.keycloak.services.resources;
|
package org.keycloak.services.resources;
|
||||||
|
|
||||||
import org.jboss.resteasy.logging.Logger;
|
import org.jboss.resteasy.logging.Logger;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
|
||||||
import org.keycloak.services.managers.AuthenticationManager;
|
|
||||||
import org.keycloak.services.managers.RealmManager;
|
import org.keycloak.services.managers.RealmManager;
|
||||||
import org.keycloak.services.managers.TokenManager;
|
import org.keycloak.services.managers.TokenManager;
|
||||||
|
import org.keycloak.services.models.KeycloakSession;
|
||||||
import org.keycloak.services.models.RealmModel;
|
import org.keycloak.services.models.RealmModel;
|
||||||
import org.keycloak.services.models.RoleModel;
|
|
||||||
import org.keycloak.services.models.UserModel;
|
|
||||||
import org.keycloak.social.SocialRequestManager;
|
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
|
||||||
import javax.ws.rs.NotAuthorizedException;
|
|
||||||
import javax.ws.rs.NotFoundException;
|
import javax.ws.rs.NotFoundException;
|
||||||
import javax.ws.rs.POST;
|
|
||||||
import javax.ws.rs.Path;
|
import javax.ws.rs.Path;
|
||||||
import javax.ws.rs.PathParam;
|
import javax.ws.rs.PathParam;
|
||||||
import javax.ws.rs.container.ResourceContext;
|
import javax.ws.rs.container.ResourceContext;
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
import javax.ws.rs.core.HttpHeaders;
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import javax.ws.rs.core.UriBuilder;
|
import javax.ws.rs.core.UriBuilder;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
|
||||||
|
@ -39,7 +30,10 @@ public class RealmsResource {
|
||||||
protected HttpHeaders headers;
|
protected HttpHeaders headers;
|
||||||
|
|
||||||
@Context
|
@Context
|
||||||
ResourceContext resourceContext;
|
protected ResourceContext resourceContext;
|
||||||
|
|
||||||
|
@Context
|
||||||
|
protected KeycloakSession session;
|
||||||
|
|
||||||
protected TokenManager tokenManager;
|
protected TokenManager tokenManager;
|
||||||
|
|
||||||
|
@ -53,57 +47,41 @@ public class RealmsResource {
|
||||||
|
|
||||||
@Path("{realm}/tokens")
|
@Path("{realm}/tokens")
|
||||||
public TokenService getTokenService(final @PathParam("realm") String id) {
|
public TokenService getTokenService(final @PathParam("realm") String id) {
|
||||||
return new Transaction<TokenService>(false) {
|
RealmManager realmManager = new RealmManager(session);
|
||||||
@Override
|
RealmModel realm = realmManager.getRealm(id);
|
||||||
protected TokenService callImpl() {
|
if (realm == null) {
|
||||||
RealmManager realmManager = new RealmManager(session);
|
logger.debug("realm not found");
|
||||||
RealmModel realm = realmManager.getRealm(id);
|
throw new NotFoundException();
|
||||||
if (realm == null) {
|
}
|
||||||
logger.debug("realm not found");
|
TokenService tokenService = new TokenService(realm, tokenManager);
|
||||||
throw new NotFoundException();
|
resourceContext.initResource(tokenService);
|
||||||
}
|
return tokenService;
|
||||||
TokenService tokenService = new TokenService(realm, tokenManager);
|
|
||||||
resourceContext.initResource(tokenService);
|
|
||||||
return tokenService;
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("{realm}/account")
|
@Path("{realm}/account")
|
||||||
public AccountService getAccountService(final @PathParam("realm") String id) {
|
public AccountService getAccountService(final @PathParam("realm") String id) {
|
||||||
return new Transaction<AccountService>(false) {
|
RealmManager realmManager = new RealmManager(session);
|
||||||
@Override
|
RealmModel realm = realmManager.getRealm(id);
|
||||||
protected AccountService callImpl() {
|
if (realm == null) {
|
||||||
RealmManager realmManager = new RealmManager(session);
|
logger.debug("realm not found");
|
||||||
RealmModel realm = realmManager.getRealm(id);
|
throw new NotFoundException();
|
||||||
if (realm == null) {
|
}
|
||||||
logger.debug("realm not found");
|
AccountService accountService = new AccountService(realm);
|
||||||
throw new NotFoundException();
|
resourceContext.initResource(accountService);
|
||||||
}
|
return accountService;
|
||||||
AccountService accountService = new AccountService(realm);
|
|
||||||
resourceContext.initResource(accountService);
|
|
||||||
return accountService;
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("{realm}")
|
@Path("{realm}")
|
||||||
public PublicRealmResource getRealmResource(final @PathParam("realm") String id) {
|
public PublicRealmResource getRealmResource(final @PathParam("realm") String id) {
|
||||||
return new Transaction<PublicRealmResource>(false) {
|
RealmManager realmManager = new RealmManager(session);
|
||||||
@Override
|
RealmModel realm = realmManager.getRealm(id);
|
||||||
protected PublicRealmResource callImpl() {
|
if (realm == null) {
|
||||||
RealmManager realmManager = new RealmManager(session);
|
logger.debug("realm not found");
|
||||||
RealmModel realm = realmManager.getRealm(id);
|
throw new NotFoundException();
|
||||||
if (realm == null) {
|
}
|
||||||
logger.debug("realm not found");
|
PublicRealmResource realmResource = new PublicRealmResource(realm);
|
||||||
throw new NotFoundException();
|
resourceContext.initResource(realmResource);
|
||||||
}
|
return realmResource;
|
||||||
PublicRealmResource realmResource = new PublicRealmResource(realm);
|
|
||||||
resourceContext.initResource(realmResource);
|
|
||||||
return realmResource;
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -10,18 +10,14 @@ import org.keycloak.representations.idm.UserRepresentation;
|
||||||
import org.keycloak.services.managers.AuthenticationManager;
|
import org.keycloak.services.managers.AuthenticationManager;
|
||||||
import org.keycloak.services.managers.RealmManager;
|
import org.keycloak.services.managers.RealmManager;
|
||||||
import org.keycloak.services.messages.Messages;
|
import org.keycloak.services.messages.Messages;
|
||||||
import org.keycloak.services.models.RealmModel;
|
import org.keycloak.services.models.*;
|
||||||
import org.keycloak.services.models.RequiredCredentialModel;
|
|
||||||
import org.keycloak.services.models.RoleModel;
|
|
||||||
import org.keycloak.services.models.UserCredentialModel;
|
|
||||||
import org.keycloak.services.models.UserModel;
|
|
||||||
import org.keycloak.services.resources.admin.RealmsAdminResource;
|
import org.keycloak.services.resources.admin.RealmsAdminResource;
|
||||||
import org.keycloak.services.resources.flows.Flows;
|
import org.keycloak.services.resources.flows.Flows;
|
||||||
import org.keycloak.services.validation.Validation;
|
import org.keycloak.services.validation.Validation;
|
||||||
|
|
||||||
import javax.ws.rs.*;
|
import javax.ws.rs.*;
|
||||||
|
import javax.ws.rs.container.ResourceContext;
|
||||||
import javax.ws.rs.core.*;
|
import javax.ws.rs.core.*;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -44,7 +40,13 @@ public class SaasService {
|
||||||
protected HttpRequest request;
|
protected HttpRequest request;
|
||||||
|
|
||||||
@Context
|
@Context
|
||||||
HttpResponse response;
|
protected HttpResponse response;
|
||||||
|
|
||||||
|
@Context
|
||||||
|
protected KeycloakSession session;
|
||||||
|
|
||||||
|
@Context
|
||||||
|
protected ResourceContext resourceContext;
|
||||||
|
|
||||||
protected String adminPath = "/saas/admin/index.html";
|
protected String adminPath = "/saas/admin/index.html";
|
||||||
protected AuthenticationManager authManager = new AuthenticationManager();
|
protected AuthenticationManager authManager = new AuthenticationManager();
|
||||||
|
@ -82,22 +84,17 @@ public class SaasService {
|
||||||
@GET
|
@GET
|
||||||
@NoCache
|
@NoCache
|
||||||
public Response keepalive(final @Context HttpHeaders headers) {
|
public Response keepalive(final @Context HttpHeaders headers) {
|
||||||
logger.info("keepalive");
|
logger.debug("keepalive");
|
||||||
return new Transaction<Response>() {
|
RealmManager realmManager = new RealmManager(session);
|
||||||
@Override
|
RealmModel realm = realmManager.defaultRealm();
|
||||||
public Response callImpl() {
|
if (realm == null)
|
||||||
RealmManager realmManager = new RealmManager(session);
|
throw new NotFoundException();
|
||||||
RealmModel realm = realmManager.defaultRealm();
|
UserModel user = authManager.authenticateSaasIdentityCookie(realm, uriInfo, headers);
|
||||||
if (realm == null)
|
if (user == null) {
|
||||||
throw new NotFoundException();
|
return Response.status(401).build();
|
||||||
UserModel user = authManager.authenticateSaasIdentityCookie(realm, uriInfo, headers);
|
}
|
||||||
if (user == null) {
|
NewCookie refreshCookie = authManager.createSaasIdentityCookie(realm, user, uriInfo);
|
||||||
return Response.status(401).build();
|
return Response.noContent().cookie(refreshCookie).build();
|
||||||
}
|
|
||||||
NewCookie refreshCookie = authManager.createSaasIdentityCookie(realm, user, uriInfo);
|
|
||||||
return Response.noContent().cookie(refreshCookie).build();
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("whoami")
|
@Path("whoami")
|
||||||
|
@ -105,20 +102,15 @@ public class SaasService {
|
||||||
@Produces("application/json")
|
@Produces("application/json")
|
||||||
@NoCache
|
@NoCache
|
||||||
public Response whoAmI(final @Context HttpHeaders headers) {
|
public Response whoAmI(final @Context HttpHeaders headers) {
|
||||||
return new Transaction<Response>() {
|
RealmManager realmManager = new RealmManager(session);
|
||||||
@Override
|
RealmModel realm = realmManager.defaultRealm();
|
||||||
public Response callImpl() {
|
if (realm == null)
|
||||||
RealmManager realmManager = new RealmManager(session);
|
throw new NotFoundException();
|
||||||
RealmModel realm = realmManager.defaultRealm();
|
UserModel user = authManager.authenticateSaasIdentityCookie(realm, uriInfo, headers);
|
||||||
if (realm == null)
|
if (user == null) {
|
||||||
throw new NotFoundException();
|
return Response.status(401).build();
|
||||||
UserModel user = authManager.authenticateSaasIdentityCookie(realm, uriInfo, headers);
|
}
|
||||||
if (user == null) {
|
return Response.ok(new WhoAmI(user.getLoginName(), user.getFirstName() + " " + user.getLastName())).build();
|
||||||
return Response.status(401).build();
|
|
||||||
}
|
|
||||||
return Response.ok(new WhoAmI(user.getLoginName(), user.getFirstName() + " " + user.getLastName())).build();
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("isLoggedIn.js")
|
@Path("isLoggedIn.js")
|
||||||
|
@ -126,24 +118,19 @@ public class SaasService {
|
||||||
@Produces("application/javascript")
|
@Produces("application/javascript")
|
||||||
@NoCache
|
@NoCache
|
||||||
public String isLoggedIn(final @Context HttpHeaders headers) {
|
public String isLoggedIn(final @Context HttpHeaders headers) {
|
||||||
return new Transaction<String>() {
|
logger.debug("WHOAMI Javascript start.");
|
||||||
@Override
|
RealmManager realmManager = new RealmManager(session);
|
||||||
public String callImpl() {
|
RealmModel realm = realmManager.defaultRealm();
|
||||||
logger.info("WHOAMI Javascript start.");
|
if (realm == null) {
|
||||||
RealmManager realmManager = new RealmManager(session);
|
return "var keycloakCookieLoggedIn = false;";
|
||||||
RealmModel realm = realmManager.defaultRealm();
|
|
||||||
if (realm == null) {
|
|
||||||
return "var keycloakCookieLoggedIn = false;";
|
|
||||||
|
|
||||||
}
|
}
|
||||||
UserModel user = authManager.authenticateSaasIdentityCookie(realm, uriInfo, headers);
|
UserModel user = authManager.authenticateSaasIdentityCookie(realm, uriInfo, headers);
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
return "var keycloakCookieLoggedIn = false;";
|
return "var keycloakCookieLoggedIn = false;";
|
||||||
}
|
}
|
||||||
logger.info("WHOAMI: " + user.getLoginName());
|
logger.debug("WHOAMI: " + user.getLoginName());
|
||||||
return "var keycloakCookieLoggedIn = true;";
|
return "var keycloakCookieLoggedIn = true;";
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UriBuilder contextRoot(UriInfo uriInfo) {
|
public static UriBuilder contextRoot(UriInfo uriInfo) {
|
||||||
|
@ -156,86 +143,63 @@ public class SaasService {
|
||||||
|
|
||||||
@Path("admin/realms")
|
@Path("admin/realms")
|
||||||
public RealmsAdminResource getRealmsAdmin(@Context final HttpHeaders headers) {
|
public RealmsAdminResource getRealmsAdmin(@Context final HttpHeaders headers) {
|
||||||
return new Transaction<RealmsAdminResource>(false) {
|
RealmManager realmManager = new RealmManager(session);
|
||||||
@Override
|
RealmModel saasRealm = realmManager.defaultRealm();
|
||||||
protected RealmsAdminResource callImpl() {
|
if (saasRealm == null)
|
||||||
RealmManager realmManager = new RealmManager(session);
|
throw new NotFoundException();
|
||||||
RealmModel saasRealm = realmManager.defaultRealm();
|
UserModel admin = authManager.authenticateSaasIdentity(saasRealm, uriInfo, headers);
|
||||||
if (saasRealm == null)
|
if (admin == null) {
|
||||||
throw new NotFoundException();
|
throw new NotAuthorizedException("Bearer");
|
||||||
UserModel admin = authManager.authenticateSaasIdentity(saasRealm, uriInfo, headers);
|
}
|
||||||
if (admin == null) {
|
RoleModel creatorRole = saasRealm.getRole(SaasService.REALM_CREATOR_ROLE);
|
||||||
throw new NotAuthorizedException("Bearer");
|
if (!saasRealm.hasRole(admin, creatorRole)) {
|
||||||
}
|
logger.warn("not a Realm creator");
|
||||||
RoleModel creatorRole = saasRealm.getRole(SaasService.REALM_CREATOR_ROLE);
|
throw new NotAuthorizedException("Bearer");
|
||||||
if (!saasRealm.hasRole(admin, creatorRole)) {
|
}
|
||||||
logger.warn("not a Realm creator");
|
RealmsAdminResource adminResource = new RealmsAdminResource(admin);
|
||||||
throw new NotAuthorizedException("Bearer");
|
resourceContext.initResource(adminResource);
|
||||||
}
|
return adminResource;
|
||||||
return new RealmsAdminResource(admin);
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("login")
|
@Path("login")
|
||||||
@GET
|
@GET
|
||||||
@NoCache
|
@NoCache
|
||||||
public void loginPage() {
|
public void loginPage() {
|
||||||
new Transaction() {
|
RealmManager realmManager = new RealmManager(session);
|
||||||
@Override
|
RealmModel realm = realmManager.defaultRealm();
|
||||||
protected void runImpl() {
|
authManager.expireSaasIdentityCookie(uriInfo);
|
||||||
RealmManager realmManager = new RealmManager(session);
|
|
||||||
RealmModel realm = realmManager.defaultRealm();
|
|
||||||
authManager.expireSaasIdentityCookie(uriInfo);
|
|
||||||
|
|
||||||
Flows.forms(realm, request).forwardToLogin();
|
Flows.forms(realm, request).forwardToLogin();
|
||||||
}
|
|
||||||
}.run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("registrations")
|
@Path("registrations")
|
||||||
@GET
|
@GET
|
||||||
@NoCache
|
@NoCache
|
||||||
public void registerPage() {
|
public void registerPage() {
|
||||||
new Transaction() {
|
RealmManager realmManager = new RealmManager(session);
|
||||||
@Override
|
RealmModel realm = realmManager.defaultRealm();
|
||||||
protected void runImpl() {
|
authManager.expireSaasIdentityCookie(uriInfo);
|
||||||
RealmManager realmManager = new RealmManager(session);
|
|
||||||
RealmModel realm = realmManager.defaultRealm();
|
|
||||||
authManager.expireSaasIdentityCookie(uriInfo);
|
|
||||||
|
|
||||||
Flows.forms(realm, request).forwardToRegistration();
|
Flows.forms(realm, request).forwardToRegistration();
|
||||||
}
|
|
||||||
}.run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("logout")
|
@Path("logout")
|
||||||
@GET
|
@GET
|
||||||
@NoCache
|
@NoCache
|
||||||
public void logout() {
|
public void logout() {
|
||||||
new Transaction() {
|
RealmManager realmManager = new RealmManager(session);
|
||||||
@Override
|
RealmModel realm = realmManager.defaultRealm();
|
||||||
protected void runImpl() {
|
authManager.expireSaasIdentityCookie(uriInfo);
|
||||||
RealmManager realmManager = new RealmManager(session);
|
|
||||||
RealmModel realm = realmManager.defaultRealm();
|
|
||||||
authManager.expireSaasIdentityCookie(uriInfo);
|
|
||||||
|
|
||||||
Flows.forms(realm, request).forwardToLogin();
|
Flows.forms(realm, request).forwardToLogin();
|
||||||
}
|
|
||||||
}.run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("logout-cookie")
|
@Path("logout-cookie")
|
||||||
@GET
|
@GET
|
||||||
@NoCache
|
@NoCache
|
||||||
public void logoutCookie() {
|
public void logoutCookie() {
|
||||||
logger.info("*** logoutCookie");
|
logger.debug("*** logoutCookie");
|
||||||
new Transaction() {
|
authManager.expireSaasIdentityCookie(uriInfo);
|
||||||
@Override
|
|
||||||
protected void runImpl() {
|
|
||||||
authManager.expireSaasIdentityCookie(uriInfo);
|
|
||||||
}
|
|
||||||
}.run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("login")
|
@Path("login")
|
||||||
|
@ -243,132 +207,117 @@ public class SaasService {
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
public Response processLogin(final MultivaluedMap<String, String> formData) {
|
public Response processLogin(final MultivaluedMap<String, String> formData) {
|
||||||
logger.info("processLogin start");
|
logger.info("processLogin start");
|
||||||
return new Transaction<Response>() {
|
RealmManager realmManager = new RealmManager(session);
|
||||||
@Override
|
RealmModel realm = realmManager.defaultRealm();
|
||||||
protected Response callImpl() {
|
if (realm == null)
|
||||||
RealmManager realmManager = new RealmManager(session);
|
throw new NotFoundException();
|
||||||
RealmModel realm = realmManager.defaultRealm();
|
|
||||||
if (realm == null)
|
|
||||||
throw new NotFoundException();
|
|
||||||
|
|
||||||
if (!realm.isEnabled()) {
|
if (!realm.isEnabled()) {
|
||||||
throw new NotImplementedYetException();
|
throw new NotImplementedYetException();
|
||||||
}
|
}
|
||||||
String username = formData.getFirst("username");
|
String username = formData.getFirst("username");
|
||||||
UserModel user = realm.getUser(username);
|
UserModel user = realm.getUser(username);
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
logger.info("Not Authenticated! Incorrect user name");
|
logger.info("Not Authenticated! Incorrect user name");
|
||||||
|
|
||||||
return Flows.forms(realm, request).setError(Messages.INVALID_USER).setFormData(formData)
|
return Flows.forms(realm, request).setError(Messages.INVALID_USER).setFormData(formData)
|
||||||
.forwardToLogin();
|
.forwardToLogin();
|
||||||
}
|
}
|
||||||
if (!user.isEnabled()) {
|
if (!user.isEnabled()) {
|
||||||
logger.info("Account is disabled, contact admin.");
|
logger.info("Account is disabled, contact admin.");
|
||||||
|
|
||||||
return Flows.forms(realm, request).setError(Messages.ACCOUNT_DISABLED)
|
return Flows.forms(realm, request).setError(Messages.ACCOUNT_DISABLED)
|
||||||
.setFormData(formData).forwardToLogin();
|
.setFormData(formData).forwardToLogin();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean authenticated = authManager.authenticateForm(realm, user, formData);
|
boolean authenticated = authManager.authenticateForm(realm, user, formData);
|
||||||
if (!authenticated) {
|
if (!authenticated) {
|
||||||
logger.info("Not Authenticated! Invalid credentials");
|
logger.info("Not Authenticated! Invalid credentials");
|
||||||
|
|
||||||
return Flows.forms(realm, request).setError(Messages.INVALID_PASSWORD).setFormData(formData)
|
return Flows.forms(realm, request).setError(Messages.INVALID_PASSWORD).setFormData(formData)
|
||||||
.forwardToLogin();
|
.forwardToLogin();
|
||||||
}
|
}
|
||||||
|
|
||||||
NewCookie cookie = authManager.createSaasIdentityCookie(realm, user, uriInfo);
|
NewCookie cookie = authManager.createSaasIdentityCookie(realm, user, uriInfo);
|
||||||
return Response.status(302).cookie(cookie).location(contextRoot(uriInfo).path(adminPath).build()).build();
|
return Response.status(302).cookie(cookie).location(contextRoot(uriInfo).path(adminPath).build()).build();
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("registrations")
|
@Path("registrations")
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public Response register(final UserRepresentation newUser) {
|
public Response register(final UserRepresentation newUser) {
|
||||||
return new Transaction<Response>() {
|
RealmManager realmManager = new RealmManager(session);
|
||||||
@Override
|
RealmModel defaultRealm = realmManager.defaultRealm();
|
||||||
protected Response callImpl() {
|
UserModel user = registerMe(defaultRealm, newUser);
|
||||||
RealmManager realmManager = new RealmManager(session);
|
if (user == null) {
|
||||||
RealmModel defaultRealm = realmManager.defaultRealm();
|
return Response.status(400).type("text/plain").entity("Already exists").build();
|
||||||
UserModel user = registerMe(defaultRealm, newUser);
|
}
|
||||||
if (user == null) {
|
URI uri = uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(user.getLoginName()).build();
|
||||||
return Response.status(400).type("text/plain").entity("Already exists").build();
|
return Response.created(uri).build();
|
||||||
}
|
|
||||||
URI uri = uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(user.getLoginName()).build();
|
|
||||||
return Response.created(uri).build();
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("registrations")
|
@Path("registrations")
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
public Response processRegister(final MultivaluedMap<String, String> formData) {
|
public Response processRegister(final MultivaluedMap<String, String> formData) {
|
||||||
return new Transaction<Response>() {
|
RealmManager realmManager = new RealmManager(session);
|
||||||
@Override
|
RealmModel defaultRealm = realmManager.defaultRealm();
|
||||||
protected Response callImpl() {
|
|
||||||
RealmManager realmManager = new RealmManager(session);
|
|
||||||
RealmModel defaultRealm = realmManager.defaultRealm();
|
|
||||||
|
|
||||||
List<String> requiredCredentialTypes = new LinkedList<String>();
|
List<String> requiredCredentialTypes = new LinkedList<String>();
|
||||||
for (RequiredCredentialModel m : defaultRealm.getRequiredCredentials()) {
|
for (RequiredCredentialModel m : defaultRealm.getRequiredCredentials()) {
|
||||||
requiredCredentialTypes.add(m.getType());
|
requiredCredentialTypes.add(m.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
String error = Validation.validateRegistrationForm(formData, requiredCredentialTypes);
|
String error = Validation.validateRegistrationForm(formData, requiredCredentialTypes);
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
return Flows.forms(defaultRealm, request).setError(error).setFormData(formData)
|
return Flows.forms(defaultRealm, request).setError(error).setFormData(formData)
|
||||||
.forwardToRegistration();
|
.forwardToRegistration();
|
||||||
}
|
}
|
||||||
|
|
||||||
UserRepresentation newUser = new UserRepresentation();
|
UserRepresentation newUser = new UserRepresentation();
|
||||||
newUser.setUsername(formData.getFirst("username"));
|
newUser.setUsername(formData.getFirst("username"));
|
||||||
newUser.setEmail(formData.getFirst("email"));
|
newUser.setEmail(formData.getFirst("email"));
|
||||||
|
|
||||||
String fullname = formData.getFirst("name");
|
String fullname = formData.getFirst("name");
|
||||||
if (fullname != null) {
|
if (fullname != null) {
|
||||||
StringTokenizer tokenizer = new StringTokenizer(fullname, " ");
|
StringTokenizer tokenizer = new StringTokenizer(fullname, " ");
|
||||||
StringBuffer first = null;
|
StringBuffer first = null;
|
||||||
String last = "";
|
String last = "";
|
||||||
while (tokenizer.hasMoreTokens()) {
|
while (tokenizer.hasMoreTokens()) {
|
||||||
String token = tokenizer.nextToken();
|
String token = tokenizer.nextToken();
|
||||||
if (tokenizer.hasMoreTokens()) {
|
if (tokenizer.hasMoreTokens()) {
|
||||||
if (first == null) {
|
if (first == null) {
|
||||||
first = new StringBuffer();
|
|
||||||
} else {
|
|
||||||
first.append(" ");
|
|
||||||
}
|
|
||||||
first.append(token);
|
|
||||||
} else {
|
|
||||||
last = token;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (first == null)
|
|
||||||
first = new StringBuffer();
|
first = new StringBuffer();
|
||||||
newUser.setFirstName(first.toString());
|
} else {
|
||||||
newUser.setLastName(last);
|
first.append(" ");
|
||||||
|
}
|
||||||
|
first.append(token);
|
||||||
|
} else {
|
||||||
|
last = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requiredCredentialTypes.contains(CredentialRepresentation.PASSWORD)) {
|
|
||||||
newUser.credential(CredentialRepresentation.PASSWORD, formData.getFirst("password"));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (requiredCredentialTypes.contains(CredentialRepresentation.TOTP)) {
|
|
||||||
newUser.credential(CredentialRepresentation.TOTP, formData.getFirst("password"));
|
|
||||||
}
|
|
||||||
|
|
||||||
UserModel user = registerMe(defaultRealm, newUser);
|
|
||||||
if (user == null) {
|
|
||||||
return Flows.forms(defaultRealm, request).setError(Messages.USERNAME_EXISTS)
|
|
||||||
.setFormData(formData).forwardToRegistration();
|
|
||||||
|
|
||||||
}
|
|
||||||
NewCookie cookie = authManager.createSaasIdentityCookie(defaultRealm, user, uriInfo);
|
|
||||||
return Response.status(302).location(contextRoot(uriInfo).path(adminPath).build()).cookie(cookie).build();
|
|
||||||
}
|
}
|
||||||
}.call();
|
if (first == null)
|
||||||
|
first = new StringBuffer();
|
||||||
|
newUser.setFirstName(first.toString());
|
||||||
|
newUser.setLastName(last);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requiredCredentialTypes.contains(CredentialRepresentation.PASSWORD)) {
|
||||||
|
newUser.credential(CredentialRepresentation.PASSWORD, formData.getFirst("password"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requiredCredentialTypes.contains(CredentialRepresentation.TOTP)) {
|
||||||
|
newUser.credential(CredentialRepresentation.TOTP, formData.getFirst("password"));
|
||||||
|
}
|
||||||
|
|
||||||
|
UserModel user = registerMe(defaultRealm, newUser);
|
||||||
|
if (user == null) {
|
||||||
|
return Flows.forms(defaultRealm, request).setError(Messages.USERNAME_EXISTS)
|
||||||
|
.setFormData(formData).forwardToRegistration();
|
||||||
|
|
||||||
|
}
|
||||||
|
NewCookie cookie = authManager.createSaasIdentityCookie(defaultRealm, user, uriInfo);
|
||||||
|
return Response.status(302).location(contextRoot(uriInfo).path(adminPath).build()).cookie(cookie).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected UserModel registerMe(RealmModel defaultRealm, UserRepresentation newUser) {
|
protected UserModel registerMe(RealmModel defaultRealm, UserRepresentation newUser) {
|
||||||
|
|
281
services/src/main/java/org/keycloak/services/resources/SocialResource.java
Normal file → Executable file
281
services/src/main/java/org/keycloak/services/resources/SocialResource.java
Normal file → Executable file
|
@ -56,10 +56,7 @@ import org.keycloak.services.managers.AuthenticationManager;
|
||||||
import org.keycloak.services.managers.RealmManager;
|
import org.keycloak.services.managers.RealmManager;
|
||||||
import org.keycloak.services.managers.TokenManager;
|
import org.keycloak.services.managers.TokenManager;
|
||||||
import org.keycloak.services.messages.Messages;
|
import org.keycloak.services.messages.Messages;
|
||||||
import org.keycloak.services.models.RealmModel;
|
import org.keycloak.services.models.*;
|
||||||
import org.keycloak.services.models.RoleModel;
|
|
||||||
import org.keycloak.services.models.SocialLinkModel;
|
|
||||||
import org.keycloak.services.models.UserModel;
|
|
||||||
import org.keycloak.services.resources.flows.Flows;
|
import org.keycloak.services.resources.flows.Flows;
|
||||||
import org.keycloak.services.resources.flows.OAuthFlows;
|
import org.keycloak.services.resources.flows.OAuthFlows;
|
||||||
import org.keycloak.services.resources.flows.PageFlows;
|
import org.keycloak.services.resources.flows.PageFlows;
|
||||||
|
@ -98,6 +95,10 @@ public class SocialResource {
|
||||||
@Context
|
@Context
|
||||||
ResourceContext resourceContext;
|
ResourceContext resourceContext;
|
||||||
|
|
||||||
|
@Context
|
||||||
|
protected KeycloakSession session;
|
||||||
|
|
||||||
|
|
||||||
private SocialRequestManager socialRequestManager;
|
private SocialRequestManager socialRequestManager;
|
||||||
|
|
||||||
private TokenManager tokenManager;
|
private TokenManager tokenManager;
|
||||||
|
@ -112,111 +113,107 @@ public class SocialResource {
|
||||||
@GET
|
@GET
|
||||||
@Path("callback")
|
@Path("callback")
|
||||||
public Response callback() throws URISyntaxException {
|
public Response callback() throws URISyntaxException {
|
||||||
return new Transaction<Response>() {
|
Map<String, String[]> queryParams = getQueryParams();
|
||||||
protected Response callImpl() {
|
|
||||||
Map<String, String[]> queryParams = getQueryParams();
|
|
||||||
|
|
||||||
RequestDetails requestData = getRequestDetails(queryParams);
|
RequestDetails requestData = getRequestDetails(queryParams);
|
||||||
SocialProvider provider = getProvider(requestData.getProviderId());
|
SocialProvider provider = getProvider(requestData.getProviderId());
|
||||||
|
|
||||||
String realmId = requestData.getClientAttribute("realmId");
|
String realmId = requestData.getClientAttribute("realmId");
|
||||||
|
|
||||||
RealmManager realmManager = new RealmManager(session);
|
RealmManager realmManager = new RealmManager(session);
|
||||||
RealmModel realm = realmManager.getRealm(realmId);
|
RealmModel realm = realmManager.getRealm(realmId);
|
||||||
|
|
||||||
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
|
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
|
||||||
|
|
||||||
if (!realm.isEnabled()) {
|
if (!realm.isEnabled()) {
|
||||||
return oauth.forwardToSecurityFailure("Realm not enabled.");
|
return oauth.forwardToSecurityFailure("Realm not enabled.");
|
||||||
}
|
}
|
||||||
|
|
||||||
String clientId = requestData.getClientAttributes().get("clientId");
|
String clientId = requestData.getClientAttributes().get("clientId");
|
||||||
|
|
||||||
UserModel client = realm.getUser(clientId);
|
UserModel client = realm.getUser(clientId);
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
return oauth.forwardToSecurityFailure("Unknown login requester.");
|
return oauth.forwardToSecurityFailure("Unknown login requester.");
|
||||||
}
|
}
|
||||||
if (!client.isEnabled()) {
|
if (!client.isEnabled()) {
|
||||||
return oauth.forwardToSecurityFailure("Login requester not enabled.");
|
return oauth.forwardToSecurityFailure("Login requester not enabled.");
|
||||||
}
|
}
|
||||||
|
|
||||||
String key = System.getProperty("keycloak.social." + requestData.getProviderId() + ".key");
|
String key = System.getProperty("keycloak.social." + requestData.getProviderId() + ".key");
|
||||||
String secret = System.getProperty("keycloak.social." + requestData.getProviderId() + ".secret");
|
String secret = System.getProperty("keycloak.social." + requestData.getProviderId() + ".secret");
|
||||||
String callbackUri = Urls.socialCallback(uriInfo.getBaseUri()).toString();
|
String callbackUri = Urls.socialCallback(uriInfo.getBaseUri()).toString();
|
||||||
SocialProviderConfig config = new SocialProviderConfig(key, secret, callbackUri);
|
SocialProviderConfig config = new SocialProviderConfig(key, secret, callbackUri);
|
||||||
|
|
||||||
AuthCallback callback = new AuthCallback(requestData.getSocialAttributes(), queryParams);
|
AuthCallback callback = new AuthCallback(requestData.getSocialAttributes(), queryParams);
|
||||||
|
|
||||||
SocialUser socialUser = null;
|
SocialUser socialUser = null;
|
||||||
try {
|
try {
|
||||||
socialUser = provider.processCallback(config, callback);
|
socialUser = provider.processCallback(config, callback);
|
||||||
} catch (SocialProviderException e) {
|
} catch (SocialProviderException e) {
|
||||||
logger.warn("Failed to process social callback", e);
|
logger.warn("Failed to process social callback", e);
|
||||||
return oauth.forwardToSecurityFailure("Failed to process social callback");
|
return oauth.forwardToSecurityFailure("Failed to process social callback");
|
||||||
}
|
}
|
||||||
|
|
||||||
SocialLinkModel socialLink = new SocialLinkModel(provider.getId(), socialUser.getUsername());
|
SocialLinkModel socialLink = new SocialLinkModel(provider.getId(), socialUser.getUsername());
|
||||||
UserModel user = realm.getUserBySocialLink(socialLink);
|
UserModel user = realm.getUserBySocialLink(socialLink);
|
||||||
|
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
if (!realm.isRegistrationAllowed()) {
|
if (!realm.isRegistrationAllowed()) {
|
||||||
return oauth.forwardToSecurityFailure("Registration not allowed");
|
return oauth.forwardToSecurityFailure("Registration not allowed");
|
||||||
}
|
|
||||||
|
|
||||||
// Automatically register user into realm with his social username (don't redirect to registration screen)
|
|
||||||
if (realm.isAutomaticRegistrationAfterSocialLogin()) {
|
|
||||||
|
|
||||||
if (realm.getUser(socialUser.getUsername()) != null) {
|
|
||||||
// TODO: Username is already in realm. Show message and let user to bind accounts after he re-authenticate
|
|
||||||
throw new IllegalStateException("Username " + socialUser.getUsername() +
|
|
||||||
" already registered in the realm. TODO: bind accounts...");
|
|
||||||
|
|
||||||
// TODO: Maybe we should search also by email and bind accounts if user with this email is
|
|
||||||
// already registered. But actually Keycloak allows duplicate emails
|
|
||||||
} else {
|
|
||||||
user = realm.addUser(socialUser.getUsername());
|
|
||||||
user.setFirstName(socialUser.getFirstName());
|
|
||||||
user.setLastName(socialUser.getLastName());
|
|
||||||
user.setEmail(socialUser.getEmail());
|
|
||||||
}
|
|
||||||
|
|
||||||
realm.addSocialLink(user, socialLink);
|
|
||||||
|
|
||||||
for (RoleModel role : realm.getDefaultRoles()) {
|
|
||||||
realm.grantRole(user, role);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Redirect user to registration screen with prefilled data from social provider
|
|
||||||
MultivaluedMap<String, String> formData = fillRegistrationFormWithSocialData(socialUser);
|
|
||||||
|
|
||||||
RequestDetailsBuilder reqDetailsBuilder = RequestDetailsBuilder.createFromRequestDetails(requestData);
|
|
||||||
reqDetailsBuilder.putSocialAttribute(SocialConstants.ATTR_SOCIAL_LINK, socialLink);
|
|
||||||
|
|
||||||
String requestId = UUID.randomUUID().toString();
|
|
||||||
socialRequestManager.addRequest(requestId, reqDetailsBuilder.build());
|
|
||||||
boolean secureOnly = !realm.isSslNotRequired();
|
|
||||||
String cookiePath = Urls.socialBase(uriInfo.getBaseUri()).build().getPath();
|
|
||||||
logger.info("creating cookie for social registration - name: " + SocialConstants.SOCIAL_REGISTRATION_COOKIE
|
|
||||||
+ " path: " + cookiePath);
|
|
||||||
NewCookie newCookie = new NewCookie(SocialConstants.SOCIAL_REGISTRATION_COOKIE, requestId,
|
|
||||||
cookiePath, null, "Added social cookie", NewCookie.DEFAULT_MAX_AGE, secureOnly);
|
|
||||||
response.addNewCookie(newCookie);
|
|
||||||
|
|
||||||
return Flows.forms(realm, request).setFormData(formData).setSocialRegistration(true).forwardToRegistration();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!user.isEnabled()) {
|
|
||||||
return oauth.forwardToSecurityFailure("Your account is not enabled.");
|
|
||||||
}
|
|
||||||
|
|
||||||
String scope = requestData.getClientAttributes().get("scope");
|
|
||||||
String state = requestData.getClientAttributes().get("state");
|
|
||||||
String redirectUri = requestData.getClientAttributes().get("redirectUri");
|
|
||||||
|
|
||||||
return oauth.processAccessCode(scope, state, redirectUri, client, user);
|
|
||||||
}
|
}
|
||||||
}.call();
|
|
||||||
|
// Automatically register user into realm with his social username (don't redirect to registration screen)
|
||||||
|
if (realm.isAutomaticRegistrationAfterSocialLogin()) {
|
||||||
|
|
||||||
|
if (realm.getUser(socialUser.getUsername()) != null) {
|
||||||
|
// TODO: Username is already in realm. Show message and let user to bind accounts after he re-authenticate
|
||||||
|
throw new IllegalStateException("Username " + socialUser.getUsername() +
|
||||||
|
" already registered in the realm. TODO: bind accounts...");
|
||||||
|
|
||||||
|
// TODO: Maybe we should search also by email and bind accounts if user with this email is
|
||||||
|
// already registered. But actually Keycloak allows duplicate emails
|
||||||
|
} else {
|
||||||
|
user = realm.addUser(socialUser.getUsername());
|
||||||
|
user.setFirstName(socialUser.getFirstName());
|
||||||
|
user.setLastName(socialUser.getLastName());
|
||||||
|
user.setEmail(socialUser.getEmail());
|
||||||
|
}
|
||||||
|
|
||||||
|
realm.addSocialLink(user, socialLink);
|
||||||
|
|
||||||
|
for (RoleModel role : realm.getDefaultRoles()) {
|
||||||
|
realm.grantRole(user, role);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Redirect user to registration screen with prefilled data from social provider
|
||||||
|
MultivaluedMap<String, String> formData = fillRegistrationFormWithSocialData(socialUser);
|
||||||
|
|
||||||
|
RequestDetailsBuilder reqDetailsBuilder = RequestDetailsBuilder.createFromRequestDetails(requestData);
|
||||||
|
reqDetailsBuilder.putSocialAttribute(SocialConstants.ATTR_SOCIAL_LINK, socialLink);
|
||||||
|
|
||||||
|
String requestId = UUID.randomUUID().toString();
|
||||||
|
socialRequestManager.addRequest(requestId, reqDetailsBuilder.build());
|
||||||
|
boolean secureOnly = !realm.isSslNotRequired();
|
||||||
|
String cookiePath = Urls.socialBase(uriInfo.getBaseUri()).build().getPath();
|
||||||
|
logger.info("creating cookie for social registration - name: " + SocialConstants.SOCIAL_REGISTRATION_COOKIE
|
||||||
|
+ " path: " + cookiePath);
|
||||||
|
NewCookie newCookie = new NewCookie(SocialConstants.SOCIAL_REGISTRATION_COOKIE, requestId,
|
||||||
|
cookiePath, null, "Added social cookie", NewCookie.DEFAULT_MAX_AGE, secureOnly);
|
||||||
|
response.addNewCookie(newCookie);
|
||||||
|
|
||||||
|
return Flows.forms(realm, request).setFormData(formData).setSocialRegistration(true).forwardToRegistration();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user.isEnabled()) {
|
||||||
|
return oauth.forwardToSecurityFailure("Your account is not enabled.");
|
||||||
|
}
|
||||||
|
|
||||||
|
String scope = requestData.getClientAttributes().get("scope");
|
||||||
|
String state = requestData.getClientAttributes().get("state");
|
||||||
|
String redirectUri = requestData.getClientAttributes().get("redirectUri");
|
||||||
|
|
||||||
|
return oauth.processAccessCode(scope, state, redirectUri, client, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
|
@ -257,63 +254,59 @@ public class SocialResource {
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
public Response socialRegistration(@PathParam("realm") final String realmId,
|
public Response socialRegistration(@PathParam("realm") final String realmId,
|
||||||
final MultivaluedMap<String, String> formData) {
|
final MultivaluedMap<String, String> formData) {
|
||||||
return new Transaction<Response>() {
|
PageFlows pageFlows = Flows.pages(request);
|
||||||
protected Response callImpl() {
|
Cookie cookie = headers.getCookies().get(SocialConstants.SOCIAL_REGISTRATION_COOKIE);
|
||||||
PageFlows pageFlows = Flows.pages(request);
|
if (cookie == null) {
|
||||||
Cookie cookie = headers.getCookies().get(SocialConstants.SOCIAL_REGISTRATION_COOKIE);
|
return pageFlows.forwardToSecurityFailure("Social registration cookie not found");
|
||||||
if (cookie == null) {
|
}
|
||||||
return pageFlows.forwardToSecurityFailure("Social registration cookie not found");
|
|
||||||
}
|
|
||||||
|
|
||||||
String requestId = cookie.getValue();
|
String requestId = cookie.getValue();
|
||||||
if (!socialRequestManager.isRequestId(requestId)) {
|
if (!socialRequestManager.isRequestId(requestId)) {
|
||||||
logger.error("Unknown requestId found in cookie. Maybe it's expired. requestId=" + requestId);
|
logger.error("Unknown requestId found in cookie. Maybe it's expired. requestId=" + requestId);
|
||||||
return pageFlows.forwardToSecurityFailure("Unknown requestId found in cookie. Maybe it's expired.");
|
return pageFlows.forwardToSecurityFailure("Unknown requestId found in cookie. Maybe it's expired.");
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestDetails requestData = socialRequestManager.getData(requestId);
|
RequestDetails requestData = socialRequestManager.getData(requestId);
|
||||||
|
|
||||||
RealmManager realmManager = new RealmManager(session);
|
RealmManager realmManager = new RealmManager(session);
|
||||||
RealmModel realm = realmManager.getRealm(realmId);
|
RealmModel realm = realmManager.getRealm(realmId);
|
||||||
if (realm == null || !realm.isEnabled()) {
|
if (realm == null || !realm.isEnabled()) {
|
||||||
return pageFlows.forwardToSecurityFailure("Realm doesn't exists or is not enabled.");
|
return pageFlows.forwardToSecurityFailure("Realm doesn't exists or is not enabled.");
|
||||||
}
|
}
|
||||||
TokenService tokenService = new TokenService(realm, tokenManager);
|
TokenService tokenService = new TokenService(realm, tokenManager);
|
||||||
resourceContext.initResource(tokenService);
|
resourceContext.initResource(tokenService);
|
||||||
|
|
||||||
String clientId = requestData.getClientAttribute("clientId");
|
String clientId = requestData.getClientAttribute("clientId");
|
||||||
String scope = requestData.getClientAttribute("scope");
|
String scope = requestData.getClientAttribute("scope");
|
||||||
String state = requestData.getClientAttribute("state");
|
String state = requestData.getClientAttribute("state");
|
||||||
String redirectUri = requestData.getClientAttribute("redirectUri");
|
String redirectUri = requestData.getClientAttribute("redirectUri");
|
||||||
SocialLinkModel socialLink = (SocialLinkModel)requestData.getSocialAttribute(SocialConstants.ATTR_SOCIAL_LINK);
|
SocialLinkModel socialLink = (SocialLinkModel)requestData.getSocialAttribute(SocialConstants.ATTR_SOCIAL_LINK);
|
||||||
|
|
||||||
Response response1 = tokenService.processRegisterImpl(clientId, scope, state, redirectUri, formData, true);
|
Response response1 = tokenService.processRegisterImpl(clientId, scope, state, redirectUri, formData, true);
|
||||||
|
|
||||||
// Some error occured during registration
|
// Some error occured during registration
|
||||||
if (response1 != null || request.wasForwarded()) {
|
if (response1 != null || request.wasForwarded()) {
|
||||||
logger.warn("Registration attempt wasn't successful. Request already forwarded or redirected.");
|
logger.warn("Registration attempt wasn't successful. Request already forwarded or redirected.");
|
||||||
return response1;
|
return response1;
|
||||||
}
|
}
|
||||||
|
|
||||||
String username = formData.getFirst("username");
|
String username = formData.getFirst("username");
|
||||||
UserModel user = realm.getUser(username);
|
UserModel user = realm.getUser(username);
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
// Normally shouldn't happen
|
// Normally shouldn't happen
|
||||||
throw new IllegalStateException("User " + username + " not found in the realm");
|
throw new IllegalStateException("User " + username + " not found in the realm");
|
||||||
}
|
}
|
||||||
realm.addSocialLink(user, socialLink);
|
realm.addSocialLink(user, socialLink);
|
||||||
|
|
||||||
// Expire cookie and invalidate requestData
|
// Expire cookie and invalidate requestData
|
||||||
String cookiePath = Urls.socialBase(uriInfo.getBaseUri()).build().getPath();
|
String cookiePath = Urls.socialBase(uriInfo.getBaseUri()).build().getPath();
|
||||||
NewCookie newCookie = new NewCookie(SocialConstants.SOCIAL_REGISTRATION_COOKIE, "", cookiePath, null,
|
NewCookie newCookie = new NewCookie(SocialConstants.SOCIAL_REGISTRATION_COOKIE, "", cookiePath, null,
|
||||||
"Expire social cookie", 0, false);
|
"Expire social cookie", 0, false);
|
||||||
logger.info("Expiring social registration cookie: " + SocialConstants.SOCIAL_REGISTRATION_COOKIE + ", path: " + cookiePath);
|
logger.info("Expiring social registration cookie: " + SocialConstants.SOCIAL_REGISTRATION_COOKIE + ", path: " + cookiePath);
|
||||||
response.addNewCookie(newCookie);
|
response.addNewCookie(newCookie);
|
||||||
socialRequestManager.retrieveData(requestId);
|
socialRequestManager.retrieveData(requestId);
|
||||||
|
|
||||||
return tokenService.processLogin(clientId, scope, state, redirectUri, formData);
|
return tokenService.processLogin(clientId, scope, state, redirectUri, formData);
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private RequestDetails getRequestDetails(Map<String, String[]> queryParams) {
|
private RequestDetails getRequestDetails(Map<String, String[]> queryParams) {
|
||||||
|
|
|
@ -18,11 +18,7 @@ import org.keycloak.services.managers.RealmManager;
|
||||||
import org.keycloak.services.managers.ResourceAdminManager;
|
import org.keycloak.services.managers.ResourceAdminManager;
|
||||||
import org.keycloak.services.managers.TokenManager;
|
import org.keycloak.services.managers.TokenManager;
|
||||||
import org.keycloak.services.messages.Messages;
|
import org.keycloak.services.messages.Messages;
|
||||||
import org.keycloak.services.models.RealmModel;
|
import org.keycloak.services.models.*;
|
||||||
import org.keycloak.services.models.RequiredCredentialModel;
|
|
||||||
import org.keycloak.services.models.RoleModel;
|
|
||||||
import org.keycloak.services.models.UserCredentialModel;
|
|
||||||
import org.keycloak.services.models.UserModel;
|
|
||||||
import org.keycloak.services.resources.flows.Flows;
|
import org.keycloak.services.resources.flows.Flows;
|
||||||
import org.keycloak.services.resources.flows.OAuthFlows;
|
import org.keycloak.services.resources.flows.OAuthFlows;
|
||||||
import org.keycloak.services.validation.Validation;
|
import org.keycloak.services.validation.Validation;
|
||||||
|
@ -75,9 +71,14 @@ public class TokenService {
|
||||||
@Context
|
@Context
|
||||||
protected HttpHeaders headers;
|
protected HttpHeaders headers;
|
||||||
@Context
|
@Context
|
||||||
HttpRequest request;
|
protected HttpRequest request;
|
||||||
@Context
|
@Context
|
||||||
HttpResponse response;
|
protected HttpResponse response;
|
||||||
|
@Context
|
||||||
|
protected KeycloakSession session;
|
||||||
|
@Context
|
||||||
|
protected KeycloakTransaction transaction;
|
||||||
|
|
||||||
|
|
||||||
private ResourceAdminManager resourceAdminManager = new ResourceAdminManager();
|
private ResourceAdminManager resourceAdminManager = new ResourceAdminManager();
|
||||||
|
|
||||||
|
@ -123,32 +124,28 @@ public class TokenService {
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Response grantIdentityToken(final MultivaluedMap<String, String> form) {
|
public Response grantIdentityToken(final MultivaluedMap<String, String> form) {
|
||||||
return new Transaction<Response>() {
|
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
|
||||||
protected Response callImpl() {
|
if (username == null) {
|
||||||
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
|
throw new NotAuthorizedException("No user");
|
||||||
if (username == null) {
|
}
|
||||||
throw new NotAuthorizedException("No user");
|
if (!realm.isEnabled()) {
|
||||||
}
|
throw new NotAuthorizedException("Disabled realm");
|
||||||
if (!realm.isEnabled()) {
|
}
|
||||||
throw new NotAuthorizedException("Disabled realm");
|
UserModel user = realm.getUser(username);
|
||||||
}
|
if (user == null) {
|
||||||
UserModel user = realm.getUser(username);
|
throw new NotAuthorizedException("No user");
|
||||||
if (user == null) {
|
}
|
||||||
throw new NotAuthorizedException("No user");
|
if (!user.isEnabled()) {
|
||||||
}
|
throw new NotAuthorizedException("Disabled user.");
|
||||||
if (!user.isEnabled()) {
|
}
|
||||||
throw new NotAuthorizedException("Disabled user.");
|
if (!authManager.authenticateForm(realm, user, form)) {
|
||||||
}
|
throw new NotAuthorizedException("FORM");
|
||||||
if (!authManager.authenticateForm(realm, user, form)) {
|
}
|
||||||
throw new NotAuthorizedException("FORM");
|
tokenManager = new TokenManager();
|
||||||
}
|
SkeletonKeyToken token = authManager.createIdentityToken(realm, username);
|
||||||
tokenManager = new TokenManager();
|
String encoded = tokenManager.encodeToken(realm, token);
|
||||||
SkeletonKeyToken token = authManager.createIdentityToken(realm, username);
|
AccessTokenResponse res = accessTokenResponse(token, encoded);
|
||||||
String encoded = tokenManager.encodeToken(realm, token);
|
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
|
||||||
AccessTokenResponse res = accessTokenResponse(token, encoded);
|
|
||||||
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("grants/access")
|
@Path("grants/access")
|
||||||
|
@ -156,32 +153,27 @@ public class TokenService {
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public Response grantAccessToken(final MultivaluedMap<String, String> form) {
|
public Response grantAccessToken(final MultivaluedMap<String, String> form) {
|
||||||
return new Transaction<Response>() {
|
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
|
||||||
protected Response callImpl() {
|
if (username == null) {
|
||||||
String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
|
throw new NotAuthorizedException("No user");
|
||||||
if (username == null) {
|
}
|
||||||
throw new NotAuthorizedException("No user");
|
if (!realm.isEnabled()) {
|
||||||
}
|
throw new NotAuthorizedException("Disabled realm");
|
||||||
if (!realm.isEnabled()) {
|
}
|
||||||
throw new NotAuthorizedException("Disabled realm");
|
UserModel user = realm.getUser(username);
|
||||||
}
|
if (user == null) {
|
||||||
UserModel user = realm.getUser(username);
|
throw new NotAuthorizedException("No user");
|
||||||
if (user == null) {
|
}
|
||||||
throw new NotAuthorizedException("No user");
|
if (!user.isEnabled()) {
|
||||||
}
|
throw new NotAuthorizedException("Disabled user.");
|
||||||
if (!user.isEnabled()) {
|
}
|
||||||
throw new NotAuthorizedException("Disabled user.");
|
if (authManager.authenticateForm(realm, user, form)) {
|
||||||
}
|
throw new NotAuthorizedException("Auth failed");
|
||||||
if (authManager.authenticateForm(realm, user, form)) {
|
}
|
||||||
throw new NotAuthorizedException("Auth failed");
|
SkeletonKeyToken token = tokenManager.createAccessToken(realm, user);
|
||||||
}
|
String encoded = tokenManager.encodeToken(realm, token);
|
||||||
SkeletonKeyToken token = tokenManager.createAccessToken(realm, user);
|
AccessTokenResponse res = accessTokenResponse(token, encoded);
|
||||||
String encoded = tokenManager.encodeToken(realm, token);
|
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
|
||||||
AccessTokenResponse res = accessTokenResponse(token, encoded);
|
|
||||||
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("auth/request/login")
|
@Path("auth/request/login")
|
||||||
|
@ -190,54 +182,50 @@ public class TokenService {
|
||||||
public Response processLogin(@QueryParam("client_id") final String clientId, @QueryParam("scope") final String scopeParam,
|
public Response processLogin(@QueryParam("client_id") final String clientId, @QueryParam("scope") final String scopeParam,
|
||||||
@QueryParam("state") final String state, @QueryParam("redirect_uri") final String redirect,
|
@QueryParam("state") final String state, @QueryParam("redirect_uri") final String redirect,
|
||||||
final MultivaluedMap<String, String> formData) {
|
final MultivaluedMap<String, String> formData) {
|
||||||
return new Transaction<Response>() {
|
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
|
||||||
protected Response callImpl() {
|
|
||||||
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
|
|
||||||
|
|
||||||
if (!realm.isEnabled()) {
|
if (!realm.isEnabled()) {
|
||||||
return oauth.forwardToSecurityFailure("Realm not enabled.");
|
return oauth.forwardToSecurityFailure("Realm not enabled.");
|
||||||
}
|
}
|
||||||
UserModel client = realm.getUser(clientId);
|
UserModel client = realm.getUser(clientId);
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
return oauth.forwardToSecurityFailure("Unknown login requester.");
|
return oauth.forwardToSecurityFailure("Unknown login requester.");
|
||||||
}
|
}
|
||||||
if (!client.isEnabled()) {
|
if (!client.isEnabled()) {
|
||||||
return oauth.forwardToSecurityFailure("Login requester not enabled.");
|
return oauth.forwardToSecurityFailure("Login requester not enabled.");
|
||||||
}
|
}
|
||||||
String username = formData.getFirst("username");
|
String username = formData.getFirst("username");
|
||||||
UserModel user = realm.getUser(username);
|
UserModel user = realm.getUser(username);
|
||||||
if (user == null) {
|
if (user == null) {
|
||||||
logger.error("Incorrect user name.");
|
logger.error("Incorrect user name.");
|
||||||
|
|
||||||
return Flows.forms(realm, request).setError(Messages.INVALID_USER).setFormData(formData)
|
return Flows.forms(realm, request).setError(Messages.INVALID_USER).setFormData(formData)
|
||||||
.forwardToLogin();
|
.forwardToLogin();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!user.isEnabled()) {
|
||||||
|
return oauth.forwardToSecurityFailure("Your account is not enabled.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("ENABLED".equals(user.getAttribute("KEYCLOAK_TOTP")) && Validation.isEmpty(formData.getFirst("totp"))) {
|
||||||
|
return Flows.forms(realm, request).setFormData(formData).forwardToLoginTotp();
|
||||||
|
} else {
|
||||||
|
for (RequiredCredentialModel c : realm.getRequiredCredentials()) {
|
||||||
|
if (c.getType().equals(CredentialRepresentation.TOTP)) {
|
||||||
|
return Flows.forms(realm, request).forwardToTotp();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!user.isEnabled()) {
|
|
||||||
return oauth.forwardToSecurityFailure("Your account is not enabled.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("ENABLED".equals(user.getAttribute("KEYCLOAK_TOTP")) && Validation.isEmpty(formData.getFirst("totp"))) {
|
|
||||||
return Flows.forms(realm, request).setFormData(formData).forwardToLoginTotp();
|
|
||||||
} else {
|
|
||||||
for (RequiredCredentialModel c : realm.getRequiredCredentials()) {
|
|
||||||
if (c.getType().equals(CredentialRepresentation.TOTP)) {
|
|
||||||
return Flows.forms(realm, request).forwardToTotp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean authenticated = authManager.authenticateForm(realm, user, formData);
|
|
||||||
if (!authenticated) {
|
|
||||||
logger.error("Authentication failed");
|
|
||||||
|
|
||||||
return Flows.forms(realm, request).setError(Messages.INVALID_PASSWORD).setFormData(formData)
|
|
||||||
.forwardToLogin();
|
|
||||||
}
|
|
||||||
|
|
||||||
return oauth.processAccessCode(scopeParam, state, redirect, client, user);
|
|
||||||
}
|
}
|
||||||
}.call();
|
}
|
||||||
|
|
||||||
|
boolean authenticated = authManager.authenticateForm(realm, user, formData);
|
||||||
|
if (!authenticated) {
|
||||||
|
logger.error("Authentication failed");
|
||||||
|
|
||||||
|
return Flows.forms(realm, request).setError(Messages.INVALID_PASSWORD).setFormData(formData)
|
||||||
|
.forwardToLogin();
|
||||||
|
}
|
||||||
|
|
||||||
|
return oauth.processAccessCode(scopeParam, state, redirect, client, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("registrations")
|
@Path("registrations")
|
||||||
|
@ -246,20 +234,15 @@ public class TokenService {
|
||||||
public Response processRegister(@QueryParam("client_id") final String clientId,
|
public Response processRegister(@QueryParam("client_id") final String clientId,
|
||||||
@QueryParam("scope") final String scopeParam, @QueryParam("state") final String state,
|
@QueryParam("scope") final String scopeParam, @QueryParam("state") final String state,
|
||||||
@QueryParam("redirect_uri") final String redirect, final MultivaluedMap<String, String> formData) {
|
@QueryParam("redirect_uri") final String redirect, final MultivaluedMap<String, String> formData) {
|
||||||
return new Transaction<Response>() {
|
Response registrationResponse = processRegisterImpl(clientId, scopeParam, state, redirect, formData, false);
|
||||||
@Override
|
|
||||||
protected Response callImpl() {
|
|
||||||
Response registrationResponse = processRegisterImpl(clientId, scopeParam, state, redirect, formData, false);
|
|
||||||
|
|
||||||
// If request has been already forwarded (either due to security or validation error) then we won't continue with login
|
// If request has been already forwarded (either due to security or validation error) then we won't continue with login
|
||||||
if (registrationResponse != null || request.wasForwarded()) {
|
if (registrationResponse != null || request.wasForwarded()) {
|
||||||
logger.warn("Registration attempt wasn't successful. Request already forwarded or redirected.");
|
logger.warn("Registration attempt wasn't successful. Request already forwarded or redirected.");
|
||||||
return registrationResponse;
|
return registrationResponse;
|
||||||
} else {
|
} else {
|
||||||
return processLogin(clientId, scopeParam, state, redirect, formData);
|
return processLogin(clientId, scopeParam, state, redirect, formData);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Response processRegisterImpl(String clientId, String scopeParam, String state, String redirect,
|
public Response processRegisterImpl(String clientId, String scopeParam, String state, String redirect,
|
||||||
|
@ -347,104 +330,99 @@ public class TokenService {
|
||||||
@POST
|
@POST
|
||||||
@Produces("application/json")
|
@Produces("application/json")
|
||||||
public Response accessCodeToToken(final MultivaluedMap<String, String> formData) {
|
public Response accessCodeToToken(final MultivaluedMap<String, String> formData) {
|
||||||
return new Transaction<Response>() {
|
logger.info("accessRequest <---");
|
||||||
protected Response callImpl() {
|
if (!realm.isEnabled()) {
|
||||||
logger.info("accessRequest <---");
|
throw new NotAuthorizedException("Realm not enabled");
|
||||||
if (!realm.isEnabled()) {
|
}
|
||||||
throw new NotAuthorizedException("Realm not enabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
String code = formData.getFirst("code");
|
String code = formData.getFirst("code");
|
||||||
if (code == null) {
|
if (code == null) {
|
||||||
logger.debug("code not specified");
|
logger.debug("code not specified");
|
||||||
Map<String, String> error = new HashMap<String, String>();
|
Map<String, String> error = new HashMap<String, String>();
|
||||||
error.put("error", "invalid_request");
|
error.put("error", "invalid_request");
|
||||||
error.put("error_description", "code not specified");
|
error.put("error_description", "code not specified");
|
||||||
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
||||||
|
|
||||||
}
|
}
|
||||||
String client_id = formData.getFirst("client_id");
|
String client_id = formData.getFirst("client_id");
|
||||||
if (client_id == null) {
|
if (client_id == null) {
|
||||||
logger.debug("client_id not specified");
|
logger.debug("client_id not specified");
|
||||||
Map<String, String> error = new HashMap<String, String>();
|
Map<String, String> error = new HashMap<String, String>();
|
||||||
error.put("error", "invalid_request");
|
error.put("error", "invalid_request");
|
||||||
error.put("error_description", "client_id not specified");
|
error.put("error_description", "client_id not specified");
|
||||||
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
||||||
}
|
}
|
||||||
UserModel client = realm.getUser(client_id);
|
UserModel client = realm.getUser(client_id);
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
logger.debug("Could not find user");
|
logger.debug("Could not find user");
|
||||||
Map<String, String> error = new HashMap<String, String>();
|
Map<String, String> error = new HashMap<String, String>();
|
||||||
error.put("error", "invalid_client");
|
error.put("error", "invalid_client");
|
||||||
error.put("error_description", "Could not find user");
|
error.put("error_description", "Could not find user");
|
||||||
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!client.isEnabled()) {
|
if (!client.isEnabled()) {
|
||||||
logger.debug("user is not enabled");
|
logger.debug("user is not enabled");
|
||||||
Map<String, String> error = new HashMap<String, String>();
|
Map<String, String> error = new HashMap<String, String>();
|
||||||
error.put("error", "invalid_client");
|
error.put("error", "invalid_client");
|
||||||
error.put("error_description", "User is not enabled");
|
error.put("error_description", "User is not enabled");
|
||||||
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean authenticated = authManager.authenticateForm(realm, client, formData);
|
boolean authenticated = authManager.authenticateForm(realm, client, formData);
|
||||||
if (!authenticated) {
|
if (!authenticated) {
|
||||||
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");
|
||||||
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
|
||||||
}
|
}
|
||||||
|
|
||||||
JWSInput input = new JWSInput(code, providers);
|
|
||||||
boolean verifiedCode = false;
|
|
||||||
try {
|
|
||||||
verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
logger.debug("Failed to verify signature", ignored);
|
|
||||||
}
|
|
||||||
if (!verifiedCode) {
|
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
|
||||||
res.put("error", "invalid_grant");
|
|
||||||
res.put("error_description", "Unable to verify code signature");
|
|
||||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
String key = input.readContent(String.class);
|
|
||||||
AccessCodeEntry accessCode = tokenManager.pullAccessCode(key);
|
|
||||||
if (accessCode == null) {
|
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
|
||||||
res.put("error", "invalid_grant");
|
|
||||||
res.put("error_description", "Code not found");
|
|
||||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
if (accessCode.isExpired()) {
|
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
|
||||||
res.put("error", "invalid_grant");
|
|
||||||
res.put("error_description", "Code is expired");
|
|
||||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
if (!accessCode.getToken().isActive()) {
|
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
|
||||||
res.put("error", "invalid_grant");
|
|
||||||
res.put("error_description", "Token expired");
|
|
||||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
if (!client.getLoginName().equals(accessCode.getClient().getLoginName())) {
|
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
|
||||||
res.put("error", "invalid_grant");
|
|
||||||
res.put("error_description", "Auth error");
|
|
||||||
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
logger.info("accessRequest SUCCESS");
|
|
||||||
AccessTokenResponse res = accessTokenResponse(realm.getPrivateKey(), accessCode.getToken());
|
|
||||||
return Response.ok(res).build();
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
|
|
||||||
|
JWSInput input = new JWSInput(code, providers);
|
||||||
|
boolean verifiedCode = false;
|
||||||
|
try {
|
||||||
|
verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
logger.debug("Failed to verify signature", ignored);
|
||||||
|
}
|
||||||
|
if (!verifiedCode) {
|
||||||
|
Map<String, String> res = new HashMap<String, String>();
|
||||||
|
res.put("error", "invalid_grant");
|
||||||
|
res.put("error_description", "Unable to verify code signature");
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
String key = input.readContent(String.class);
|
||||||
|
AccessCodeEntry accessCode = tokenManager.pullAccessCode(key);
|
||||||
|
if (accessCode == null) {
|
||||||
|
Map<String, String> res = new HashMap<String, String>();
|
||||||
|
res.put("error", "invalid_grant");
|
||||||
|
res.put("error_description", "Code not found");
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
if (accessCode.isExpired()) {
|
||||||
|
Map<String, String> res = new HashMap<String, String>();
|
||||||
|
res.put("error", "invalid_grant");
|
||||||
|
res.put("error_description", "Code is expired");
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
if (!accessCode.getToken().isActive()) {
|
||||||
|
Map<String, String> res = new HashMap<String, String>();
|
||||||
|
res.put("error", "invalid_grant");
|
||||||
|
res.put("error_description", "Token expired");
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
if (!client.getLoginName().equals(accessCode.getClient().getLoginName())) {
|
||||||
|
Map<String, String> res = new HashMap<String, String>();
|
||||||
|
res.put("error", "invalid_grant");
|
||||||
|
res.put("error_description", "Auth error");
|
||||||
|
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
logger.info("accessRequest SUCCESS");
|
||||||
|
AccessTokenResponse res = accessTokenResponse(realm.getPrivateKey(), accessCode.getToken());
|
||||||
|
return Response.ok(res).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AccessTokenResponse accessTokenResponse(PrivateKey privateKey, SkeletonKeyToken token) {
|
protected AccessTokenResponse accessTokenResponse(PrivateKey privateKey, SkeletonKeyToken token) {
|
||||||
|
@ -475,47 +453,43 @@ public class TokenService {
|
||||||
public Response loginPage(final @QueryParam("response_type") String responseType,
|
public Response loginPage(final @QueryParam("response_type") String responseType,
|
||||||
final @QueryParam("redirect_uri") String redirect, final @QueryParam("client_id") String clientId,
|
final @QueryParam("redirect_uri") String redirect, final @QueryParam("client_id") String clientId,
|
||||||
final @QueryParam("scope") String scopeParam, final @QueryParam("state") String state) {
|
final @QueryParam("scope") String scopeParam, final @QueryParam("state") String state) {
|
||||||
return new Transaction<Response>() {
|
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
|
||||||
protected Response callImpl() {
|
|
||||||
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
|
|
||||||
|
|
||||||
if (!realm.isEnabled()) {
|
if (!realm.isEnabled()) {
|
||||||
oauth.forwardToSecurityFailure("Realm not enabled");
|
oauth.forwardToSecurityFailure("Realm not enabled");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
UserModel client = realm.getUser(clientId);
|
UserModel client = realm.getUser(clientId);
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
oauth.forwardToSecurityFailure("Unknown login requester.");
|
oauth.forwardToSecurityFailure("Unknown login requester.");
|
||||||
transaction.rollback();
|
transaction.rollback();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!client.isEnabled()) {
|
if (!client.isEnabled()) {
|
||||||
oauth.forwardToSecurityFailure("Login requester not enabled.");
|
oauth.forwardToSecurityFailure("Login requester not enabled.");
|
||||||
transaction.rollback();
|
transaction.rollback();
|
||||||
session.close();
|
session.close();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
RoleModel resourceRole = realm.getRole(RealmManager.RESOURCE_ROLE);
|
RoleModel resourceRole = realm.getRole(RealmManager.RESOURCE_ROLE);
|
||||||
RoleModel identityRequestRole = realm.getRole(RealmManager.IDENTITY_REQUESTER_ROLE);
|
RoleModel identityRequestRole = realm.getRole(RealmManager.IDENTITY_REQUESTER_ROLE);
|
||||||
boolean isResource = realm.hasRole(client, resourceRole);
|
boolean isResource = realm.hasRole(client, resourceRole);
|
||||||
if (!isResource && !realm.hasRole(client, identityRequestRole)) {
|
if (!isResource && !realm.hasRole(client, identityRequestRole)) {
|
||||||
oauth.forwardToSecurityFailure("Login requester not allowed to request login.");
|
oauth.forwardToSecurityFailure("Login requester not allowed to request login.");
|
||||||
transaction.rollback();
|
transaction.rollback();
|
||||||
session.close();
|
session.close();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
logger.info(user.getLoginName() + " already logged in.");
|
logger.info(user.getLoginName() + " already logged in.");
|
||||||
return oauth.processAccessCode(scopeParam, state, redirect, client, user);
|
return oauth.processAccessCode(scopeParam, state, redirect, client, user);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Flows.forms(realm, request).forwardToLogin();
|
return Flows.forms(realm, request).forwardToLogin();
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("registrations")
|
@Path("registrations")
|
||||||
|
@ -523,88 +497,76 @@ public class TokenService {
|
||||||
public Response registerPage(final @QueryParam("response_type") String responseType,
|
public Response registerPage(final @QueryParam("response_type") String responseType,
|
||||||
final @QueryParam("redirect_uri") String redirect, final @QueryParam("client_id") String clientId,
|
final @QueryParam("redirect_uri") String redirect, final @QueryParam("client_id") String clientId,
|
||||||
final @QueryParam("scope") String scopeParam, final @QueryParam("state") String state) {
|
final @QueryParam("scope") String scopeParam, final @QueryParam("state") String state) {
|
||||||
return new Transaction<Response>() {
|
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
|
||||||
protected Response callImpl() {
|
|
||||||
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
|
|
||||||
|
|
||||||
if (!realm.isEnabled()) {
|
if (!realm.isEnabled()) {
|
||||||
return oauth.forwardToSecurityFailure("Realm not enabled");
|
return oauth.forwardToSecurityFailure("Realm not enabled");
|
||||||
}
|
}
|
||||||
UserModel client = realm.getUser(clientId);
|
UserModel client = realm.getUser(clientId);
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
return oauth.forwardToSecurityFailure("Unknown login requester.");
|
return oauth.forwardToSecurityFailure("Unknown login requester.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!client.isEnabled()) {
|
if (!client.isEnabled()) {
|
||||||
return oauth.forwardToSecurityFailure("Login requester not enabled.");
|
return oauth.forwardToSecurityFailure("Login requester not enabled.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!realm.isRegistrationAllowed()) {
|
if (!realm.isRegistrationAllowed()) {
|
||||||
return oauth.forwardToSecurityFailure("Registration not allowed");
|
return oauth.forwardToSecurityFailure("Registration not allowed");
|
||||||
}
|
}
|
||||||
|
|
||||||
authManager.expireIdentityCookie(realm, uriInfo);
|
authManager.expireIdentityCookie(realm, uriInfo);
|
||||||
|
|
||||||
return Flows.forms(realm, request).forwardToRegistration();
|
return Flows.forms(realm, request).forwardToRegistration();
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("logout")
|
@Path("logout")
|
||||||
@GET
|
@GET
|
||||||
@NoCache
|
@NoCache
|
||||||
public Response logout(final @QueryParam("redirect_uri") String redirectUri) {
|
public Response logout(final @QueryParam("redirect_uri") String redirectUri) {
|
||||||
return new Transaction<Response>() {
|
// todo do we care if anybody can trigger this?
|
||||||
protected Response callImpl() {
|
|
||||||
// todo do we care if anybody can trigger this?
|
|
||||||
|
|
||||||
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
logger.info("Logging out: " + user.getLoginName());
|
logger.info("Logging out: " + user.getLoginName());
|
||||||
authManager.expireIdentityCookie(realm, uriInfo);
|
authManager.expireIdentityCookie(realm, uriInfo);
|
||||||
resourceAdminManager.singleLogOut(realm, user.getLoginName());
|
resourceAdminManager.singleLogOut(realm, user.getLoginName());
|
||||||
}
|
}
|
||||||
// todo manage legal redirects
|
// todo manage legal redirects
|
||||||
return Response.status(302).location(UriBuilder.fromUri(redirectUri).build()).build();
|
return Response.status(302).location(UriBuilder.fromUri(redirectUri).build()).build();
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("oauth/grant")
|
@Path("oauth/grant")
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||||
public Response processOAuth(final MultivaluedMap<String, String> formData) {
|
public Response processOAuth(final MultivaluedMap<String, String> formData) {
|
||||||
return new Transaction<Response>() {
|
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
|
||||||
protected Response callImpl() {
|
|
||||||
OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager);
|
|
||||||
|
|
||||||
String code = formData.getFirst("code");
|
String code = formData.getFirst("code");
|
||||||
JWSInput input = new JWSInput(code, providers);
|
JWSInput input = new JWSInput(code, providers);
|
||||||
boolean verifiedCode = false;
|
boolean verifiedCode = false;
|
||||||
try {
|
try {
|
||||||
verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
|
verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
logger.debug("Failed to verify signature", ignored);
|
logger.debug("Failed to verify signature", ignored);
|
||||||
}
|
}
|
||||||
if (!verifiedCode) {
|
if (!verifiedCode) {
|
||||||
return oauth.forwardToSecurityFailure("Illegal access code.");
|
return oauth.forwardToSecurityFailure("Illegal access code.");
|
||||||
}
|
}
|
||||||
String key = input.readContent(String.class);
|
String key = input.readContent(String.class);
|
||||||
AccessCodeEntry accessCodeEntry = tokenManager.getAccessCode(key);
|
AccessCodeEntry accessCodeEntry = tokenManager.getAccessCode(key);
|
||||||
if (accessCodeEntry == null) {
|
if (accessCodeEntry == null) {
|
||||||
return oauth.forwardToSecurityFailure("Unknown access code.");
|
return oauth.forwardToSecurityFailure("Unknown access code.");
|
||||||
}
|
}
|
||||||
|
|
||||||
String redirect = accessCodeEntry.getRedirectUri();
|
String redirect = accessCodeEntry.getRedirectUri();
|
||||||
String state = accessCodeEntry.getState();
|
String state = accessCodeEntry.getState();
|
||||||
|
|
||||||
if (formData.containsKey("cancel")) {
|
if (formData.containsKey("cancel")) {
|
||||||
return redirectAccessDenied(redirect, state);
|
return redirectAccessDenied(redirect, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
return oauth.redirectAccessCode(accessCodeEntry, state, redirect);
|
return oauth.redirectAccessCode(accessCodeEntry, state, redirect);
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Response redirectAccessDenied(String redirect, String state) {
|
protected Response redirectAccessDenied(String redirect, String state) {
|
||||||
|
|
|
@ -2,17 +2,15 @@ package org.keycloak.services.resources;
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||||
import org.keycloak.services.models.KeycloakSession;
|
import org.keycloak.services.models.KeycloakSession;
|
||||||
import org.keycloak.services.models.KeycloakSessionFactory;
|
|
||||||
import org.keycloak.services.models.KeycloakTransaction;
|
import org.keycloak.services.models.KeycloakTransaction;
|
||||||
|
|
||||||
import javax.ws.rs.core.Application;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Meant to be used as an inner class wrapper (I forget the pattern name, its been awhile).
|
* Meant to be used as an inner class wrapper (I forget the pattern name, its been awhile).
|
||||||
*
|
*
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public class Transaction<T> {
|
public class Transaction<T> {
|
||||||
protected KeycloakSession session;
|
protected KeycloakSession session;
|
||||||
protected KeycloakTransaction transaction;
|
protected KeycloakTransaction transaction;
|
||||||
|
@ -36,6 +34,8 @@ public class Transaction<T> {
|
||||||
*/
|
*/
|
||||||
public Transaction(boolean close) {
|
public Transaction(boolean close) {
|
||||||
this.session = ResteasyProviderFactory.getContextData(KeycloakSession.class);
|
this.session = ResteasyProviderFactory.getContextData(KeycloakSession.class);
|
||||||
|
this.transaction = session.getTransaction();
|
||||||
|
/*
|
||||||
if (session == null) {
|
if (session == null) {
|
||||||
KeycloakApplication app = (KeycloakApplication)ResteasyProviderFactory.getContextData(Application.class);
|
KeycloakApplication app = (KeycloakApplication)ResteasyProviderFactory.getContextData(Application.class);
|
||||||
session = app.getFactory().createSession();
|
session = app.getFactory().createSession();
|
||||||
|
@ -44,20 +44,10 @@ public class Transaction<T> {
|
||||||
}
|
}
|
||||||
transaction = session.getTransaction();
|
transaction = session.getTransaction();
|
||||||
closeSession = close;
|
closeSession = close;
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates and manages its own session.
|
|
||||||
*
|
|
||||||
* @param factory
|
|
||||||
*/
|
|
||||||
public Transaction(KeycloakSessionFactory factory) {
|
|
||||||
this.closeSession = true;
|
|
||||||
this.session = factory.createSession();
|
|
||||||
this.transaction = session.getTransaction();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void runImpl() {
|
protected void runImpl() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -67,20 +57,20 @@ public class Transaction<T> {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public void run() {
|
public void run() {
|
||||||
boolean wasActive = transaction.isActive();
|
// boolean wasActive = transaction.isActive();
|
||||||
if (!wasActive) transaction.begin();
|
// if (!wasActive) transaction.begin();
|
||||||
try {
|
// try {
|
||||||
runImpl();
|
runImpl();
|
||||||
if (!wasActive && transaction.isActive()) transaction.commit();
|
// if (!wasActive && transaction.isActive()) transaction.commit();
|
||||||
} catch (RuntimeException e) {
|
// } catch (RuntimeException e) {
|
||||||
if (!wasActive && transaction.isActive()) transaction.rollback();
|
// if (!wasActive && transaction.isActive()) transaction.rollback();
|
||||||
if (created) closeSession = true;
|
// if (created) closeSession = true;
|
||||||
throw e;
|
// throw e;
|
||||||
} finally {
|
// } finally {
|
||||||
if (!wasActive && closeSession) {
|
// if (!wasActive && closeSession) {
|
||||||
session.close();
|
// session.close();
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
protected T callImpl() {
|
protected T callImpl() {
|
||||||
|
@ -92,18 +82,18 @@ public class Transaction<T> {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public T call() {
|
public T call() {
|
||||||
boolean wasActive = transaction.isActive();
|
// boolean wasActive = transaction.isActive();
|
||||||
if (!wasActive) transaction.begin();
|
// if (!wasActive) transaction.begin();
|
||||||
try {
|
// try {
|
||||||
T rtn = callImpl();
|
T rtn = callImpl();
|
||||||
if (!wasActive && transaction.isActive()) transaction.commit();
|
// if (!wasActive && transaction.isActive()) transaction.commit();
|
||||||
return rtn;
|
return rtn;
|
||||||
} catch (RuntimeException e) {
|
// } catch (RuntimeException e) {
|
||||||
if (!wasActive && transaction.isActive()) transaction.rollback();
|
// if (!wasActive && transaction.isActive()) transaction.rollback();
|
||||||
if (created) closeSession = true; // close if there was a failure
|
// if (created) closeSession = true; // close if there was a failure
|
||||||
throw e;
|
// throw e;
|
||||||
} finally {
|
// } finally {
|
||||||
if (!wasActive && closeSession) session.close();
|
// if (!wasActive && closeSession) session.close();
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,16 +5,13 @@ import org.jboss.resteasy.logging.Logger;
|
||||||
import org.keycloak.representations.idm.ApplicationRepresentation;
|
import org.keycloak.representations.idm.ApplicationRepresentation;
|
||||||
import org.keycloak.services.managers.RealmManager;
|
import org.keycloak.services.managers.RealmManager;
|
||||||
import org.keycloak.services.managers.ResourceManager;
|
import org.keycloak.services.managers.ResourceManager;
|
||||||
import org.keycloak.services.models.RealmModel;
|
|
||||||
import org.keycloak.services.models.ApplicationModel;
|
import org.keycloak.services.models.ApplicationModel;
|
||||||
|
import org.keycloak.services.models.KeycloakSession;
|
||||||
|
import org.keycloak.services.models.RealmModel;
|
||||||
import org.keycloak.services.models.UserModel;
|
import org.keycloak.services.models.UserModel;
|
||||||
import org.keycloak.services.resources.Transaction;
|
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.*;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.PUT;
|
|
||||||
import javax.ws.rs.PathParam;
|
|
||||||
import javax.ws.rs.Produces;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -27,6 +24,9 @@ public class ApplicationResource {
|
||||||
protected RealmModel realm;
|
protected RealmModel realm;
|
||||||
protected ApplicationModel applicationModel;
|
protected ApplicationModel applicationModel;
|
||||||
|
|
||||||
|
@Context
|
||||||
|
protected KeycloakSession session;
|
||||||
|
|
||||||
public ApplicationResource(UserModel admin, RealmModel realm, ApplicationModel applicationModel) {
|
public ApplicationResource(UserModel admin, RealmModel realm, ApplicationModel applicationModel) {
|
||||||
this.admin = admin;
|
this.admin = admin;
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
|
@ -36,13 +36,8 @@ public class ApplicationResource {
|
||||||
@PUT
|
@PUT
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public void update(final ApplicationRepresentation rep) {
|
public void update(final ApplicationRepresentation rep) {
|
||||||
new Transaction<Void>() {
|
ResourceManager resourceManager = new ResourceManager(new RealmManager(session));
|
||||||
@Override
|
resourceManager.updateResource(rep, applicationModel);
|
||||||
protected void runImpl() {
|
|
||||||
ResourceManager resourceManager = new ResourceManager(new RealmManager(session));
|
|
||||||
resourceManager.updateResource(rep, applicationModel);
|
|
||||||
}
|
|
||||||
}.run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,12 +45,7 @@ public class ApplicationResource {
|
||||||
@NoCache
|
@NoCache
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
public ApplicationRepresentation getResource(final @PathParam("id") String id) {
|
public ApplicationRepresentation getResource(final @PathParam("id") String id) {
|
||||||
return new Transaction<ApplicationRepresentation>() {
|
ResourceManager resourceManager = new ResourceManager(new RealmManager(session));
|
||||||
@Override
|
return resourceManager.toRepresentation(applicationModel);
|
||||||
protected ApplicationRepresentation callImpl() {
|
|
||||||
ResourceManager resourceManager = new ResourceManager(new RealmManager(session));
|
|
||||||
return resourceManager.toRepresentation(applicationModel);
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,18 +5,13 @@ import org.jboss.resteasy.logging.Logger;
|
||||||
import org.keycloak.representations.idm.ApplicationRepresentation;
|
import org.keycloak.representations.idm.ApplicationRepresentation;
|
||||||
import org.keycloak.services.managers.RealmManager;
|
import org.keycloak.services.managers.RealmManager;
|
||||||
import org.keycloak.services.managers.ResourceManager;
|
import org.keycloak.services.managers.ResourceManager;
|
||||||
import org.keycloak.services.models.RealmModel;
|
|
||||||
import org.keycloak.services.models.ApplicationModel;
|
import org.keycloak.services.models.ApplicationModel;
|
||||||
|
import org.keycloak.services.models.KeycloakSession;
|
||||||
|
import org.keycloak.services.models.RealmModel;
|
||||||
import org.keycloak.services.models.UserModel;
|
import org.keycloak.services.models.UserModel;
|
||||||
import org.keycloak.services.resources.Transaction;
|
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.*;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.container.ResourceContext;
|
||||||
import javax.ws.rs.NotFoundException;
|
|
||||||
import javax.ws.rs.POST;
|
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.PathParam;
|
|
||||||
import javax.ws.rs.Produces;
|
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
|
@ -33,6 +28,12 @@ public class ApplicationsResource {
|
||||||
protected UserModel admin;
|
protected UserModel admin;
|
||||||
protected RealmModel realm;
|
protected RealmModel realm;
|
||||||
|
|
||||||
|
@Context
|
||||||
|
protected ResourceContext resourceContext;
|
||||||
|
|
||||||
|
@Context
|
||||||
|
protected KeycloakSession session;
|
||||||
|
|
||||||
public ApplicationsResource(UserModel admin, RealmModel realm) {
|
public ApplicationsResource(UserModel admin, RealmModel realm) {
|
||||||
this.admin = admin;
|
this.admin = admin;
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
|
@ -42,46 +43,32 @@ public class ApplicationsResource {
|
||||||
@Produces(MediaType.APPLICATION_JSON)
|
@Produces(MediaType.APPLICATION_JSON)
|
||||||
@NoCache
|
@NoCache
|
||||||
public List<ApplicationRepresentation> getResources() {
|
public List<ApplicationRepresentation> getResources() {
|
||||||
return new Transaction<List<ApplicationRepresentation>>() {
|
List<ApplicationRepresentation> rep = new ArrayList<ApplicationRepresentation>();
|
||||||
@Override
|
List<ApplicationModel> applicationModels = realm.getApplications();
|
||||||
protected List<ApplicationRepresentation> callImpl() {
|
ResourceManager resourceManager = new ResourceManager(new RealmManager(session));
|
||||||
List<ApplicationRepresentation> rep = new ArrayList<ApplicationRepresentation>();
|
for (ApplicationModel applicationModel : applicationModels) {
|
||||||
List<ApplicationModel> applicationModels = realm.getApplications();
|
rep.add(resourceManager.toRepresentation(applicationModel));
|
||||||
ResourceManager resourceManager = new ResourceManager(new RealmManager(session));
|
}
|
||||||
for (ApplicationModel applicationModel : applicationModels) {
|
return rep;
|
||||||
rep.add(resourceManager.toRepresentation(applicationModel));
|
|
||||||
}
|
|
||||||
return rep;
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@POST
|
@POST
|
||||||
@Consumes(MediaType.APPLICATION_JSON)
|
@Consumes(MediaType.APPLICATION_JSON)
|
||||||
public Response createResource(final @Context UriInfo uriInfo, final ApplicationRepresentation rep) {
|
public Response createResource(final @Context UriInfo uriInfo, final ApplicationRepresentation rep) {
|
||||||
return new Transaction<Response>() {
|
ResourceManager resourceManager = new ResourceManager(new RealmManager(session));
|
||||||
@Override
|
ApplicationModel applicationModel = resourceManager.createResource(realm, rep);
|
||||||
protected Response callImpl() {
|
return Response.created(uriInfo.getAbsolutePathBuilder().path(applicationModel.getId()).build()).build();
|
||||||
ResourceManager resourceManager = new ResourceManager(new RealmManager(session));
|
|
||||||
ApplicationModel applicationModel = resourceManager.createResource(realm, rep);
|
|
||||||
return Response.created(uriInfo.getAbsolutePathBuilder().path(applicationModel.getId()).build()).build();
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("{id}")
|
@Path("{id}")
|
||||||
public ApplicationResource getResource(final @PathParam("id") String id) {
|
public ApplicationResource getResource(final @PathParam("id") String id) {
|
||||||
return new Transaction<ApplicationResource>(false) {
|
ApplicationModel applicationModel = realm.getApplicationById(id);
|
||||||
@Override
|
if (applicationModel == null) {
|
||||||
protected ApplicationResource callImpl() {
|
throw new NotFoundException();
|
||||||
ApplicationModel applicationModel = realm.getApplicationById(id);
|
}
|
||||||
if (applicationModel == null) {
|
ApplicationResource applicationResource = new ApplicationResource(admin, realm, applicationModel);
|
||||||
throw new NotFoundException();
|
resourceContext.initResource(applicationResource);
|
||||||
}
|
return applicationResource;
|
||||||
return new ApplicationResource(admin, realm, applicationModel);
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,20 +6,13 @@ import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
import org.keycloak.representations.idm.RoleRepresentation;
|
import org.keycloak.representations.idm.RoleRepresentation;
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
import org.keycloak.services.managers.RealmManager;
|
import org.keycloak.services.managers.RealmManager;
|
||||||
|
import org.keycloak.services.models.KeycloakSession;
|
||||||
import org.keycloak.services.models.RealmModel;
|
import org.keycloak.services.models.RealmModel;
|
||||||
import org.keycloak.services.models.RoleModel;
|
import org.keycloak.services.models.RoleModel;
|
||||||
import org.keycloak.services.models.UserModel;
|
import org.keycloak.services.models.UserModel;
|
||||||
import org.keycloak.services.resources.Transaction;
|
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.*;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.container.ResourceContext;
|
||||||
import javax.ws.rs.InternalServerErrorException;
|
|
||||||
import javax.ws.rs.NotFoundException;
|
|
||||||
import javax.ws.rs.POST;
|
|
||||||
import javax.ws.rs.PUT;
|
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.PathParam;
|
|
||||||
import javax.ws.rs.Produces;
|
|
||||||
import javax.ws.rs.core.Context;
|
import javax.ws.rs.core.Context;
|
||||||
import javax.ws.rs.core.Response;
|
import javax.ws.rs.core.Response;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
@ -35,6 +28,12 @@ public class RealmAdminResource {
|
||||||
protected UserModel admin;
|
protected UserModel admin;
|
||||||
protected RealmModel realm;
|
protected RealmModel realm;
|
||||||
|
|
||||||
|
@Context
|
||||||
|
protected ResourceContext resourceContext;
|
||||||
|
|
||||||
|
@Context
|
||||||
|
protected KeycloakSession session;
|
||||||
|
|
||||||
public RealmAdminResource(UserModel admin, RealmModel realm) {
|
public RealmAdminResource(UserModel admin, RealmModel realm) {
|
||||||
this.admin = admin;
|
this.admin = admin;
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
|
@ -42,19 +41,16 @@ public class RealmAdminResource {
|
||||||
|
|
||||||
@Path("applications")
|
@Path("applications")
|
||||||
public ApplicationsResource getResources() {
|
public ApplicationsResource getResources() {
|
||||||
return new ApplicationsResource(admin, realm);
|
ApplicationsResource applicationsResource = new ApplicationsResource(admin, realm);
|
||||||
|
resourceContext.initResource(applicationsResource);
|
||||||
|
return applicationsResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@NoCache
|
@NoCache
|
||||||
@Produces("application/json")
|
@Produces("application/json")
|
||||||
public RealmRepresentation getRealm() {
|
public RealmRepresentation getRealm() {
|
||||||
return new Transaction<RealmRepresentation>() {
|
return new RealmManager(session).toRepresentation(realm);
|
||||||
@Override
|
|
||||||
protected RealmRepresentation callImpl() {
|
|
||||||
return new RealmManager(session).toRepresentation(realm);
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -63,31 +59,20 @@ public class RealmAdminResource {
|
||||||
@NoCache
|
@NoCache
|
||||||
@Produces("application/json")
|
@Produces("application/json")
|
||||||
public List<RoleRepresentation> getRoles() {
|
public List<RoleRepresentation> getRoles() {
|
||||||
return new Transaction<List<RoleRepresentation>>() {
|
List<RoleModel> roleModels = realm.getRoles();
|
||||||
@Override
|
List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
|
||||||
protected List<RoleRepresentation> callImpl() {
|
for (RoleModel roleModel : roleModels) {
|
||||||
List<RoleModel> roleModels = realm.getRoles();
|
RoleRepresentation role = new RoleRepresentation(roleModel.getName(), roleModel.getDescription());
|
||||||
List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
|
roles.add(role);
|
||||||
for (RoleModel roleModel : roleModels) {
|
}
|
||||||
RoleRepresentation role = new RoleRepresentation(roleModel.getName(), roleModel.getDescription());
|
return roles;
|
||||||
roles.add(role);
|
|
||||||
}
|
|
||||||
return roles;
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@PUT
|
@PUT
|
||||||
@Consumes("application/json")
|
@Consumes("application/json")
|
||||||
public void updateRealm(final RealmRepresentation rep) {
|
public void updateRealm(final RealmRepresentation rep) {
|
||||||
new Transaction() {
|
logger.info("updating realm: " + rep.getRealm());
|
||||||
@Override
|
new RealmManager(session).updateRealm(rep, realm);
|
||||||
protected void runImpl() {
|
|
||||||
logger.info("updating realm: " + rep.getRealm());
|
|
||||||
new RealmManager(session).updateRealm(rep, realm);
|
|
||||||
}
|
|
||||||
}.run();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("roles/{id}")
|
@Path("roles/{id}")
|
||||||
|
@ -95,18 +80,13 @@ public class RealmAdminResource {
|
||||||
@NoCache
|
@NoCache
|
||||||
@Produces("application/json")
|
@Produces("application/json")
|
||||||
public RoleRepresentation getRole(final @PathParam("id") String id) {
|
public RoleRepresentation getRole(final @PathParam("id") String id) {
|
||||||
return new Transaction<RoleRepresentation>() {
|
RoleModel roleModel = realm.getRoleById(id);
|
||||||
@Override
|
if (roleModel == null) {
|
||||||
protected RoleRepresentation callImpl() {
|
throw new NotFoundException();
|
||||||
RoleModel roleModel = realm.getRoleById(id);
|
}
|
||||||
if (roleModel == null) {
|
RoleRepresentation rep = new RoleRepresentation(roleModel.getName(), roleModel.getDescription());
|
||||||
throw new NotFoundException();
|
rep.setId(roleModel.getId());
|
||||||
}
|
return rep;
|
||||||
RoleRepresentation rep = new RoleRepresentation(roleModel.getName(), roleModel.getDescription());
|
|
||||||
rep.setId(roleModel.getId());
|
|
||||||
return rep;
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -114,39 +94,27 @@ public class RealmAdminResource {
|
||||||
@PUT
|
@PUT
|
||||||
@Consumes("application/json")
|
@Consumes("application/json")
|
||||||
public void updateRole(final @PathParam("id") String id, final RoleRepresentation rep) {
|
public void updateRole(final @PathParam("id") String id, final RoleRepresentation rep) {
|
||||||
new Transaction() {
|
RoleModel role = realm.getRoleById(id);
|
||||||
@Override
|
if (role == null) {
|
||||||
protected void runImpl() {
|
throw new NotFoundException();
|
||||||
RoleModel role = realm.getRoleById(id);
|
}
|
||||||
if (role == null) {
|
role.setName(rep.getName());
|
||||||
throw new NotFoundException();
|
role.setDescription(rep.getDescription());
|
||||||
}
|
|
||||||
role.setName(rep.getName());
|
|
||||||
role.setDescription(rep.getDescription());
|
|
||||||
}
|
|
||||||
}.run();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("roles")
|
@Path("roles")
|
||||||
@POST
|
@POST
|
||||||
@Consumes("application/json")
|
@Consumes("application/json")
|
||||||
public Response createRole(final @Context UriInfo uriInfo, final RoleRepresentation rep) {
|
public Response createRole(final @Context UriInfo uriInfo, final RoleRepresentation rep) {
|
||||||
return new Transaction<Response>() {
|
if (realm.getRole(rep.getName()) != null) {
|
||||||
@Override
|
throw new InternalServerErrorException(); // todo appropriate status here.
|
||||||
protected Response callImpl() {
|
}
|
||||||
if (realm.getRole(rep.getName()) != null) {
|
RoleModel role = realm.addRole(rep.getName());
|
||||||
throw new InternalServerErrorException(); // todo appropriate status here.
|
if (role == null) {
|
||||||
}
|
throw new NotFoundException();
|
||||||
RoleModel role = realm.addRole(rep.getName());
|
}
|
||||||
if (role == null) {
|
role.setDescription(rep.getDescription());
|
||||||
throw new NotFoundException();
|
return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getId()).build()).build();
|
||||||
}
|
|
||||||
role.setDescription(rep.getDescription());
|
|
||||||
return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getId()).build()).build();
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,34 +4,17 @@ import org.jboss.resteasy.annotations.cache.NoCache;
|
||||||
import org.jboss.resteasy.logging.Logger;
|
import org.jboss.resteasy.logging.Logger;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
import org.keycloak.services.managers.RealmManager;
|
import org.keycloak.services.managers.RealmManager;
|
||||||
|
import org.keycloak.services.models.KeycloakSession;
|
||||||
import org.keycloak.services.models.RealmModel;
|
import org.keycloak.services.models.RealmModel;
|
||||||
import org.keycloak.services.models.UserModel;
|
import org.keycloak.services.models.UserModel;
|
||||||
import org.keycloak.services.resources.PublicRealmResource;
|
|
||||||
import org.keycloak.services.resources.SaasService;
|
import org.keycloak.services.resources.SaasService;
|
||||||
import org.keycloak.services.resources.Transaction;
|
|
||||||
|
|
||||||
import javax.ws.rs.Consumes;
|
import javax.ws.rs.*;
|
||||||
import javax.ws.rs.ForbiddenException;
|
import javax.ws.rs.container.ResourceContext;
|
||||||
import javax.ws.rs.GET;
|
import javax.ws.rs.core.*;
|
||||||
import javax.ws.rs.NotAuthorizedException;
|
|
||||||
import javax.ws.rs.NotFoundException;
|
|
||||||
import javax.ws.rs.POST;
|
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.PathParam;
|
|
||||||
import javax.ws.rs.Produces;
|
|
||||||
import javax.ws.rs.core.CacheControl;
|
|
||||||
import javax.ws.rs.core.Context;
|
|
||||||
import javax.ws.rs.core.GenericEntity;
|
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
|
||||||
import javax.ws.rs.core.MediaType;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import javax.ws.rs.core.UriBuilder;
|
|
||||||
import javax.ws.rs.core.UriInfo;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -50,23 +33,24 @@ public class RealmsAdminResource {
|
||||||
noCache.setNoCache(true);
|
noCache.setNoCache(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Context
|
||||||
|
protected ResourceContext resourceContext;
|
||||||
|
|
||||||
|
@Context
|
||||||
|
protected KeycloakSession session;
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@NoCache
|
@NoCache
|
||||||
@Produces("application/json")
|
@Produces("application/json")
|
||||||
public List<RealmRepresentation> getRealms() {
|
public List<RealmRepresentation> getRealms() {
|
||||||
return new Transaction<List<RealmRepresentation>>() {
|
logger.info(("getRealms()"));
|
||||||
@Override
|
RealmManager realmManager = new RealmManager(session);
|
||||||
protected List<RealmRepresentation> callImpl() {
|
List<RealmModel> realms = session.getRealms(admin);
|
||||||
logger.info(("getRealms()"));
|
List<RealmRepresentation> reps = new ArrayList<RealmRepresentation>();
|
||||||
RealmManager realmManager = new RealmManager(session);
|
for (RealmModel realm : realms) {
|
||||||
List<RealmModel> realms = session.getRealms(admin);
|
reps.add(realmManager.toRepresentation(realm));
|
||||||
List<RealmRepresentation> reps = new ArrayList<RealmRepresentation>();
|
}
|
||||||
for (RealmModel realm : realms) {
|
return reps;
|
||||||
reps.add(realmManager.toRepresentation(realm));
|
|
||||||
}
|
|
||||||
return reps;
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static UriBuilder realmUrl(UriInfo uriInfo) {
|
public static UriBuilder realmUrl(UriInfo uriInfo) {
|
||||||
|
@ -81,34 +65,26 @@ public class RealmsAdminResource {
|
||||||
@Consumes("application/json")
|
@Consumes("application/json")
|
||||||
public Response importRealm(@Context final UriInfo uriInfo, final RealmRepresentation rep) {
|
public Response importRealm(@Context final UriInfo uriInfo, final RealmRepresentation rep) {
|
||||||
logger.info("importRealm: " + rep.getRealm());
|
logger.info("importRealm: " + rep.getRealm());
|
||||||
return new Transaction<Response>() {
|
RealmManager realmManager = new RealmManager(session);
|
||||||
@Override
|
RealmModel realm = realmManager.importRealm(rep, admin);
|
||||||
protected Response callImpl() {
|
URI location = realmUrl(uriInfo).build(realm.getId());
|
||||||
RealmManager realmManager = new RealmManager(session);
|
logger.info("imported realm success, sending back: " + location.toString());
|
||||||
RealmModel realm = realmManager.importRealm(rep, admin);
|
return Response.created(location).build();
|
||||||
URI location = realmUrl(uriInfo).build(realm.getId());
|
|
||||||
logger.info("imported realm success, sending back: " + location.toString());
|
|
||||||
return Response.created(location).build();
|
|
||||||
}
|
|
||||||
}.call();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Path("{id}")
|
@Path("{id}")
|
||||||
public RealmAdminResource getRealmAdmin(@Context final HttpHeaders headers,
|
public RealmAdminResource getRealmAdmin(@Context final HttpHeaders headers,
|
||||||
@PathParam("id") final String id) {
|
@PathParam("id") final String id) {
|
||||||
return new Transaction<RealmAdminResource>(false) {
|
RealmManager realmManager = new RealmManager(session);
|
||||||
@Override
|
RealmModel realm = realmManager.getRealm(id);
|
||||||
protected RealmAdminResource callImpl() {
|
if (realm == null) throw new NotFoundException();
|
||||||
RealmManager realmManager = new RealmManager(session);
|
if (!realm.isRealmAdmin(admin)) {
|
||||||
RealmModel realm = realmManager.getRealm(id);
|
throw new ForbiddenException();
|
||||||
if (realm == null) throw new NotFoundException();
|
}
|
||||||
if (!realm.isRealmAdmin(admin)) {
|
|
||||||
throw new ForbiddenException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return new RealmAdminResource(admin, realm);
|
RealmAdminResource adminResource = new RealmAdminResource(admin, realm);
|
||||||
}
|
resourceContext.initResource(adminResource);
|
||||||
}.call();
|
return adminResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
4
services/src/main/java/org/keycloak/services/resources/flows/Flows.java
Normal file → Executable file
4
services/src/main/java/org/keycloak/services/resources/flows/Flows.java
Normal file → Executable file
|
@ -21,13 +21,13 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.services.resources.flows;
|
package org.keycloak.services.resources.flows;
|
||||||
|
|
||||||
import javax.ws.rs.core.UriInfo;
|
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.jboss.resteasy.spi.HttpRequest;
|
||||||
import org.keycloak.services.managers.AuthenticationManager;
|
import org.keycloak.services.managers.AuthenticationManager;
|
||||||
import org.keycloak.services.managers.TokenManager;
|
import org.keycloak.services.managers.TokenManager;
|
||||||
import org.keycloak.services.models.RealmModel;
|
import org.keycloak.services.models.RealmModel;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
|
|
6
services/src/main/java/org/keycloak/services/resources/flows/FormFlows.java
Normal file → Executable file
6
services/src/main/java/org/keycloak/services/resources/flows/FormFlows.java
Normal file → Executable file
|
@ -21,14 +21,14 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.services.resources.flows;
|
package org.keycloak.services.resources.flows;
|
||||||
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
|
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.jboss.resteasy.spi.HttpRequest;
|
||||||
import org.keycloak.services.models.RealmModel;
|
import org.keycloak.services.models.RealmModel;
|
||||||
import org.keycloak.services.models.UserModel;
|
import org.keycloak.services.models.UserModel;
|
||||||
import org.picketlink.idm.model.sample.Realm;
|
import org.picketlink.idm.model.sample.Realm;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
|
|
8
services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java
Normal file → Executable file
8
services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java
Normal file → Executable file
|
@ -21,10 +21,6 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.services.resources.flows;
|
package org.keycloak.services.resources.flows;
|
||||||
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
import javax.ws.rs.core.UriBuilder;
|
|
||||||
import javax.ws.rs.core.UriInfo;
|
|
||||||
|
|
||||||
import org.jboss.resteasy.logging.Logger;
|
import org.jboss.resteasy.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.jboss.resteasy.spi.HttpRequest;
|
||||||
import org.keycloak.services.managers.AccessCodeEntry;
|
import org.keycloak.services.managers.AccessCodeEntry;
|
||||||
|
@ -36,6 +32,10 @@ import org.keycloak.services.models.RoleModel;
|
||||||
import org.keycloak.services.models.UserModel;
|
import org.keycloak.services.models.UserModel;
|
||||||
import org.keycloak.services.resources.TokenService;
|
import org.keycloak.services.resources.TokenService;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
import javax.ws.rs.core.UriBuilder;
|
||||||
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
|
|
4
services/src/main/java/org/keycloak/services/resources/flows/PageFlows.java
Normal file → Executable file
4
services/src/main/java/org/keycloak/services/resources/flows/PageFlows.java
Normal file → Executable file
|
@ -21,12 +21,12 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.services.resources.flows;
|
package org.keycloak.services.resources.flows;
|
||||||
|
|
||||||
import javax.ws.rs.core.Response;
|
|
||||||
|
|
||||||
import org.jboss.resteasy.logging.Logger;
|
import org.jboss.resteasy.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.HttpRequest;
|
import org.jboss.resteasy.spi.HttpRequest;
|
||||||
import org.keycloak.services.JspRequestParameters;
|
import org.keycloak.services.JspRequestParameters;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.Response;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
|
|
9
services/src/main/java/org/keycloak/services/resources/flows/Urls.java
Normal file → Executable file
9
services/src/main/java/org/keycloak/services/resources/flows/Urls.java
Normal file → Executable file
|
@ -21,15 +21,10 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.services.resources.flows;
|
package org.keycloak.services.resources.flows;
|
||||||
|
|
||||||
import java.net.URI;
|
import org.keycloak.services.resources.*;
|
||||||
|
|
||||||
import javax.ws.rs.core.UriBuilder;
|
import javax.ws.rs.core.UriBuilder;
|
||||||
|
import java.net.URI;
|
||||||
import org.keycloak.services.resources.AccountService;
|
|
||||||
import org.keycloak.services.resources.RealmsResource;
|
|
||||||
import org.keycloak.services.resources.SaasService;
|
|
||||||
import org.keycloak.services.resources.SocialResource;
|
|
||||||
import org.keycloak.services.resources.TokenService;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
|
|
7
services/src/main/java/org/keycloak/services/validation/Validation.java
Normal file → Executable file
7
services/src/main/java/org/keycloak/services/validation/Validation.java
Normal file → Executable file
|
@ -1,12 +1,11 @@
|
||||||
package org.keycloak.services.validation;
|
package org.keycloak.services.validation;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
|
||||||
|
|
||||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
import org.keycloak.services.messages.Messages;
|
import org.keycloak.services.messages.Messages;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class Validation {
|
public class Validation {
|
||||||
|
|
||||||
public static String validateRegistrationForm(MultivaluedMap<String, String> formData, List<String> requiredCredentialTypes) {
|
public static String validateRegistrationForm(MultivaluedMap<String, String> formData, List<String> requiredCredentialTypes) {
|
||||||
|
|
70
services/src/test/java/org/keycloak/test/AbstractKeycloakServerTest.java
Executable file
70
services/src/test/java/org/keycloak/test/AbstractKeycloakServerTest.java
Executable file
|
@ -0,0 +1,70 @@
|
||||||
|
package org.keycloak.test;
|
||||||
|
|
||||||
|
import io.undertow.servlet.Servlets;
|
||||||
|
import io.undertow.servlet.api.DeploymentInfo;
|
||||||
|
import io.undertow.servlet.api.FilterInfo;
|
||||||
|
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||||
|
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||||
|
import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer;
|
||||||
|
import org.jboss.resteasy.spi.ResteasyDeployment;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.keycloak.SkeletonKeyContextResolver;
|
||||||
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
|
import org.keycloak.services.filters.KeycloakSessionServletFilter;
|
||||||
|
import org.keycloak.services.resources.KeycloakApplication;
|
||||||
|
|
||||||
|
import javax.servlet.DispatcherType;
|
||||||
|
import javax.ws.rs.client.Client;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class AbstractKeycloakServerTest {
|
||||||
|
public static UndertowJaxrsServer server;
|
||||||
|
public static ResteasyDeployment deployment;
|
||||||
|
public static Client client;
|
||||||
|
public static KeycloakApplication application;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void undertowSetup() throws Exception {
|
||||||
|
deployment = new ResteasyDeployment();
|
||||||
|
deployment.setApplicationClass(KeycloakApplication.class.getName());
|
||||||
|
server = new UndertowJaxrsServer().start();
|
||||||
|
DeploymentInfo di = server.undertowDeployment(deployment);
|
||||||
|
di.setClassLoader(AbstractKeycloakServerTest.class.getClassLoader());
|
||||||
|
di.setContextPath("/");
|
||||||
|
di.setDeploymentName("Keycloak");
|
||||||
|
|
||||||
|
FilterInfo filter = Servlets.filter("SessionFilter", KeycloakSessionServletFilter.class);
|
||||||
|
di.addFilter(filter);
|
||||||
|
di.addFilterUrlMapping("SessionFilter", "/*", DispatcherType.REQUEST);
|
||||||
|
server.deploy(di);
|
||||||
|
application = (KeycloakApplication) deployment.getApplication();
|
||||||
|
client = new ResteasyClientBuilder().connectionPoolSize(10).build();
|
||||||
|
client.register(SkeletonKeyContextResolver.class);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void undertowShutdown() throws Exception {
|
||||||
|
server.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RealmRepresentation loadJson(String path) throws IOException {
|
||||||
|
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
int c;
|
||||||
|
while ((c = is.read()) != -1) {
|
||||||
|
os.write(c);
|
||||||
|
}
|
||||||
|
byte[] bytes = os.toByteArray();
|
||||||
|
System.out.println(new String(bytes));
|
||||||
|
|
||||||
|
return JsonSerialization.fromBytes(RealmRepresentation.class, bytes);
|
||||||
|
}
|
||||||
|
}
|
|
@ -66,7 +66,7 @@ public class ImportTest {
|
||||||
UserModel admin = defaultRealm.addUser("admin");
|
UserModel admin = defaultRealm.addUser("admin");
|
||||||
defaultRealm.grantRole(admin, role);
|
defaultRealm.grantRole(admin, role);
|
||||||
|
|
||||||
RealmRepresentation rep = KeycloakTestBase.loadJson("testrealm.json");
|
RealmRepresentation rep = AbstractKeycloakServerTest.loadJson("testrealm.json");
|
||||||
RealmModel realm = manager.createRealm("demo", rep.getRealm());
|
RealmModel realm = manager.createRealm("demo", rep.getRealm());
|
||||||
manager.importRealm(rep, realm);
|
manager.importRealm(rep, realm);
|
||||||
realm.addRealmAdmin(admin);
|
realm.addRealmAdmin(admin);
|
||||||
|
@ -141,7 +141,7 @@ public class ImportTest {
|
||||||
UserModel admin = defaultRealm.addUser("admin");
|
UserModel admin = defaultRealm.addUser("admin");
|
||||||
defaultRealm.grantRole(admin, role);
|
defaultRealm.grantRole(admin, role);
|
||||||
|
|
||||||
RealmRepresentation rep = KeycloakTestBase.loadJson("testrealm-demo.json");
|
RealmRepresentation rep = AbstractKeycloakServerTest.loadJson("testrealm-demo.json");
|
||||||
RealmModel realm = manager.createRealm("demo", rep.getRealm());
|
RealmModel realm = manager.createRealm("demo", rep.getRealm());
|
||||||
manager.importRealm(rep, realm);
|
manager.importRealm(rep, realm);
|
||||||
realm.addRealmAdmin(admin);
|
realm.addRealmAdmin(admin);
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
package org.keycloak.test;
|
|
||||||
|
|
||||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
|
||||||
import org.jboss.resteasy.test.BaseResourceTest;
|
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
public class KeycloakTestBase extends BaseResourceTest
|
|
||||||
{
|
|
||||||
public static RealmRepresentation loadJson(String path) throws IOException
|
|
||||||
{
|
|
||||||
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
|
|
||||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
|
||||||
int c;
|
|
||||||
while ( (c = is.read()) != -1)
|
|
||||||
{
|
|
||||||
os.write(c);
|
|
||||||
}
|
|
||||||
byte[] bytes = os.toByteArray();
|
|
||||||
System.out.println(new String(bytes));
|
|
||||||
|
|
||||||
return JsonSerialization.fromBytes(RealmRepresentation.class, bytes);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,12 +1,8 @@
|
||||||
package org.keycloak.test;
|
package org.keycloak.test;
|
||||||
|
|
||||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
|
||||||
import org.jboss.resteasy.spi.ResteasyDeployment;
|
|
||||||
import org.jboss.resteasy.test.EmbeddedContainer;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.SkeletonKeyContextResolver;
|
|
||||||
import org.keycloak.representations.AccessTokenResponse;
|
import org.keycloak.representations.AccessTokenResponse;
|
||||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
|
@ -15,10 +11,8 @@ import org.keycloak.services.managers.AuthenticationManager;
|
||||||
import org.keycloak.services.managers.RealmManager;
|
import org.keycloak.services.managers.RealmManager;
|
||||||
import org.keycloak.services.models.KeycloakSession;
|
import org.keycloak.services.models.KeycloakSession;
|
||||||
import org.keycloak.services.models.RealmModel;
|
import org.keycloak.services.models.RealmModel;
|
||||||
import org.keycloak.services.resources.KeycloakApplication;
|
|
||||||
|
|
||||||
import javax.ws.rs.NotAuthorizedException;
|
import javax.ws.rs.NotAuthorizedException;
|
||||||
import javax.ws.rs.client.Client;
|
|
||||||
import javax.ws.rs.client.Entity;
|
import javax.ws.rs.client.Entity;
|
||||||
import javax.ws.rs.client.WebTarget;
|
import javax.ws.rs.client.WebTarget;
|
||||||
import javax.ws.rs.core.Form;
|
import javax.ws.rs.core.Form;
|
||||||
|
@ -31,30 +25,16 @@ import static org.jboss.resteasy.test.TestPortProvider.generateURL;
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class RealmCreationTest {
|
public class RealmCreationTest extends AbstractKeycloakServerTest {
|
||||||
|
|
||||||
private static ResteasyDeployment deployment;
|
|
||||||
private static Client client;
|
|
||||||
|
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void before() throws Exception {
|
public static void before() throws Exception {
|
||||||
deployment = new ResteasyDeployment();
|
|
||||||
deployment.setApplicationClass(KeycloakApplication.class.getName());
|
|
||||||
EmbeddedContainer.start(deployment);
|
|
||||||
KeycloakApplication application = (KeycloakApplication) deployment.getApplication();
|
|
||||||
KeycloakSession session = application.getFactory().createSession();
|
KeycloakSession session = application.getFactory().createSession();
|
||||||
session.getTransaction().begin();
|
session.getTransaction().begin();
|
||||||
RealmManager manager = new RealmManager(session);
|
RealmManager manager = new RealmManager(session);
|
||||||
new InstallationManager().install(manager);
|
new InstallationManager().install(manager);
|
||||||
session.getTransaction().commit();
|
session.getTransaction().commit();
|
||||||
session.close();
|
session.close();
|
||||||
client = new ResteasyClientBuilder().build();
|
|
||||||
client.register(SkeletonKeyContextResolver.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void after() throws Exception {
|
|
||||||
client.close();
|
|
||||||
EmbeddedContainer.stop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -86,7 +66,7 @@ public class RealmCreationTest {
|
||||||
System.out.println(tokenResponse.getToken());
|
System.out.println(tokenResponse.getToken());
|
||||||
//
|
//
|
||||||
|
|
||||||
RealmRepresentation realm = KeycloakTestBase.loadJson("testrealm.json");
|
RealmRepresentation realm = loadJson("testrealm.json");
|
||||||
response = target.path("saas/admin/realms").request().header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenResponse.getToken()).post(Entity.json(realm));
|
response = target.path("saas/admin/realms").request().header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenResponse.getToken()).post(Entity.json(realm));
|
||||||
Assert.assertEquals(201, response.getStatus());
|
Assert.assertEquals(201, response.getStatus());
|
||||||
response.close();
|
response.close();
|
||||||
|
|
Loading…
Reference in a new issue