added changes for 7

This commit is contained in:
Matthew Helmke 2019-01-15 08:08:19 -06:00 committed by Stian Thorgersen
parent cb1b73930f
commit f9cb6f1c6b
10 changed files with 20 additions and 22 deletions

View file

@ -1,7 +1,7 @@
[[_user-storage-spi]]
== User Storage SPI
You can use the User Storage SPI to write extensions to {project_name} to connect to external user databases and credential stores. The built-in LDAP and ActiveDirectory support is an implementation of this SPI in action. Out of the box, {project_name} uses its local database to create, update, and look up users and validation credentials. Often though, organizations have existing external proprietary user databases that they cannot migrate to {project_name}'s data model. For those situations, application developers can write implementations of the User Storage SPI to bridge the external user store and the internal user object model that {project_name} uses to log in users and manage them.
You can use the User Storage SPI to write extensions to {project_name} to connect to external user databases and credential stores. The built-in LDAP and ActiveDirectory support is an implementation of this SPI in action. Out of the box, {project_name} uses its local database to create, update, and look up users and validate credentials. Often though, organizations have existing external proprietary user databases that they cannot migrate to {project_name}'s data model. For those situations, application developers can write implementations of the User Storage SPI to bridge the external user store and the internal user object model that {project_name} uses to log in users and manage them.
When the {project_name} runtime needs to look up a user, such as when a user is logging in, it performs a number of steps to locate the user. It first looks to see if the user is in the user cache; if the user is found it uses that in-memory representation. Then it looks for the user within the {project_name} local database. If the user is not found, it then loops through User Storage SPI provider implementations to perform the user query until one of them returns the user the runtime is looking for. The provider queries the external user store for the user and maps the external data representation of the user to {project_name}'s user metamodel.

View file

@ -1,7 +1,7 @@
=== Augmenting External Storage
The `PropertyProfileUserStorageProvider` example is really limited. While we will be able to login with users stored
The `PropertyFileUserStorageProvider` example is really limited. While we will be able to login with users stored
in a property file, we won't be able to do much else. If users loaded by this provider need special role or group
mappings to fully access particular applications there is no way for us to add additional role mappings to these users.
You also can't modify or add additional important attributes like email, first and last name.

View file

@ -1,9 +1,9 @@
=== User Caches
When a user is loaded by ID, username, or email queries it is cached. When a user is cached, it iterates through
When a user object is loaded by ID, username, or email queries it is cached. When a user object is bing cached, it iterates through
the entire `UserModel` interface and pulls this information to a local in-memory-only cache. In a cluster, this cache
is still local, but it becomes an invalidation cache. When a user is modified, it is evicted. This eviction event
is still local, but it becomes an invalidation cache. When a user object is modified, it is evicted. This eviction event
is propagated to the entire cluster so that the other nodes' user cache is also invalidated.
==== Managing the user cache

View file

@ -1,7 +1,7 @@
=== Configuration Techniques
Our `PropertyFileUserStorageProvider` example is bit contrived. It is hardcoded to a property file that is embedded in the jar of the provider. Not very useful at all. We might want to make the location of this file configurable per instance of the provider. In other words, we might want to reuse this provider mulitple times in multiple different realms and point to completely different user property files. We'll also want to perform this configuration within the administration console UI.
Our `PropertyFileUserStorageProvider` example is bit contrived. It is hardcoded to a property file that is embedded in the jar of the provider, which is not terribly useful. We might want to make the location of this file configurable per instance of the provider. In other words, we might want to reuse this provider mulitple times in multiple different realms and point to completely different user property files. We'll also want to perform this configuration within the administration console UI.
The `UserStorageProviderFactory` has additional methods you can implement that handle provider configuration. You describe the variables you want to configure per provider and the administration console automatically renders a generic input page to gather this configuration. When implemented, callback methods also validate the configuration before it is saved, when a provider is created for the first time, and when it is updated. `UserStorageProviderFactory` inherits these methods from the `org.keycloak.component.ComponentFactory` interface.

