cleanup and docs for mappers

This commit is contained in:
Bill Burke 2015-03-11 12:05:27 -04:00
parent 451ce64907
commit 6450c4c5f3
18 changed files with 250 additions and 110 deletions

View file

@ -40,6 +40,8 @@
<!ENTITY ApplicationClustering SYSTEM "modules/application-clustering.xml">
<!ENTITY MultiTenancy SYSTEM "modules/multi-tenancy.xml">
<!ENTITY Proxy SYSTEM "modules/proxy.xml">
<!ENTITY CustomAttributes SYSTEM "modules/custom-attributes.xml">
<!ENTITY ProtocolMappers SYSTEM "modules/protocol-mappers.xml">
]>
<book>
@ -128,6 +130,8 @@ This one is short
&Clustering;
&ApplicationClustering;
&Proxy;
&CustomAttributes;
&ProtocolMappers;
&Migration;
</book>

View file

@ -94,6 +94,14 @@
Multitenancy support. You can host and manage multiple realms for multiple organizations. In the same auth server
and even within the same deployed application.
</listitem>
<listitem>
Identity brokering/chaining. You can make the Keycloak server a child IDP to another SAML 2.0 or OpenID Connect IDP.
</listitem>
<listitem>
Token claim, assertion, and attribute mappings. You can map user attributes, roles, and role names however you want
into a OIDC ID Token, Access Token, SAML attribute statements, etc. This feature allows you to basically
tailor however you want auth responses to look.
</listitem>
<listitem>
Supports JBoss AS7, EAP 6.x, Wildfly, Tomcat 7, Tomcat 8, Jetty 9.1.x, Jetty 9.2.x, Jetty 8.1.x, and Pure JavaScript applications. Plans to support Node.js, RAILS, GRAILS, and other non-Java deployments
</listitem>

View file

