Fix minor typos in the 'Server Developer' guide (#1702)
This commit is contained in:
parent
0ea743e15e
commit
8ab8c4e3e6
14 changed files with 23 additions and 23 deletions
|
@ -1,7 +1,7 @@
|
|||
[[_action_token_handler_spi]]
|
||||
== Action Token Handler SPI
|
||||
|
||||
An action token is a special instance of Json Web Token (JWT) that permits its bearer to perform some actions, e. g. to
|
||||
An action token is a special instance of Json Web Token (JWT) that permits its bearer to perform some actions, e.g. to
|
||||
reset a password or validate e-mail address. They are usually sent to users in form of a link that points to an endpoint
|
||||
processing action tokens for a particular realm.
|
||||
|
||||
|
@ -160,7 +160,7 @@ token, only the last token would be invalidated. In that case, you should use
|
|||
`org.keycloak.models.SingleUseObjectProvider` in action token handler to invalidate the used tokens manually.
|
||||
+
|
||||
Default implementation of most of the `ActionTokenHandler` methods is the
|
||||
`org.keycloak.authentication.actiontoken.AbstractActionTokenHander` abstract class in `keycloak-services` module. The
|
||||
`org.keycloak.authentication.actiontoken.AbstractActionTokenHandler` abstract class in `keycloak-services` module. The
|
||||
only method that needs to be implemented is `handleToken(token, context)` that performs the actual action.
|
||||
|
||||
* `org.keycloak.authentication.actiontoken.ActionTokenHandlerFactory` - factory that instantiates action token
|
||||
|
|
|
@ -10,7 +10,7 @@ The Admin Console supports applying, ordering, and configuring these new mechani
|
|||
Different aspects of this form can be enabled and disabled for example
|
||||
Recaptcha support can be turned off and on.
|
||||
The same authentication SPI can be used to add another page to the registration flow or reimplement it entirely.
|
||||
There's also an additional fine-grained SPI you can use to add specific validations and user extensions to the built in registration form.
|
||||
There's also an additional fine-grained SPI you can use to add specific validations and user extensions to the built-in registration form.
|
||||
|
||||
A required action in {project_name} is an action that a user has to perform after he authenticates.
|
||||
After the action is performed successfully, the user doesn't have to perform the action again.
|
||||
|
@ -700,7 +700,7 @@ public class SecretQuestionAuthenticatorFactory implements AuthenticatorFactory,
|
|||
The next thing the factory is responsible for is to specify the allowed requirement switches.
|
||||
While there are four different requirement types: ALTERNATIVE, REQUIRED, CONDITIONAL, DISABLED, AuthenticatorFactory implementations can limit which
|
||||
requirement options are shown in the Admin Console when defining a flow. CONDITIONAL should only always be used for subflows, and unless there's a good
|
||||
reason for doing otherwise, the requirement on a authenticator should be REQUIRED, ALTERNATIVE and DISABLED:
|
||||
reason for doing otherwise, the requirement on an authenticator should be REQUIRED, ALTERNATIVE and DISABLED:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
|
@ -792,7 +792,7 @@ Let's take a bigger look at secret-question.ftl Here's a small code snippet:
|
|||
</form>
|
||||
----
|
||||
|
||||
Any piece of text enclosed in `${}` corresponds to an attribute or template funtion.
|
||||
Any piece of text enclosed in `${}` corresponds to an attribute or template function.
|
||||
If you see the form's action, you see it points to `${url.loginAction}`.
|
||||
This value is automatically generated when you invoke the AuthenticationFlowContext.form() method.
|
||||
You can also obtain this value by calling the AuthenticationFlowContext.getActionURL() method in Java code.
|
||||
|
@ -940,7 +940,7 @@ Your new required action should now be displayed and enabled in the required act
|
|||
=== Modifying or extending the registration form
|
||||
|
||||
It is entirely possible for you to implement your own flow with a set of Authenticators to totally change how registration is done in {project_name}.
|
||||
But what you'll usually want to do is just add a little bit of validation to the out of the box registration page.
|
||||
But what you'll usually want to do is just add a bit of validation to the out-of-the-box registration page.
|
||||
An additional SPI was created to be able to do this.
|
||||
It basically allows you to add validation of form elements on the page as well as to initialize UserModel attributes and data after the user has been registered.
|
||||
We'll look at both the implementation of the user profile registration processing as well as the registration Google Recaptcha plugin.
|
||||
|
@ -1153,7 +1153,7 @@ One thing to note if you are extending the reset credentials flow.
|
|||
The first "authenticator" is just a page to obtain the username or email.
|
||||
If the username or email exists, then the AuthenticationFlowContext.getUser() will return the located user.
|
||||
Otherwise this will be null.
|
||||
This form *WILL NOT* re-ask the user to enter in an email or username if the previous email or username did not exist.
|
||||
This form *WILL NOT* re-ask the user to enter an email or username if the previous email or username did not exist.
|
||||
You need to prevent attackers from being able to guess valid users.
|
||||
So, if AuthenticationFlowContext.getUser() returns null, you should proceed with the flow to make it look like a valid user was selected.
|
||||
I suggest that if you want to add secret questions to this flow, you should ask these questions after the email is sent.
|
||||
|
@ -1187,7 +1187,7 @@ Actually {project_name} has 2 default implementations of client authentication:
|
|||
|
||||
Traditional authentication with client_id and client_secret::
|
||||
This is default mechanism mentioned in the https://openid.net/specs/openid-connect-core-1_0.html[OpenID Connect] or https://datatracker.ietf.org/doc/html/rfc6749[OAuth2] specification and {project_name} supports it since it's early days.
|
||||
The public client needs to include `client_id` parameter with its ID in the POST request (so it's defacto not authenticated) and the confidential client needs to include `Authorization: Basic` header with the clientId and clientSecret used as username and password.
|
||||
The public client needs to include `client_id` parameter with its ID in the POST request (so it's de facto not authenticated) and the confidential client needs to include `Authorization: Basic` header with the clientId and clientSecret used as username and password.
|
||||
|
||||
Authentication with signed JWT::
|
||||
This is based on the https://datatracker.ietf.org/doc/html/rfc7523[JWT Bearer Token Profiles for OAuth 2.0] specification.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[[_events]]
|
||||
== Event Listener SPI
|
||||
|
||||
Writing a Event Listener Provider starts by implementing the `EventListenerProvider` and `EventListenerProviderFactory` interfaces. Please see the Javadoc
|
||||
Writing an Event Listener Provider starts by implementing the `EventListenerProvider` and `EventListenerProviderFactory` interfaces. Please see the Javadoc
|
||||
and examples for complete details on how to do this.
|
||||
|
||||
For details on how to package and deploy a custom provider refer to the <<_providers,Service Provider Interfaces>> chapter.
|
||||
|
|
|
@ -152,4 +152,4 @@ The DB schema will be automatically updated at startup.
|
|||
|
||||
For more details, take a look at the example distribution at example `providers/domain-extension`, which shows the `ExampleJpaEntityProvider` and `example-changelog.xml` described above.
|
||||
|
||||
NOTE: Don't forget to always backup your database before doing any changes in the Liquibase changelog and triggering a DB update.
|
||||
NOTE: Don't forget to always back up your database before doing any changes in the Liquibase changelog and triggering a DB update.
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
== Identity Brokering APIs
|
||||
|
||||
{project_name} can delegate authentication to a parent IDP for login. A typical example of this is the case
|
||||
where you want users to be able to login through a social provider such as Facebook or Google. You can
|
||||
where you want users to be able to log in through a social provider such as Facebook or Google. You can
|
||||
also link existing accounts to a brokered IDP. This section describes some APIs that your applications
|
||||
can use as it pertains to identity brokering.
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ This behavior can be changed through the `LocaleSelectorSPI` by implementing the
|
|||
|
||||
The `LocaleSelectorProvider` interface has a single method, `resolveLocale`, which must return a locale given a `RealmModel` and a nullable `UserModel`. The actual request is available from the `KeycloakSession#getContext` method.
|
||||
|
||||
Custom implementations can extend the `DefaultLocaleSelectorProvider` in order to reuse parts of the default behavior. For example to ignore the `Accept-Language` request header, a custom implementation could extend the default provider, override it's `getAcceptLanguageHeaderLocale`, and return a null value. As a result the locale selection will fall back on the realms's default language.
|
||||
Custom implementations can extend the `DefaultLocaleSelectorProvider` in order to reuse parts of the default behavior. For example to ignore the `Accept-Language` request header, a custom implementation could extend the default provider, override it's `getAcceptLanguageHeaderLocale`, and return a null value. As a result the locale selection will fall back on the realm's default language.
|
||||
|
||||
[role="_additional-resources"]
|
||||
=== Additional resources
|
||||
|
|
|
@ -100,7 +100,7 @@ public void init(Config.Scope config) {
|
|||
}
|
||||
----
|
||||
|
||||
Your provider can also lookup other providers if needed. For example:
|
||||
Your provider can also look up other providers if needed. For example:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
|
@ -123,7 +123,7 @@ public class MyThemeSelectorProvider implements ThemeSelectorProvider {
|
|||
==== Show info from your SPI implementation in the Admin Console
|
||||
|
||||
Sometimes it is useful to show additional info about your Provider to a {project_name} administrator. You can show provider build time information (for example, version of
|
||||
custom provider currently installed), current configuration of the provider (eg. url of remote system your provider talks to) or some operational info
|
||||
custom provider currently installed), current configuration of the provider (e.g. url of remote system your provider talks to) or some operational info
|
||||
(average time of response from remote system your provider talks to). {project_name} Admin Console provides Server Info page to show this kind of information.
|
||||
|
||||
To show info from your provider it is enough to implement `org.keycloak.provider.ServerInfoAwareProviderFactory` interface in your `ProviderFactory`.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[[_saml_role_mappings_spi]]
|
||||
== SAML role mappings SPI
|
||||
|
||||
{project_name} defines a SPI for mapping SAML roles into roles that exist in the SP environment. The roles returned by
|
||||
{project_name} defines an SPI for mapping SAML roles into roles that exist in the SP environment. The roles returned by
|
||||
a third-party IDP might not always correspond to the roles that were defined for the SP application so there is a need for a
|
||||
mechanism that allows mapping the SAML roles into different roles. It is used by the SAML adapter after it extracts the roles
|
||||
from the SAML assertion to set up the container's security context.
|
||||
|
|
|
@ -97,7 +97,7 @@ import=common/keycloak
|
|||
+
|
||||
You have now created a theme with support for the login type.
|
||||
|
||||
. Log into the Admin Console to checkout your new theme
|
||||
. Log into the Admin Console to check out your new theme
|
||||
. Select your realm
|
||||
. Click *Realm Settings* from the menu.
|
||||
. Click on the *Themes* tab.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
=== LDAP mapper
|
||||
|
||||
For the more advanced usecases, you have the possibility to create your own implementation of LDAP mapper or just subclass from some already existing mapper
|
||||
For the more advanced use cases, you have the possibility to create your own implementation of LDAP mapper or just subclass from some already existing mapper
|
||||
implementation. You will need to implement `UserFederationMapperFactory` interface.
|
||||
|
||||
In most cases, instead of creating `UserFederationMapperFactory` from scratch, you can create subclasses of `AbstractLDAPFederationMapperFactory`, which itself
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
=== Augmenting external storage
|
||||
|
||||
The `PropertyFileUserStorageProvider` 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 log in 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.
|
||||
|
|
|
@ -63,7 +63,7 @@ return a `ReadOnlyException`.
|
|||
|
||||
The `UserFederationProvider` query methods such as `searchByAttributes()` and `getGroupMembers()` are now encapsulated
|
||||
in an optional interface `UserQueryProvider`. If you do not implement this interface, then users will not be viewable
|
||||
in the admin console. You'll still be able to login though.
|
||||
in the admin console. You'll still be able to log in though.
|
||||
|
||||
==== UserFederationProviderFactory versus UserStorageProviderFactory
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ The `createAdapter()` method uses the helper class `org.keycloak.storage.adapter
|
|||
|
||||
Every get method of `AbstractUserAdapter` either returns null or empty collections. However, methods that return role and group mappings will return the default roles and groups configured for the realm for every user. Every set method of `AbstractUserAdapter` will throw a `org.keycloak.storage.ReadOnlyException`. So if you attempt to modify the user in the Admin Console, you will get an error.
|
||||
|
||||
The `getUserById()` method parses the `id` parameter using the `org.keycloak.storage.StorageId` helper class. The `StorageId.getExternalId()` method is invoked to obtain the username embeded in the `id` parameter. The method then delegates to `getUserByUsername()`.
|
||||
The `getUserById()` method parses the `id` parameter using the `org.keycloak.storage.StorageId` helper class. The `StorageId.getExternalId()` method is invoked to obtain the username embedded in the `id` parameter. The method then delegates to `getUserByUsername()`.
|
||||
|
||||
Emails are not stored, so the `getUserByEmail()` method returns null.
|
||||
|
||||
|
|
|
@ -24,13 +24,13 @@ ifeval::[{project_community}==true]
|
|||
| `org.keycloak.models` | `GroupModel`, `RoleMapperModel`, `UserCredentialManager`, `UserModel`, `UserProvider`
|
||||
| `org.keycloak.models.cache` | `CachedUserModel`, `UserCache`
|
||||
| `org.keycloak.storage.federated` | All interfaces
|
||||
| `org.kecyloak.storage.user` | `UserQueryProvider`(*)
|
||||
| `org.keycloak.storage.user` | `UserQueryProvider`(*)
|
||||
endif::[]
|
||||
ifeval::[{project_product}==true]
|
||||
| `org.keycloak.credential` | `CredentialInputUpdater`(*)
|
||||
| `org.keycloak.models` | `GroupModel`, `RoleMapperModel`, `UserModel`
|
||||
| `org.keycloak.storage.federated` | All interfaces
|
||||
| `org.kecyloak.storage.user` | `UserQueryProvider`(*)
|
||||
| `org.keycloak.storage.user` | `UserQueryProvider`(*)
|
||||
endif::[]
|
||||
|===
|
||||
(*) indicates the interface is a _<<_provider_capability_interfaces,capability interface>>_
|
||||
|
@ -54,4 +54,4 @@ public class CustomQueryProvider extends UserQueryProvider.Streams {
|
|||
}
|
||||
...
|
||||
}
|
||||
----
|
||||
----
|
||||
|
|
Loading…
Reference in a new issue