View file

@ -16,7 +16,7 @@ There are some obvious disadvantages though to using an import strategy:
* Looking up a user for the first time will require multiple updates to {project_name} database. This can
be a big performance loss under load and put a lot of strain on the {project_name} database. The user federated
storage approach will only store extra data as needed and may never be used depending on the capabilities of your external store.
* With the import approach, you have to keep local keycloak storage and external storage in sync. The User Storage SPI
* With the import approach, you have to keep local {project_name} storage and external storage in sync. The User Storage SPI
has capability interfaces that you can implement to support synchronization, but this can quickly become painful and messy.
To implement the import strategy you simply check to see first if the user has been imported locally. If so return the
@ -51,7 +51,7 @@ begin first by modifying the `createAdapter()` method.
In this method we call the `KeycloakSession.userLocalStorage()` method to obtain a reference to local {project_name}
user storage. We see if the user is stored locally, if not, we add it locally. Do not set the `id` of the local user.
Let {project_name} set auto generate the `id`. Also note that we call
Let {project_name} automatically generate the `id`. Also note that we call
`UserModel.setFederationLink()` and pass in the ID of the `ComponentModel` of our provider. This sets a link between
the provider and the imported user.

View file

@ -53,7 +53,7 @@ not proxy the user correctly and your provider won't work.
You must put the `@Remove` annotation on the `close()` method of your provider. If you do not, the stateful bean
will never be cleaned up and you might eventually see error messages.
Implementations of `UserStorageProviderFactory` are required to be plain java objects. Your factory class would
Implementations of `UserStorageProvider` are required to be plain Java objects. Your factory class would
perform a JNDI lookup of the Stateful EJB in its create() method.
[source,java]
@ -81,9 +81,7 @@ file as well as any JPA `@Entity` classes.
WARNING: When using JPA any additional datasource must be an XA datasource. The {project_name} datasource
is not an XA datasource. If you interact with two or more non-XA datasources in the same transaction, the server returns
an error message. Only one non-XA resource is permitted in a single transaction.
See the {appserver_name} manual for more details on deploying an XA datasource.
an error message. Only one non-XA resource is permitted in a single transaction. See the {appserver_name} manual for more details on deploying an XA datasource.
CDI is not supported.

View file

@ -4,7 +4,7 @@
NOTE: This chapter is only applicable if you have implemented a provider using the earlier (and now removed)
User Federation SPI.
In Keycloak version 2.4.0 and earlier there was a User Federation SPI. Red Hat Single Sign-On version 7.0, although unsupported, also had
In Keycloak version 2.4.0 and earlier there was a User Federation SPI. Red Hat Single Sign-On version 7.0, although unsupported, had
this earlier SPI available as well. This earlier User Federation SPI has been removed from Keycloak version 2.5.0 and Red Hat Single Sign-On version 7.1.
However, if you have written a provider with this earlier SPI, this chapter discusses some strategies you can use to port it.
@ -28,7 +28,7 @@ There are some obvious disadvantages though to using an import strategy:
* Looking up a user for the first time will require multiple updates to {project_name} database. This can
be a big performance loss under load and put a lot of strain on the {project_name} database. The user federated
storage approach will only store extra data as needed and might never be used depending on the capabilities of your external store.
* With the import approach, you have to keep local keycloak storage and external storage in sync. The User Storage SPI
* With the import approach, you have to keep local {project_name} storage and external storage in sync. The User Storage SPI
has capability interfaces that you can implement to support synchronization, but this can quickly become painful and messy.
==== UserFederationProvider vs. UserStorageProvider
@ -44,7 +44,7 @@ Also note that in the earlier SPI, this method was called every time the user wa
In the later SPI, this method is only called when the local user is loaded from local storage. If the local user is cached,
then the `ImportedUserValidation.validate()` method is not called at all.
The `UserFederationProvider.isValid()` method no longer exists in the later model.
The `UserFederationProvider.isValid()` method no longer exists in the later SPI.
The `UserFederationProvider` methods `synchronizeRegistrations()`, `registerUser()`, and `removeUser()` have been
moved to the `UserRegistrationProvider` capability interface. This new interface is optional to implement so if your
@ -80,8 +80,8 @@ with the same provider ID (i.e., "ldap", "kerberos") as the earlier User Federat
So, knowing this there are different approaches you can take.
. You can remove the earlier provider in your earlier {project_name} deployment. This will remove all local linked copies
of imported users. Then, when you upgrade {project_name}, just deploy and configure your new provider for your realm.
. You can remove the earlier provider in your earlier {project_name} deployment. This will remove thedd local linked copies
of all users you imported. Then, when you upgrade {project_name}, just deploy and configure your new provider for your realm.
. The second option is to write your new provider making sure it has the same provider ID: `UserStorageProviderFactory.getId()`.
Make sure this provider is in the `deploy/` directory of the new {project_name} installation. Boot the server, and have
the built-in migration script convert from the earlier data model to the later data model. In this case all your earlier linked imported