@ -0,0 +1,150 @@
<chapter id="custom-user-attributes">
<title>Custom User Attributes</title>
<para>If you have custom user data you want to store and manage in the admin console, registration page, and user account service, you can easily add
support for it by extending and modifying various Keycloak <link linkend="themes">themes</link>.</para>
<section>
<title>In admin console</title>
<para>To be able to enter custom attributes in the admin console, take the following steps</para>
<para>
<orderedlist>
<listitem>
Create a new theme within the <literal>themes/admin/mytheme</literal> directory in your distribution.
Where <literal>mytheme</literal> is whatever you want to name your theme.
</listitem>
<listitem>
Create a <literal>theme.properties</literal> file in this directory that extends the main admin console
theme.
<programlisting><![CDATA[parent=keycloak
import=common/keycloak
]]></programlisting>
</listitem>
<listitem>
Copy the file <literal>themes/admin/base/resources/partials/user-attribute-entry.html</literal> into the
a mirror directory in your theme: <literal>themes/admin/mytheme/resources/partials/user-attribute-entry.html</literal>.
What you are doing here is overriding the user attribute entry page in the admin console and putting in
what attributes you want. This file already contains an example of entering address data. You can remove
this if you want and replace it with something else. Also, if you want to edit this file directly instead
of creating a new theme, you can.
</listitem>
<listitem>
In the <literal>user-attribute-entry.html</literal> file add your custom user attribute entry form item. For example
<programlisting><![CDATA[ <div class="form-group clearfix block">
<label class="col-sm-2 control-label" for="mobile">Mobile</label>
<div class="col-sm-6">
<input ng-model="user.attributes.mobile" class="form-control" type="text" name="mobile" id="mobile" />
</div>
<span tooltip-placement="right" tooltip="Mobile number." class="fa fa-info-circle"></span>
</div>
]]></programlisting>
The <literal>ng-model</literal> names the user attribute you will store in the database and must have the
form of <literal>user.attributes.ATTR_NAME</literal>.
</listitem>
<listitem>
Change the theme for the admin console. Save it, then refresh your browser, and you should
now see these fields in the User detail page for any user.
</listitem>
</orderedlist>
</para>
</section>
<section>
<title>In registration page</title>
<para>To be able to enter custom attributes in the registration page, take the following steps</para>
<para>
<orderedlist>
<listitem>
Create a new theme within the <literal>themes/login/mytheme</literal> directory in your distribution.
Where <literal>mytheme</literal> is whatever you want to name your theme.
</listitem>
<listitem>
Create a <literal>theme.properties</literal> file in this directory that extends the main admin console
theme.
<programlisting><![CDATA[parent=keycloak
import=common/keycloak
styles= ../patternfly/lib/patternfly/css/patternfly.css ../patternfly/css/login.css ../patternfly/lib/zocial/zocial.css css/login.css]]></programlisting>
</listitem>
<listitem>
Copy the file <literal>themes/login/base/register.ftl</literal> into the
a mirror directory in your theme: <literal>themes/login/mytheme/register.ftl</literal>.
What you are doing here is overriding the registration page and adding
what attributes you want. This file already contains an example of entering address data. You can remove
this if you want and replace it with something else. Also, if you want to edit this file directly instead
of creating a new theme, you can.
</listitem>
<listitem>
In the <literal>register.ftl</literal> file add your custom user attribute entry form item. For example
<programlisting><![CDATA[
<div class="form-group">
<div class="${properties.kcLabelWrapperClass!}">
<label for="user.attributes.mobile" class="${properties.kcLabelClass!}">Mobile number</label>
</div>
<div class="col-sm-10 col-md-10">
<input type="text" class="${properties.kcInputClass!}" id="user.attributes.mobile" name="user.attributes.mobile"/>
</div>
</div>
]]></programlisting>
Make sure the input field id ane name match the user attribute you want to store in the database.
This must have the
form of <literal>user.attributes.ATTR_NAME</literal>. You might also want to replace the label text
with a message property. This will help later if you want to internationalize your pages.
</listitem>
<listitem>
Change the theme for the login to your new theme. Save it, then refresh your browser, and you should
now see these fields in the registration.
</listitem>
</orderedlist>
</para>
</section>
<section>
<title>In user account profile page</title>
<para>To be able to manage custom attributes in the user account profile page, take the following steps</para>
<para>
<orderedlist>
<listitem>
Create a new theme within the <literal>themes/account/mytheme</literal> directory in your distribution.
Where <literal>mytheme</literal> is whatever you want to name your theme.
</listitem>
<listitem>
Create a <literal>theme.properties</literal> file in this directory that extends the main admin console
theme.
<programlisting><![CDATA[parent=patternfly
import=common/keycloak
styles= ../patternfly/lib/patternfly/css/patternfly.css ../patternfly/css/account.css css/account.css]]></programlisting>
</listitem>
<listitem>
Copy the file <literal>themes/account/base/account.ftl</literal> into the
a mirror directory in your theme: <literal>themes/account/mytheme/account.ftl</literal>.
What you are doing here is overriding the profile page and adding
what attributes you want to manage. This file already contains an example of entering address data. You can remove
this if you want and replace it with something else. Also, if you want to edit this file directly instead
of creating a new theme, you can.
</listitem>
<listitem>
In the <literal>account.ftl</literal> file add your custom user attribute entry form item. For example
<programlisting><![CDATA[
<div class="form-group">
<div class="col-sm-2 col-md-2">
<label for="user.attributes.mobile" class="control-label">Mobile number</label>
</div>
<div class="col-sm-10 col-md-10">
<input type="text" class="form-control" id="user.attributes.mobile" name="user.attributes.mobile" value="${(account.attributes.mobile!'')?html}"/>
</div>
</div>]]></programlisting>
Make sure the input field id ane name match the user attribute you want to store in the database.
This must have the
form of <literal>user.attributes.ATTR_NAME</literal>. You might also want to replace the label text
with a message property. This will help later if you want to internationalize your pages.
</listitem>
<listitem>
Change the theme for the account to your new theme. Save it, then refresh your browser, and you should
now see these fields in the account profile page.
</listitem>
</orderedlist>
</para>
</section>
</chapter>

View file

@ -0,0 +1,17 @@
<chapter id="mappers">
<title>OIDC Token and SAML Assertion Mappings</title>
<para>
Applications that receive ID Tokens, Access Tokens, or SAML assertions may need or want different user metadata
and roles. Keycloak allows you to define what exactly is transferred. You can hardcode roles, claims and custom
attributes. You can pull user metadata into a token or assertion. You can rename roles. Basicall you have
a lot of control of what exactly goes back to the client.
</para>
<para>
Within the admin console, if you go to an application you've registered, you'll see a "Mappers" sub-menu item.
This is the place where you can control how a OIDC ID Token, Access Token, and SAML login response assertions look
like. When you click on this you'll see some default mappers that have been set up for you. Clicking the
"Add Builtin" button gives you the option to add other preconfigured mappers. Clicking on "Create" allows
you to define your own protocol mappers. The tooltips are very helpful to learn exactly what you can do
to tailor your tokens and assertions. They should be enough to guide you through the process.
</para>
</chapter>

View file

@ -64,13 +64,6 @@
</div>
<span tooltip-placement="right" tooltip="Should a statement specifying the method and timestamp be included in login responses?" class="fa fa-info-circle"></span>
</div>
<div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
<label class="col-sm-2 control-label" for="samlMultiValuedRoles">Multi-valued Roles</label>
<div class="col-sm-6">
<input ng-model="samlMultiValuedRoles" ng-click="switchChange()" name="samlMultiValuedRoles" id="samlMultiValuedRoles" onoffswitch />
</div>
<span tooltip-placement="right" tooltip="'On' means that there will be one role attribute with multiple values for each role in SAML response. 'Off' means that there will be an attribute defined for each role." class="fa fa-info-circle"></span>
</div>
<div class="form-group clearfix block" data-ng-show="protocol == 'saml'">
<label class="col-sm-2 control-label" for="samlServerSignature">Sign Documents</label>
<div class="col-sm-6">

View file

@ -1,6 +1,7 @@
package org.keycloak.login;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
import org.keycloak.models.UserModel;
@ -35,7 +36,7 @@ public interface LoginFormsProvider extends Provider {
public Response createErrorPage();
public Response createOAuthGrant();
public Response createOAuthGrant(ClientSessionModel clientSessionModel);
public Response createCode();

View file

@ -24,6 +24,7 @@ import org.keycloak.login.freemarker.model.IdentityProviderBean;
import org.keycloak.login.freemarker.model.TotpBean;
import org.keycloak.login.freemarker.model.UrlBean;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
import org.keycloak.models.RoleModel;
@ -75,6 +76,7 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
private UserModel user;
private ClientModel client;
private ClientSessionModel clientSession;
private UriInfo uriInfo;
@ -213,7 +215,7 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
attributes.put("register", new RegisterBean(formData));
break;
case OAUTH_GRANT:
attributes.put("oauth", new OAuthGrantBean(accessCode, client, realmRolesRequested, resourceRolesRequested, this.accessRequestMessage));
attributes.put("oauth", new OAuthGrantBean(accessCode, clientSession, client, realmRolesRequested, resourceRolesRequested, this.accessRequestMessage));
break;
case CODE:
attributes.put(OAuth2Constants.CODE, new CodeBean(accessCode, messageType == MessageType.ERROR ? message : null));
@ -265,7 +267,8 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider {
return createResponse(LoginFormsPages.ERROR);
}
public Response createOAuthGrant() {
public Response createOAuthGrant(ClientSessionModel clientSession) {
this.clientSession = clientSession;
return createResponse(LoginFormsPages.OAUTH_GRANT);
}

View file

@ -21,8 +21,9 @@
*/
package org.keycloak.login.freemarker.model;
import org.keycloak.models.ClaimMask;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RoleModel;
import javax.ws.rs.core.MultivaluedMap;
@ -41,7 +42,7 @@ public class OAuthGrantBean {
private ClientModel client;
private List<String> claimsRequested;
public OAuthGrantBean(String code, ClientModel client, List<RoleModel> realmRolesRequested, MultivaluedMap<String, RoleModel> resourceRolesRequested, String accessRequestMessage) {
public OAuthGrantBean(String code, ClientSessionModel clientSession, ClientModel client, List<RoleModel> realmRolesRequested, MultivaluedMap<String, RoleModel> resourceRolesRequested, String accessRequestMessage) {
this.code = code;
this.client = client;
this.realmRolesRequested = realmRolesRequested;
@ -50,36 +51,12 @@ public class OAuthGrantBean {
// todo support locale
List<String> claims = new LinkedList<String>();
long mask = client.getAllowedClaimsMask();
if (ClaimMask.hasEmail(mask)) {
claims.add("email");
}
if (ClaimMask.hasUsername(mask)) {
claims.add("username");
}
if (ClaimMask.hasName(mask)) {
claims.add("name");
}
if (ClaimMask.hasGender(mask)) {
claims.add("gender");
}
if (ClaimMask.hasAddress(mask)) {
claims.add("address");
}
if (ClaimMask.hasPhone(mask)) {
claims.add("phone");
}
if (ClaimMask.hasPicture(mask)) {
claims.add("picture");
}
if (ClaimMask.hasProfile(mask)) {
claims.add("profile page");
}
if (ClaimMask.hasLocale(mask)) {
claims.add("locale");
}
if (ClaimMask.hasWebsite(mask)) {
claims.add("website");
if (clientSession != null) {
for (ProtocolMapperModel model : client.getProtocolMappers()) {
if (model.isConsentRequired() && model.getProtocol().equals(clientSession.getAuthMethod()) && model.getConsentText() != null) {
claims.add(model.getConsentText());
}
}
}
if (claims.size() > 0) this.claimsRequested = claims;
}

View file

@ -24,11 +24,6 @@ public class HardcodedAttributeMapper extends AbstractSAMLProtocolMapper impleme
static {
ConfigProperty property;
property = new ConfigProperty();
property.setName(ProtocolMapperUtils.USER_ATTRIBUTE);
property.setLabel(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_LABEL);
property.setHelpText(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_HELP_TEXT);
configProperties.add(property);
AttributeStatementHelper.setConfigProperties(configProperties);
property = new ConfigProperty();
property.setName(ATTRIBUTE_VALUE);

View file

@ -5,6 +5,7 @@ import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.ProtocolMapper;
import org.keycloak.protocol.ProtocolMapperUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.representations.AccessToken;
@ -44,8 +45,13 @@ public class HardcodedClaim extends AbstractOIDCProtocolMapper implements OIDCAc
property = new ConfigProperty();
property.setName(OIDCAttributeMapperHelper.JSON_TYPE);
property.setLabel(OIDCAttributeMapperHelper.JSON_TYPE);
property.setType(ConfigProperty.STRING_TYPE);
property.setDefaultValue(ConfigProperty.STRING_TYPE);
List<String> types = new ArrayList(3);
types.add("String");
types.add("long");
types.add("int");
types.add("boolean");
property.setType(ProtocolMapper.ConfigProperty.LIST_TYPE);
property.setDefaultValue(types);
property.setHelpText("JSON type that should be used for the value of the claim. long, int, boolean, and String are valid values.");
configProperties.add(property);
property = new ConfigProperty();

View file

@ -49,7 +49,7 @@ public class HardcodedRole extends AbstractOIDCProtocolMapper implements OIDCAcc
@Override
public String getDisplayType() {
return "Add Role";
return "Hardcoded Role";
}
@Override
@ -59,7 +59,7 @@ public class HardcodedRole extends AbstractOIDCProtocolMapper implements OIDCAcc
@Override
public String getHelpText() {
return "Hardcode any role specify into the token.";
return "Hardcode a role into the access token.";
}
@Override

View file

@ -2,12 +2,15 @@ package org.keycloak.protocol.oidc.mappers;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.protocol.ProtocolMapper;
import org.keycloak.protocol.ProtocolMapperUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.IDToken;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@ -97,4 +100,40 @@ public class OIDCAttributeMapperHelper {
public static boolean includeInAccessToken(ProtocolMapperModel mappingModel) {
return "true".equals(mappingModel.getConfig().get(INCLUDE_IN_ACCESS_TOKEN));
}
public static void addAttributeConfig(List<ProtocolMapper.ConfigProperty> configProperties) {
ProtocolMapper.ConfigProperty property;
property = new ProtocolMapper.ConfigProperty();
property.setName(TOKEN_CLAIM_NAME);
property.setLabel(TOKEN_CLAIM_NAME_LABEL);
property.setType(ProtocolMapper.ConfigProperty.STRING_TYPE);
property.setHelpText("Name of the claim to insert into the token. This can be a fully qualified name like 'address.street'. In this case, a nested json object will be created.");
configProperties.add(property);
property = new ProtocolMapper.ConfigProperty();
property.setName(JSON_TYPE);
property.setLabel(JSON_TYPE);
List<String> types = new ArrayList(3);
types.add("String");
types.add("long");
types.add("int");
types.add("boolean");
property.setType(ProtocolMapper.ConfigProperty.LIST_TYPE);
property.setDefaultValue(types);
property.setHelpText("JSON type that should be used to populate the json claim in the token. long, int, boolean, and String are valid values.");
configProperties.add(property);
property = new ProtocolMapper.ConfigProperty();
property.setName(INCLUDE_IN_ID_TOKEN);
property.setLabel(INCLUDE_IN_ID_TOKEN_LABEL);
property.setType(ProtocolMapper.ConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(INCLUDE_IN_ID_TOKEN_HELP_TEXT);
configProperties.add(property);
property = new ProtocolMapper.ConfigProperty();
property.setName(INCLUDE_IN_ACCESS_TOKEN);
property.setLabel(INCLUDE_IN_ACCESS_TOKEN_LABEL);
property.setType(ProtocolMapper.ConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
configProperties.add(property);
}
}

View file

@ -58,7 +58,7 @@ public class RoleNameMapper extends AbstractOIDCProtocolMapper implements OIDCAc
@Override
public String getDisplayType() {
return "Role Mapper";
return "Role Name Mapper";
}
@Override

View file

@ -33,33 +33,7 @@ public class UserAttributeMapper extends AbstractOIDCProtocolMapper implements O
property.setHelpText(ProtocolMapperUtils.USER_MODEL_ATTRIBUTE_HELP_TEXT);
property.setType(ConfigProperty.STRING_TYPE);
configProperties.add(property);
property = new ConfigProperty();
property.setName(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
property.setLabel(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME_LABEL);
property.setType(ConfigProperty.STRING_TYPE);
property.setHelpText("Name of the claim to insert into the token. This can be a fully qualified name like 'address.street'. In this case, a nested json object will be created.");
configProperties.add(property);
property = new ConfigProperty();
property.setName(OIDCAttributeMapperHelper.JSON_TYPE);
property.setLabel(OIDCAttributeMapperHelper.JSON_TYPE);
property.setType(ConfigProperty.STRING_TYPE);
property.setDefaultValue(ConfigProperty.STRING_TYPE);
property.setHelpText("JSON type that should be used to populate the json claim in the token. long, int, boolean, and String are valid values.");
configProperties.add(property);
property = new ConfigProperty();
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
property.setType(ConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
configProperties.add(property);
property = new ConfigProperty();
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
property.setType(ConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
configProperties.add(property);
OIDCAttributeMapperHelper.addAttributeConfig(configProperties);
}

View file

@ -3,7 +3,6 @@ package org.keycloak.protocol.oidc.mappers;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.ProtocolMapperUtils;
@ -32,33 +31,7 @@ public class UserPropertyMapper extends AbstractOIDCProtocolMapper implements OI
property.setType(ConfigProperty.STRING_TYPE);
property.setHelpText(ProtocolMapperUtils.USER_MODEL_PROPERTY_HELP_TEXT);
configProperties.add(property);
property = new ConfigProperty();
property.setName(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
property.setLabel(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME_LABEL);
property.setType(ConfigProperty.STRING_TYPE);
property.setHelpText("Name of the claim to insert into the token. This can be a fully qualified name like 'address.street'. In this case, a nested json object will be created.");
configProperties.add(property);
property = new ConfigProperty();
property.setName(OIDCAttributeMapperHelper.JSON_TYPE);
property.setLabel(OIDCAttributeMapperHelper.JSON_TYPE);
property.setType(ConfigProperty.STRING_TYPE);
property.setDefaultValue(ConfigProperty.STRING_TYPE);
property.setHelpText("JSON type that should be used to populate the json claim in the token. long, int, boolean, and String are valid values.");
configProperties.add(property);
property = new ConfigProperty();
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
property.setType(ConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
configProperties.add(property);
property = new ConfigProperty();
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
property.setType(ConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
configProperties.add(property);
OIDCAttributeMapperHelper.addAttributeConfig(configProperties);
}
public static final String PROVIDER_ID = "oidc-usermodel-property-mapper";

View file

@ -33,7 +33,7 @@ public class UserSessionNoteMapper extends AbstractOIDCProtocolMapper implements
configProperties.add(property);
property = new ConfigProperty();
property.setName(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
property.setLabel(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
property.setLabel(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME_LABEL);
property.setType(ConfigProperty.STRING_TYPE);
property.setHelpText("Name of the claim to insert into the token. This can be a fully qualified name like 'address.street'. In this case, a nested json object will be created.");
configProperties.add(property);

View file

@ -391,7 +391,7 @@ public class AuthenticationManager {
.setClientSessionCode(accessCode.getCode())
.setAccessRequest(realmRoles, resourceRoles)
.setClient(client)
.createOAuthGrant();
.createOAuthGrant(clientSession);
}
event.success();

View file

@ -197,7 +197,7 @@ public class IdentityBrokerService {
.setClient(clientModel)
.setUriInfo(this.uriInfo)
.setActionUri(this.uriInfo.getRequestUri())
.createOAuthGrant(), clientModel);
.createOAuthGrant(null), clientModel);
}
IdentityProvider identityProvider = getIdentityProvider(providerId);