View file

@ -66,7 +66,7 @@ package org.keycloak.storage;
public interface UserStorageProviderFactory<T extends UserStorageProvider> extends ComponentFactory<T, UserStorageProvider> {
/**
* This is the name of the provider and will be showed in the admin console as an option.
* This is the name of the provider and will be shown in the admin console as an option.
*
* @return
*/
@ -102,10 +102,10 @@ public class FileProviderFactory implements UserStorageProviderFactory<FileProvi
----
The `getId()` method returns the name of the User Storage provider. This id will be displayed in the admin console's
`UserFederation` page when you want to enable the provider for a specific realm.
User Federation page when you want to enable the provider for a specific realm.
The `create()` method is responsible for allocating an instance of the provider class. It takes a `org.keycloak.models.KeycloakSession`
parameter. This object can be used to lookup other information and metadata as well as provide access to various other
parameter. This object can be used to look up other information and metadata as well as provide access to various other
components within the runtime. The `ComponentModel` parameter represents how the provider was enabled and configured within
a specific realm. It contains the instance id of the enabled provider as well as any configuration you may have specified
for it when you enabled through the admin console.

View file

@ -56,7 +56,7 @@ Notice that when adding a user we set the password value of the property map to
we can't have null values for a property in the property value. We also have to modify the `CredentialInputValidator`
methods to reflect this.
`addUser()` will be called if the provider implements the `UserRegistrationProvider` interface. If your provider has
The `addUser()` method will be called if the provider implements the `UserRegistrationProvider` interface. If your provider has
a configuration switch to turn of adding a user, returning `null` from this method will skip the provider and call
the next one.
@ -92,7 +92,7 @@ Since we can now save our property file, it also makes sense to allow password u
}
----
We can now also implement disabling a password too.
We can now also implement disabling a password.
.PropertyFileUserStorageProvider
[source,java]

View file

@ -208,7 +208,7 @@ The `UserStorageProviderFactory` interface has an optional `init()` method you c
In our `init()` method implementation, we find the property file containing our user declarations from the classpath. We then load the `properties` field with the username and password combinations stored there.
The `Config.Scope` parameter is factory configuration that can be set up within `standalone.xml`, `standalone-ha.xml`, or `domain.xml`. For more information on where the `standalone.xml`, `standalone-ha.xml`, or `domain.xml` file resides see the link:{installguide_link}[{installguide_name}].
The `Config.Scope` parameter is factory configuration that can be set up within `standalone.xml`, `standalone-ha.xml`, or `domain.xml`. For more information on where these files reside see the link:{installguide_link}[{installguide_name}].
For example, by adding the following to `standalone.xml`: