<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	
	xmlns:georss="http://www.georss.org/georss"
	xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#"
	>

<channel>
	<title>Marceli Formela, Autor w serwisie Inero Software - Software Consulting</title>
	<atom:link href="https://inero-software.com/author/marceli-formela/feed/" rel="self" type="application/rss+xml" />
	<link>https://inero-software.com/author/marceli-formela/</link>
	<description>We unleash innovations using cutting-edge technologies, modern design and AI</description>
	<lastBuildDate>Tue, 01 Apr 2025 09:31:39 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.1</generator>

<image>
	<url>https://inero-software.com/wp-content/uploads/2018/11/inero-logo-favicon.png</url>
	<title>Marceli Formela, Autor w serwisie Inero Software - Software Consulting</title>
	<link>https://inero-software.com/author/marceli-formela/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">153509928</site>	<item>
		<title>Configuring Password Policies in Keycloak</title>
		<link>https://inero-software.com/configuring-password-policies-in-keycloak/</link>
		
		<dc:creator><![CDATA[Marceli Formela]]></dc:creator>
		<pubDate>Thu, 20 Mar 2025 12:10:07 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Company]]></category>
		<category><![CDATA[Keycloak]]></category>
		<category><![CDATA[IAM]]></category>
		<category><![CDATA[keycloak]]></category>
		<category><![CDATA[Password]]></category>
		<category><![CDATA[password management]]></category>
		<category><![CDATA[password policies]]></category>
		<guid isPermaLink="false">https://inero-software.com/?p=7635</guid>

					<description><![CDATA[<p>In this blog, we will first take a look at the built-in Keycloak mechanisms for password policy management. Then, we will explore the possibilities for customizing these mechanisms to better fit specific requirements.</p>
<p>Artykuł <a href="https://inero-software.com/configuring-password-policies-in-keycloak/">Configuring Password Policies in Keycloak</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="7635" class="elementor elementor-7635" data-elementor-post-type="post">
				<div class="elementor-element elementor-element-949c242 e-flex e-con-boxed e-con e-parent" data-id="949c242" data-element_type="container">
					<div class="e-con-inner">
				<div class="elementor-element elementor-element-a9078db elementor-widget elementor-widget-html" data-id="a9078db" data-element_type="widget" data-widget_type="html.default">
				<div class="elementor-widget-container">
			 
		</div>
				</div>
				<div class="elementor-element elementor-element-cc34f5b elementor-widget elementor-widget-text-editor" data-id="cc34f5b" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<h4><strong>Effective password management is an important aspect of securing user accounts, and Keycloak provides tools to enforce strong authentication policies. By configuring password rules, administrators can ensure that credentials meet security standards, reducing the risk of unauthorized access. The framework offers flexible options, allowing you to set requirements for password length, complexity, expiration, and reuse prevention. </strong></h4>						</div>
				</div>
				<div class="elementor-element elementor-element-0df981b elementor-widget elementor-widget-text-editor" data-id="0df981b" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">In this blog, we will first take a look at the built-in Keycloak mechanisms for password policy management. Then, we will explore the possibilities for customizing these mechanisms to better fit specific requirements.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-ad5f7b2 elementor-widget elementor-widget-image" data-id="ad5f7b2" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img fetchpriority="high" decoding="async" data-attachment-id="7638" data-permalink="https://inero-software.com/configuring-password-policies-in-keycloak/attachment/115856/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/115856.png" data-orig-size="775,411" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="115856" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/115856-300x159.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/115856.png" tabindex="0" role="button" width="775" height="411" src="https://inero-software.com/wp-content/uploads/2025/03/115856.png" class="attachment-large size-large wp-image-7638" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/03/115856.png 775w, https://inero-software.com/wp-content/uploads/2025/03/115856-300x159.png 300w, https://inero-software.com/wp-content/uploads/2025/03/115856-768x407.png 768w, https://inero-software.com/wp-content/uploads/2025/03/115856-566x300.png 566w" sizes="(max-width: 775px) 100vw, 775px" data-attachment-id="7638" data-permalink="https://inero-software.com/configuring-password-policies-in-keycloak/attachment/115856/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/115856.png" data-orig-size="775,411" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="115856" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/115856-300x159.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/115856.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-b583771 elementor-widget elementor-widget-heading" data-id="b583771" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Built-in policies</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-b2a2079 elementor-widget elementor-widget-text-editor" data-id="b2a2079" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">These built-in password policies in Keycloak allow administrators to enforce security rules to strengthen user authentication. Here’s a brief description of each policy:</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-1dcf64f elementor-widget elementor-widget-text-editor" data-id="1dcf64f" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<ol><li aria-level="1"><strong>Expire Password</strong> <span style="font-weight: 400;">– Forces users to change their password after a specified period.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;"><strong>Hashing Iterations</strong> – Determines the number of iterations for password hashing to enhance security.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;"><strong>Not Recently Used</strong> – Prevents users from reusing their recent passwords.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;"><strong>Password Blacklist</strong> – Blocks specific passwords from being used, typically to prevent weak or common passwords.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;"><strong>Regular Expression</strong> – Allows enforcing a custom regex pattern for password validation.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;"><strong>Minimum Length</strong> – Sets the minimum number of characters required in a password.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;"><strong>Not Username</strong> – Prevents users from setting their username as a password.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;"><strong>Not Email</strong> – Prevents users from using their email address as a password.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;"><strong>Not Recently Used</strong> (In Days) – Prevents password reuse within a specified number of days.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;"><strong>Not Contains Username</strong> – Ensures the password does not include the username as part of it.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;"><strong>Special Character</strong>s – Requires passwords to contain at least one special character.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;"><strong>Uppercase Characters</strong> – Enforces at least one uppercase letter in the password.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;"><strong>Lowercase Characters</strong> – Requires at least one lowercase letter in the password.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;"><strong>Digits</strong> – Ensures the password includes at least one numeric digit.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;"><strong>Maximum Authentication Age</strong> – Sets a limit on how long authentication remains valid before requiring reauthentication.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;"><strong>Hashing Algorithm</strong> – Specifies the hashing algorithm used for password encryption.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;"><strong>Maximum Length</strong> – Defines the maximum allowable length for passwords.</span></li></ol>						</div>
				</div>
				<div class="elementor-element elementor-element-95da107 elementor-widget elementor-widget-heading" data-id="95da107" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h2 class="elementor-heading-title elementor-size-default">Implementing custom policy using SPI</h2>		</div>
				</div>
				<div class="elementor-element elementor-element-86f9385 elementor-widget elementor-widget-text-editor" data-id="86f9385" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">To implement a custom password policy in Keycloak, we should use the Service Provider Interface (SPI).</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-efcfbc7 elementor-widget elementor-widget-text-editor" data-id="efcfbc7" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">In this case, we define a custom password policy provider by implementing the PasswordPolicyProviderFactory interface:</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-a47d185 elementor-widget elementor-widget-code-highlight" data-id="a47d185" data-element_type="widget" data-widget_type="code-highlight.default">
				<div class="elementor-widget-container">
					<div class="prismjs-default copy-to-clipboard ">
			<pre data-line="" class="highlight-height language-javascript line-numbers">
				<code readonly="true" class="language-javascript">
					<xmp>public class PasswordCustomPolicyProviderFactory implements PasswordPolicyProviderFactory {

	public static final Integer DEFAULT_VALUE = 1;
	public static final String MIN_PASSWORD_LIFETIME_ID = "minimumPasswordLifetime";

	@Override
	public String getId() {
    	return MIN_PASSWORD_LIFETIME_ID;
	}

	@Override
	public PasswordPolicyProvider create(KeycloakSession session) {
    	return new PasswordCustomPolicyProvider(session);
	}
[...]
}

</xmp>
				</code>
			</pre>
		</div>
				</div>
				</div>
				<div class="elementor-element elementor-element-75140a5 elementor-widget elementor-widget-text-editor" data-id="75140a5" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Factory instantiates and returns a new instance of <strong>PasswordCustomPolicyProvider</strong>, which contains the actual validation logic for enforcing the minimum password lifetime. The <strong>MIN_PASSWORD_LIFETIME_ID</strong> constant serves as the unique identifier for this custom policy </span><span style="font-weight: 400;">and <strong>DEFAULT_VALUE</strong> constant represents the default minimum password lifetime (in days) if no custom value is configured via admin console.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-3c1cd5b elementor-widget elementor-widget-code-highlight" data-id="3c1cd5b" data-element_type="widget" data-widget_type="code-highlight.default">
				<div class="elementor-widget-container">
					<div class="prismjs-default copy-to-clipboard ">
			<pre data-line="" class="highlight-height language-javascript line-numbers">
				<code readonly="true" class="language-javascript">
					<xmp>public class PasswordCustomPolicyProvider implements PasswordPolicyProvider {
np.
   private static final String POLICY_VIOLATION_MESSAGE = "passwordLifetimeViolation";


   private final KeycloakSession keycloakSession;

   public PasswordCustomPolicyProvider(KeycloakSession keycloakSession) {
   	this.keycloakSession = keycloakSession;
   }


   @Override
   public PolicyError validate(RealmModel realm, UserModel user, String password) {
   	PasswordCredentialProvider credentialProvider = new PasswordCredentialProvider(keycloakSession);
   	PasswordCredentialModel credentialModel = credentialProvider.getPassword(realm, user);

   	if (credentialModel == null) {
       	return null;
   	}

   	long passwordCreationTime = credentialModel.getCreatedDate();
   	long currentTime = Time.currentTimeMillis();
   	long elapsedTime = currentTime - passwordCreationTime;

   	PasswordPolicy passwordPolicy = realm.getPasswordPolicy();
   	int minPasswordLifetimeDays = passwordPolicy.getPolicyConfig(PasswordCustomPolicyProviderFactory.MIN_PASSWORD_LIFETIME_ID);
   	long minPasswordLifetimeMillis = TimeUnit.DAYS.toMillis(minPasswordLifetimeDays);
   	return elapsedTime >= minPasswordLifetimeMillis ? null : new PolicyError(POLICY_VIOLATION_MESSAGE, minPasswordLifetimeDays);
   }
[...]
}
</xmp>
				</code>
			</pre>
		</div>
				</div>
				</div>
				<div class="elementor-element elementor-element-7cd9848 elementor-widget elementor-widget-text-editor" data-id="7cd9848" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">The <strong>PasswordCredentialProvider</strong> can access the stored password creation timestamp via the <strong>PasswordCredentialModel</strong> instance. It then computes <strong>elapsedTime</strong> as the difference between this timestamp and the current system time, representing how long the password has been in use.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-c8ec00f elementor-widget elementor-widget-text-editor" data-id="c8ec00f" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Next, the PasswordPolicy object retrieves the password policy for the realm, extracts the minimum required password lifetime in days (minPasswordLifetimeDays), and converts it to milliseconds (minPasswordLifetimeMillis). The policy ensures that the password has been in use for at least the required duration. If this requirement is not met, a PolicyError is returned. The error message key is stored in <strong>POLICY_VIOLATION_MESSAGE</strong>, and its content can be customized within our theme. This allows us to define a user-friendly message that informs the user why the password change is restricted and how much time remains before a new password can be set.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-5c8b84b elementor-widget elementor-widget-image" data-id="5c8b84b" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img decoding="async" data-attachment-id="7639" data-permalink="https://inero-software.com/configuring-password-policies-in-keycloak/attachment/122254/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/122254.png" data-orig-size="711,443" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="122254" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/122254-300x187.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/122254.png" tabindex="0" role="button" width="711" height="443" src="https://inero-software.com/wp-content/uploads/2025/03/122254.png" class="attachment-large size-large wp-image-7639" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/03/122254.png 711w, https://inero-software.com/wp-content/uploads/2025/03/122254-300x187.png 300w, https://inero-software.com/wp-content/uploads/2025/03/122254-481x300.png 481w" sizes="(max-width: 711px) 100vw, 711px" data-attachment-id="7639" data-permalink="https://inero-software.com/configuring-password-policies-in-keycloak/attachment/122254/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/122254.png" data-orig-size="711,443" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="122254" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/122254-300x187.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/122254.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-a18d447 elementor-widget elementor-widget-text-editor" data-id="a18d447" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">In this way, we can define custom password policies in Keycloak when the default set of policies is insufficient for specific requirements. This flexibility allows for more granular control over user authentication and password management when we need it.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-ed723ca elementor-widget elementor-widget-heading" data-id="ed723ca" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Customizing UI to improve user experience</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-0d876c8 elementor-widget elementor-widget-text-editor" data-id="0d876c8" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">By default, Keycloak displays unsatisfied password policies</span><b> individually </b><span style="font-weight: 400;">on the login page. This can be problematic for many users, especially when there are multiple policies that are not met. It can lead to a cluttered interface and make it harder for users to understand all the password requirements at once. To address this, you can customize the login screen to display a collective list of all unsatisfied password policies together, providing a clearer and more user-friendly experience.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-129921c elementor-widget elementor-widget-code-highlight" data-id="129921c" data-element_type="widget" data-widget_type="code-highlight.default">
				<div class="elementor-widget-container">
					<div class="prismjs-default copy-to-clipboard ">
			<pre data-line="" class="highlight-height language-javascript line-numbers">
				<code readonly="true" class="language-javascript">
					<xmp>public class CustomFreeMarkerLoginFormsProvider extends FreeMarkerLoginFormsProvider {
/**
* Mapping between password policy provider IDs and custom messages
* Note: contains only standard policies that must be displayed in the UI
*/
private final Map<String, String> policyPropertyMessages = Map.of(
LengthPasswordPolicyProviderFactory.ID, MINIMUM_LENGTH_MESSAGE,
MaximumLengthPasswordPolicyProviderFactory.ID, MAXIMUM_LENGTH_MESSAGE,
DigitsPasswordPolicyProviderFactory.ID, MINIMUM_DIGIT_MESSAGE,
SpecialCharsPasswordPolicyProviderFactory.ID, MINIMUM_SPECIAL_CHAR_MESSAGE,
UpperCasePasswordPolicyProviderFactory.ID, MINIMUM_UPPERCASE_MESSAGE,
LowerCasePasswordPolicyProviderFactory.ID, MINIMUM_LOWERCASE_MESSAGE,
NotUsernamePasswordPolicyProviderFactory.ID, NOT_USERNAME_MESSAGE,
NotContainsUsernamePasswordPolicyProviderFactory.ID, NOT_CONTAINS_USERNAME_MESSAGE,
NotEmailPasswordPolicyProviderFactory.ID, NOT_EMAIL_MESSAGE
);

[...]

@Override
protected void createCommonAttributes(Theme theme, Locale locale, Properties messagesBundle,
UriBuilder baseUriBuilder, LoginFormsPages page) {
super.createCommonAttributes(theme, locale, messagesBundle, baseUriBuilder, page);
if (realm != null && realm.getPasswordPolicy() != null) {
attributes.put("passwordPolicies", getPasswordPolicyMessages(realm.getPasswordPolicy(), messagesBundle));
}}

[...]

private Map<String, String> getPasswordPolicyMessages(PasswordPolicy passwordPolicy, Properties messagesBundle) {
Map<String, String> policyMessages = new HashMap<>();
PasswordPolicy.Builder builder = passwordPolicy.toBuilder();
for (String policyName : passwordPolicy.getPolicies()) {
var value = builder.get(policyName);
String message = extractPolicyMessage(policyName, value, messagesBundle);
if (message != null) {
policyMessages.put(policyName, message);
}
}
return policyMessages;
}

[...]

/**
* Extracts a message for a given password policy from the messages bundle
* Note: Policy message is constructed by replacing the {0} placeholder with the policy value
*/
private String extractPolicyMessage(String policy, String value, Properties messagesBundle) {
String property = policyPropertyMessages.get(policy);
if (property == null) {
return null;
}
String policyMessage = messagesBundle.getProperty(property);
return policyMessage != null ? policyMessage.replace("{0}", value) : null;
}
</xmp>
				</code>
			</pre>
		</div>
				</div>
				</div>
				<div class="elementor-element elementor-element-e47c0c6 elementor-widget elementor-widget-text-editor" data-id="e47c0c6" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">The getPasswordPolicyMessages() function already collects the password policies from the PasswordPolicy and maps them to the appropriate messages from the message bundle. You can extend this function to display all unsatisfied policies in one collective message.</span></p><p> </p><p><span style="font-weight: 400;">Password policies such as minimum length, required digits, special characters, etc., are mapped to messages via the extractPolicyMessage() method. Our service implementation will iterate through each policy and check if it&#8217;s satisfied. If not, the corresponding message will be displayed.</span></p><p> </p><p><span style="font-weight: 400;">In your update-password.ftl page, you can display these unsatisfied policies as a list using FreeMarker.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-e70d98c elementor-widget elementor-widget-code-highlight" data-id="e70d98c" data-element_type="widget" data-widget_type="code-highlight.default">
				<div class="elementor-widget-container">
					<div class="prismjs-default copy-to-clipboard ">
			<pre data-line="" class="highlight-height language-javascript line-numbers">
				<code readonly="true" class="language-javascript">
					<xmp>
    	<#if passwordPolicies?has_content>
        	<div class="${properties.kcAlertClass}">
            	<div class="${properties.kcAlertIconWrapperClass}">
                	<span class="${properties.kcAlertIconClass}"></span>
            	</div>
            	<span class="${properties.kcAlertTitleClass}">
            	${msg("passwordInstruction")} <br>
            	<#list passwordPolicies?keys as key>
                	<span class="${properties.kcAlertTitleClass}">&#x2022; ${passwordPolicies[key]}</span><br/>
            	</#list>
            	</span>
        	</div>
    	</#if>

</xmp>
				</code>
			</pre>
		</div>
				</div>
				</div>
				<div class="elementor-element elementor-element-358fd5c elementor-widget elementor-widget-image" data-id="358fd5c" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img decoding="async" data-attachment-id="7640" data-permalink="https://inero-software.com/configuring-password-policies-in-keycloak/attachment/123206/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/123206.png" data-orig-size="648,510" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="123206" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/123206-300x236.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/123206.png" tabindex="0" role="button" width="648" height="510" src="https://inero-software.com/wp-content/uploads/2025/03/123206.png" class="attachment-large size-large wp-image-7640" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/03/123206.png 648w, https://inero-software.com/wp-content/uploads/2025/03/123206-300x236.png 300w, https://inero-software.com/wp-content/uploads/2025/03/123206-381x300.png 381w, https://inero-software.com/wp-content/uploads/2025/03/123206-380x300.png 380w" sizes="(max-width: 648px) 100vw, 648px" data-attachment-id="7640" data-permalink="https://inero-software.com/configuring-password-policies-in-keycloak/attachment/123206/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/123206.png" data-orig-size="648,510" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="123206" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/123206-300x236.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/123206.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-6d7a6c0 elementor-widget elementor-widget-heading" data-id="6d7a6c0" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Real world policy examples
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-776740f elementor-widget elementor-widget-text-editor" data-id="776740f" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Let&#8217;s see how password policies look in large companies.</span></p><p><span style="font-weight: 400;"> </span></p><p><b>Apple</b><span style="font-weight: 400;"> requires passwords to be at least eight characters long and must include both letters and numbers. Additionally, passwords cannot contain three or more consecutive identical characters and cannot be commonly used passwords.</span></p><p><span style="font-weight: 400;"> </span></p><p><b>Facebook</b><span style="font-weight: 400;"> enforces a minimum password length of more than six characters, although longer passwords are recommended. While Meta does not require the use of special characters or digits, it encourages creating complex passwords.</span></p><p><span style="font-weight: 400;"> </span></p><p><b>Microsoft</b><span style="font-weight: 400;"> passwords must be at least 8 characters long and contain at least two of the following types of characters: uppercase letters, lowercase letters, digits, and symbols. Additionally, it may block the ability to set a password that is too similar to the previous one.</span></p><p><span style="font-weight: 400;">Although these companies use different tools for authentication, it&#8217;s important to consider the security standards implemented in big real-world systems.</span></p><p><span style="font-weight: 400;"> </span></p><p><span style="font-weight: 400;">And despite the fact that these password policies are not extremely restrictive, users should still avoid using sensitive personal information, such as names, birthdates, or phone numbers, in their passwords. Additionally, it&#8217;s essential to avoid reusing passwords across different services, as this can lead to vulnerabilities in case one account is compromised. Employing two-factor authentication (2FA) and periodically reviewing password security are further steps users can take to enhance their protection.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-d64b6d9 elementor-widget elementor-widget-heading" data-id="d64b6d9" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Summary</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-911c3a6 elementor-widget elementor-widget-text-editor" data-id="911c3a6" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">As you can see now, Keycloak provides a set of default password policies that cover standard security rules, such as minimum length, complexity requirements, and password history. These built-in policies are sufficient in many cases, but if needed, there is the option to customize them to meet specific organizational requirements. Keycloak also allows the creation of custom password policies, providing greater control over security.</span></p><p><span style="font-weight: 400;">In addition to customizing policies, Keycloak enables modification of the user interface, which is especially useful when the default display of password policy violations, such as showing unmet requirements individually, does not meet our needs. In such cases, we can change how errors are presented or enrich the messages with additional details to make them more user-friendly.</span></p><p> </p><p><span style="font-weight: 400;">With these options, Keycloak demonstrates a high level of flexibility, allowing full control over security policies and the user interface, making it a versatile solution for identity and access management. The ability to define custom rules and adjust components ensures that Keycloak is a scalable tool that can be easily tailored to the specific needs of an organization.</span></p>						</div>
				</div>
					</div>
				</div>
				</div>
		<p>Artykuł <a href="https://inero-software.com/configuring-password-policies-in-keycloak/">Configuring Password Policies in Keycloak</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7635</post-id>	</item>
		<item>
		<title>Setting Up Passwordless Login with Passkey on a Mobile Device</title>
		<link>https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/</link>
		
		<dc:creator><![CDATA[Marceli Formela]]></dc:creator>
		<pubDate>Wed, 12 Mar 2025 07:47:03 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Company]]></category>
		<category><![CDATA[Keycloak]]></category>
		<category><![CDATA[cybersecurity]]></category>
		<category><![CDATA[IAM]]></category>
		<category><![CDATA[keycloak]]></category>
		<category><![CDATA[login]]></category>
		<category><![CDATA[MFA]]></category>
		<category><![CDATA[mobile]]></category>
		<category><![CDATA[Mobile Device]]></category>
		<category><![CDATA[Multi-Factor Authentication]]></category>
		<category><![CDATA[Passkey]]></category>
		<category><![CDATA[Passwordless]]></category>
		<guid isPermaLink="false">https://inero-software.com/?p=7534</guid>

					<description><![CDATA[<p>This blog focuses on configuring Passkeys specifically for mobile devices, ensuring a seamless and secure passwordless experience.</p>
<p>Artykuł <a href="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/">Setting Up Passwordless Login with Passkey on a Mobile Device</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="7534" class="elementor elementor-7534" data-elementor-post-type="post">
				<div class="elementor-element elementor-element-a40bff4 e-flex e-con-boxed e-con e-parent" data-id="a40bff4" data-element_type="container">
					<div class="e-con-inner">
				<div class="elementor-element elementor-element-8062b20 elementor-widget elementor-widget-html" data-id="8062b20" data-element_type="widget" data-widget_type="html.default">
				<div class="elementor-widget-container">
			 		</div>
				</div>
				<div class="elementor-element elementor-element-5dc3085 elementor-widget elementor-widget-text-editor" data-id="5dc3085" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<h4><strong>In our previous post, we demonstrated how to configure Passkeys in Keycloak, replacing traditional passwords with WebAuthn-based authentication. We covered the setup process, key advantages, and potential limitations, including the challenge of user adoption. This blog focuses on configuring Passkeys specifically for mobile devices, ensuring a seamless and secure passwordless experience.</strong></h4>						</div>
				</div>
				<div class="elementor-element elementor-element-8e87fa0 elementor-widget elementor-widget-text-editor" data-id="8e87fa0" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Our first publication about Passkeys in Keycloak, you can find here: <a href="https://inero-software.com/an-introduction-to-passkey-with-keycloak/">An introduction to Passkey with Keycloak</a></span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-618f1e8 elementor-widget elementor-widget-text-editor" data-id="618f1e8" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">In this post, we’ll dive deeper into optimizing Passkey authentication in Keycloak, looking into a different approach, this time using more than one device.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-9754353 elementor-widget elementor-widget-heading" data-id="9754353" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Using a Passkey stored on a phone</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-f889420 elementor-widget elementor-widget-text-editor" data-id="f889420" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">When logging in on a different device, such as a laptop or desktop, users can authenticate using a Passkey stored on their phone. The process works as follows:</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-823577d elementor-widget elementor-widget-text-editor" data-id="823577d" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<ol><li><strong>Selecting Passkey Login</strong> <br />Instead of entering a password, users choose the Passkey authentication option. The laptop&#8217;s browser generates a request for authentication. Now we have to establish a secure connection between your phone (e.g., iPhone) and your laptop.</li><li><strong>Scanning a QR Code</strong><br />The login interface generates a QR code, which users scan using their phone’s camera. Then the laptop sends a cryptographic challenge to the phone, asking it to sign a request using the stored passkey. The phone communicates securely with the laptop over Bluetooth or other close-range communication protocols (like NFC).</li><li><strong>Confirming Identity</strong> <br />Once the phone receives the challenge, it asks the user for biometric authentication (e.g., Face ID or Touch ID). This verifies that the person attempting the login is the authorized user.</li><li><strong>Secure Authentication</strong> <br />The laptop checks the response from the phone, verifying the cryptographic signature against the public key registered with the service. If the verification is successful, the user is logged in without having to enter a password.</li></ol>						</div>
				</div>
				<div class="elementor-element elementor-element-5edfe44 elementor-widget elementor-widget-heading" data-id="5edfe44" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Step by step: Configuring Passkey with a smartphone</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-b53966d elementor-widget elementor-widget-text-editor" data-id="b53966d" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Before we dive into our custom authentication flow, it&#8217;s important to check if the </span><b>Webauthn Register Passwordless</b><span style="font-weight: 400;"> required action is enabled in the realm (</span><b>Authentication</b><span style="font-weight: 400;"> -&gt; </span><b>Required actions</b><span style="font-weight: 400;"> tab).</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-6d213d0 elementor-widget elementor-widget-image" data-id="6d213d0" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7536" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/12025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/12025-03-11.png" data-orig-size="773,180" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="12025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/12025-03-11-300x70.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/12025-03-11.png" tabindex="0" role="button" width="773" height="180" src="https://inero-software.com/wp-content/uploads/2025/03/12025-03-11.png" class="attachment-large size-large wp-image-7536" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/03/12025-03-11.png 773w, https://inero-software.com/wp-content/uploads/2025/03/12025-03-11-300x70.png 300w, https://inero-software.com/wp-content/uploads/2025/03/12025-03-11-768x179.png 768w" sizes="(max-width: 773px) 100vw, 773px" data-attachment-id="7536" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/12025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/12025-03-11.png" data-orig-size="773,180" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="12025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/12025-03-11-300x70.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/12025-03-11.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-271f72a elementor-widget elementor-widget-text-editor" data-id="271f72a" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">This gives us, for example, the ability to enforce passkey configuration from users after their next successful login. However, it’s important to remember that this is just one of many ways to configure multiple authentication methods.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-456b3a4 elementor-widget elementor-widget-image" data-id="456b3a4" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7537" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/22025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/22025-03-11.png" data-orig-size="616,227" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="22025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/22025-03-11-300x111.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/22025-03-11.png" tabindex="0" role="button" width="616" height="227" src="https://inero-software.com/wp-content/uploads/2025/03/22025-03-11.png" class="attachment-large size-large wp-image-7537" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/03/22025-03-11.png 616w, https://inero-software.com/wp-content/uploads/2025/03/22025-03-11-300x111.png 300w" sizes="(max-width: 616px) 100vw, 616px" data-attachment-id="7537" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/22025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/22025-03-11.png" data-orig-size="616,227" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="22025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/22025-03-11-300x111.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/22025-03-11.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-a3f5cac elementor-widget elementor-widget-text-editor" data-id="a3f5cac" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Once we confirm that this option is active, we can proceed with configuring the authentication flow.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-0950898 elementor-widget elementor-widget-image" data-id="0950898" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7538" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/32025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/32025-03-11.png" data-orig-size="770,452" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="32025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/32025-03-11-300x176.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/32025-03-11.png" tabindex="0" role="button" width="770" height="452" src="https://inero-software.com/wp-content/uploads/2025/03/32025-03-11.png" class="attachment-large size-large wp-image-7538" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/03/32025-03-11.png 770w, https://inero-software.com/wp-content/uploads/2025/03/32025-03-11-300x176.png 300w, https://inero-software.com/wp-content/uploads/2025/03/32025-03-11-768x451.png 768w, https://inero-software.com/wp-content/uploads/2025/03/32025-03-11-511x300.png 511w, https://inero-software.com/wp-content/uploads/2025/03/32025-03-11-512x300.png 512w" sizes="(max-width: 770px) 100vw, 770px" data-attachment-id="7538" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/32025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/32025-03-11.png" data-orig-size="770,452" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="32025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/32025-03-11-300x176.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/32025-03-11.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-87518d4 elementor-widget elementor-widget-text-editor" data-id="87518d4" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">This custom authentication flow for Keycloak is designed to demonstrate how users can choose between password-based authentication and passkey authentication (WebAuthn) during login. Here’s how it works:</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-d372519 elementor-widget elementor-widget-text-editor" data-id="d372519" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<ul><li style="list-style-type: none;"><ul><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Users are required to provide their username to proceed with authentication.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">This step enforces authentication, but users can choose between password-based login or passkey-based login.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">If the user opts for password authentication, they enter their credentials here.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">If the user prefers passwordless authentication using passkeys, they can authenticate using this method instead.</span></li></ul></li></ul>						</div>
				</div>
				<div class="elementor-element elementor-element-5a1acc1 elementor-widget elementor-widget-image" data-id="5a1acc1" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7539" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/42025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/42025-03-11.png" data-orig-size="643,279" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="42025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/42025-03-11-300x130.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/42025-03-11.png" tabindex="0" role="button" width="643" height="279" src="https://inero-software.com/wp-content/uploads/2025/03/42025-03-11.png" class="attachment-large size-large wp-image-7539" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/03/42025-03-11.png 643w, https://inero-software.com/wp-content/uploads/2025/03/42025-03-11-300x130.png 300w" sizes="(max-width: 643px) 100vw, 643px" data-attachment-id="7539" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/42025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/42025-03-11.png" data-orig-size="643,279" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="42025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/42025-03-11-300x130.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/42025-03-11.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-d065fdf elementor-widget elementor-widget-text-editor" data-id="d065fdf" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">In this step, users can enter their username or email to proceed with authentication. This is a required step, ensuring that the system identifies the user before offering authentication options.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-4b5d087 elementor-widget elementor-widget-image" data-id="4b5d087" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7540" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/52025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/52025-03-11.png" data-orig-size="644,292" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="52025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/52025-03-11-300x136.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/52025-03-11.png" tabindex="0" role="button" width="644" height="292" src="https://inero-software.com/wp-content/uploads/2025/03/52025-03-11.png" class="attachment-large size-large wp-image-7540" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/03/52025-03-11.png 644w, https://inero-software.com/wp-content/uploads/2025/03/52025-03-11-300x136.png 300w" sizes="(max-width: 644px) 100vw, 644px" data-attachment-id="7540" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/52025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/52025-03-11.png" data-orig-size="644,292" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="52025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/52025-03-11-300x136.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/52025-03-11.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-a1bfcfe elementor-widget elementor-widget-text-editor" data-id="a1bfcfe" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">At this stage, we can only use password authentication because we haven&#8217;t configured our Passkey (WebAuthn) yet. Once Passkey is set up, users will have the option to choose between password-based and passwordless authentication.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-c2348be elementor-widget elementor-widget-image" data-id="c2348be" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7541" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/62025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/62025-03-11.png" data-orig-size="655,236" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="62025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/62025-03-11-300x108.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/62025-03-11.png" tabindex="0" role="button" width="655" height="236" src="https://inero-software.com/wp-content/uploads/2025/03/62025-03-11.png" class="attachment-large size-large wp-image-7541" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/03/62025-03-11.png 655w, https://inero-software.com/wp-content/uploads/2025/03/62025-03-11-300x108.png 300w" sizes="(max-width: 655px) 100vw, 655px" data-attachment-id="7541" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/62025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/62025-03-11.png" data-orig-size="655,236" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="62025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/62025-03-11-300x108.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/62025-03-11.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-4a740ef elementor-widget elementor-widget-text-editor" data-id="4a740ef" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Instead of registering a device PIN as mentioned earlier, we will use authentication via a phone, specifically an iPhone, in this example</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-8e0e308 elementor-widget elementor-widget-image" data-id="8e0e308" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7542" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/72025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/72025-03-11.png" data-orig-size="558,686" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="72025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/72025-03-11-244x300.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/72025-03-11.png" tabindex="0" role="button" width="558" height="686" src="https://inero-software.com/wp-content/uploads/2025/03/72025-03-11.png" class="attachment-large size-large wp-image-7542" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/03/72025-03-11.png 558w, https://inero-software.com/wp-content/uploads/2025/03/72025-03-11-244x300.png 244w" sizes="(max-width: 558px) 100vw, 558px" data-attachment-id="7542" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/72025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/72025-03-11.png" data-orig-size="558,686" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="72025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/72025-03-11-244x300.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/72025-03-11.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-512ac1c elementor-widget elementor-widget-image" data-id="512ac1c" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7543" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/82025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/82025-03-11.png" data-orig-size="554,704" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="82025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/82025-03-11-236x300.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/82025-03-11.png" tabindex="0" role="button" width="554" height="704" src="https://inero-software.com/wp-content/uploads/2025/03/82025-03-11.png" class="attachment-large size-large wp-image-7543" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/03/82025-03-11.png 554w, https://inero-software.com/wp-content/uploads/2025/03/82025-03-11-236x300.png 236w" sizes="(max-width: 554px) 100vw, 554px" data-attachment-id="7543" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/82025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/82025-03-11.png" data-orig-size="554,704" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="82025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/82025-03-11-236x300.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/82025-03-11.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-579c8d6 elementor-widget elementor-widget-text-editor" data-id="579c8d6" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Now, a QR code should appear, allowing us to register a Passkey on our account. Let&#8217;s scan it using our phone&#8217;s camera and verify the operation, for example, using Face ID.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-e3e3a98 elementor-widget elementor-widget-image" data-id="e3e3a98" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7544" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/92025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/92025-03-11.png" data-orig-size="547,241" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="92025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/92025-03-11-300x132.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/92025-03-11.png" tabindex="0" role="button" width="547" height="241" src="https://inero-software.com/wp-content/uploads/2025/03/92025-03-11.png" class="attachment-large size-large wp-image-7544" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/03/92025-03-11.png 547w, https://inero-software.com/wp-content/uploads/2025/03/92025-03-11-300x132.png 300w" sizes="(max-width: 547px) 100vw, 547px" data-attachment-id="7544" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/92025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/92025-03-11.png" data-orig-size="547,241" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="92025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/92025-03-11-300x132.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/92025-03-11.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-48105ee elementor-widget elementor-widget-text-editor" data-id="48105ee" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Now, our Passkey should be visible in the Credentials section.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-1d1bbc7 elementor-widget elementor-widget-image" data-id="1d1bbc7" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7545" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/102025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/102025-03-11.png" data-orig-size="776,486" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="102025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/102025-03-11-300x188.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/102025-03-11.png" tabindex="0" role="button" width="776" height="486" src="https://inero-software.com/wp-content/uploads/2025/03/102025-03-11.png" class="attachment-large size-large wp-image-7545" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/03/102025-03-11.png 776w, https://inero-software.com/wp-content/uploads/2025/03/102025-03-11-300x188.png 300w, https://inero-software.com/wp-content/uploads/2025/03/102025-03-11-768x481.png 768w, https://inero-software.com/wp-content/uploads/2025/03/102025-03-11-479x300.png 479w" sizes="(max-width: 776px) 100vw, 776px" data-attachment-id="7545" data-permalink="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/102025-03-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/03/102025-03-11.png" data-orig-size="776,486" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="102025-03-11" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/03/102025-03-11-300x188.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/03/102025-03-11.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-7b13102 elementor-widget elementor-widget-text-editor" data-id="7b13102" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">During the next login, we should see the option to choose between password authentication and Passkey authentication.</span></p><p> </p><p><span style="font-weight: 400;">This setup enhances user convenience by allowing them to pick their preferred authentication method. Passkeys provide a more secure and phishing-resistant login experience, while passwords remain available for users who prefer traditional authentication. With this flexibility, we can ensure both security and ease of access for different user preferences.</span></p><p> </p><p><span style="font-weight: 400;">It is worth remembering that traditional passwords are a weak link in digital security, often compromised through reuse, phishing, or data breaches. Passkeys offer a modern, passwordless authentication method that enhances security and usability by leveraging cryptographic key pairs managed by platform authenticators. They provide phishing resistance, seamless multi-device access, and compliance with multi-factor authentication (MFA) standards.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-4a97718 elementor-cta--skin-cover elementor-animated-content elementor-bg-transform elementor-bg-transform-zoom-in elementor-widget elementor-widget-call-to-action" data-id="4a97718" data-element_type="widget" data-widget_type="call-to-action.default">
				<div class="elementor-widget-container">
					<a class="elementor-cta" href="https://inero-software.com/best-keycloak-practices/">
					<div class="elementor-cta__bg-wrapper">
				<div class="elementor-cta__bg elementor-bg" style="background-image: url(https://inero-software.com/wp-content/uploads/2025/01/cta-wm-1-1030x579.png);" role="img" aria-label="cta wm (1)"></div>
				<div class="elementor-cta__bg-overlay"></div>
			</div>
							<div class="elementor-cta__content">
				
									<h2 class="elementor-cta__title elementor-cta__content-item elementor-content-item elementor-animated-item--grow">
						Best Practices in Keycloak: Secure Your System in 5 Steps					</h2>
				
				
									<div class="elementor-cta__button-wrapper elementor-cta__content-item elementor-content-item elementor-animated-item--grow">
					<span class="elementor-cta__button elementor-button elementor-size-">
						Read more 					</span>
					</div>
							</div>
						</a>
				</div>
				</div>
					</div>
				</div>
				</div>
		<p>Artykuł <a href="https://inero-software.com/setting-up-passwordless-login-with-passkey-on-a-mobile-device/">Setting Up Passwordless Login with Passkey on a Mobile Device</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7534</post-id>	</item>
		<item>
		<title>An introduction to Passkey with Keycloak</title>
		<link>https://inero-software.com/an-introduction-to-passkey-with-keycloak/</link>
		
		<dc:creator><![CDATA[Marceli Formela]]></dc:creator>
		<pubDate>Wed, 26 Feb 2025 08:11:28 +0000</pubDate>
				<category><![CDATA[Company]]></category>
		<category><![CDATA[Keycloak]]></category>
		<category><![CDATA[authentication]]></category>
		<category><![CDATA[cybersecurity]]></category>
		<category><![CDATA[digital security]]></category>
		<category><![CDATA[Face ID]]></category>
		<category><![CDATA[IAM]]></category>
		<category><![CDATA[keycloak]]></category>
		<category><![CDATA[Passkey]]></category>
		<category><![CDATA[Touch ID]]></category>
		<guid isPermaLink="false">https://inero-software.com/?p=7417</guid>

					<description><![CDATA[<p>In this blog post, we’ll show you how to set up Passkeys based on the Keycloak. </p>
<p>Artykuł <a href="https://inero-software.com/an-introduction-to-passkey-with-keycloak/">An introduction to Passkey with Keycloak</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="7417" class="elementor elementor-7417" data-elementor-post-type="post">
				<div class="elementor-element elementor-element-55d1eac e-flex e-con-boxed e-con e-parent" data-id="55d1eac" data-element_type="container">
					<div class="e-con-inner">
				<div class="elementor-element elementor-element-6093d86 elementor-widget elementor-widget-html" data-id="6093d86" data-element_type="widget" data-widget_type="html.default">
				<div class="elementor-widget-container">
			 		</div>
				</div>
				<div class="elementor-element elementor-element-05e6799 elementor-widget elementor-widget-text-editor" data-id="05e6799" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<h4><strong>Traditional passwords have long been a weak factor in digital security. They are often reused, easy to compromise, and vulnerable to phishing attacks. Passkeys offer a modern solution by replacing passwords with app-specific cryptographic key pairs managed by platform authenticators. Because passkeys involve multiple authentication touchpoints, they meet multi-factor authentication (MFA) requirements and align with multiple standards.</strong></h4>						</div>
				</div>
				<div class="elementor-element elementor-element-7416163 elementor-widget elementor-widget-text-editor" data-id="7416163" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">In this blog post, we’ll show you how to set up Passkeys based on the Keycloak configuration we&#8217;ve covered in previous posts (check<a href="https://inero-software.com/securing-java-spring-endpoints-with-keycloak/"> Securing Java Spring Endpoints with Keycloak</a></span><span style="font-weight: 400;"> or <a href="https://inero-software.com/hands-on-keycloak-sso-from-setup-to-integration/">Hands-On Keycloak SSO: From Setup to Integration</a></span><span style="font-weight: 400;">). While passkeys promise a seamless and secure authentication experience, integrating them into an existing system can come with its own challenges. We’ll guide you through the basic setup process. If you&#8217;re looking to modernize your authentication strategy, this is the perfect place to start.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-c1afbd0 elementor-widget elementor-widget-heading" data-id="c1afbd0" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">How it works
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-848333b elementor-widget elementor-widget-text-editor" data-id="848333b" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Passkeys are a passwordless authentication method designed to replace traditional passwords with a more secure and convenient alternative. Unlike passwords, which can be phished, stolen, or forgotten, passkeys eliminate these risks by using cryptographic key pairs stored in a trusted authenticator, such as a smartphone, another device, or a password manager. Instead of manually creating and remembering a password, users enable an authenticator to generate and manage a passkey for them. In general, a passkey consists of two parts:</span></p><ul><li style="list-style-type: none;"><ul><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">A public key, which is stored by the application</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">A private key, which remains securely stored in the user&#8217;s authenticator</span></li></ul></li></ul>						</div>
				</div>
				<div class="elementor-element elementor-element-40bb800 elementor-widget elementor-widget-text-editor" data-id="40bb800" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">The private key never leaves the device, ensuring that even if the public key is compromised, accounts remain secure.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-349583e elementor-widget elementor-widget-text-editor" data-id="349583e" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<ol><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">When logging in, the app sends a challenge to the authenticator.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">The user verifies their identity using biometrics (Face ID, Touch ID), a PIN, or a password.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">The authenticator signs the challenge with the private key and sends it back for verification.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">If the signature is valid, access is granted &#8211; without ever needing a password.</span></li></ol>						</div>
				</div>
				<div class="elementor-element elementor-element-1621f94 elementor-widget elementor-widget-image" data-id="1621f94" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7419" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/passkeys-in-keycloak-schema/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/passkeys-in-keycloak-schema.png" data-orig-size="1920,792" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="passkeys in keycloak schema" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/passkeys-in-keycloak-schema-300x124.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/passkeys-in-keycloak-schema-1030x425.png" tabindex="0" role="button" width="1030" height="425" src="https://inero-software.com/wp-content/uploads/2025/02/passkeys-in-keycloak-schema-1030x425.png" class="attachment-large size-large wp-image-7419" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/02/passkeys-in-keycloak-schema-1030x425.png 1030w, https://inero-software.com/wp-content/uploads/2025/02/passkeys-in-keycloak-schema-300x124.png 300w, https://inero-software.com/wp-content/uploads/2025/02/passkeys-in-keycloak-schema-768x317.png 768w, https://inero-software.com/wp-content/uploads/2025/02/passkeys-in-keycloak-schema-1536x634.png 1536w, https://inero-software.com/wp-content/uploads/2025/02/passkeys-in-keycloak-schema-727x300.png 727w, https://inero-software.com/wp-content/uploads/2025/02/passkeys-in-keycloak-schema.png 1920w" sizes="(max-width: 1030px) 100vw, 1030px" data-attachment-id="7419" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/passkeys-in-keycloak-schema/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/passkeys-in-keycloak-schema.png" data-orig-size="1920,792" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="passkeys in keycloak schema" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/passkeys-in-keycloak-schema-300x124.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/passkeys-in-keycloak-schema-1030x425.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-3000e74 elementor-widget elementor-widget-heading" data-id="3000e74" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Advantages of Passkeys
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-b64357e elementor-widget elementor-widget-text-editor" data-id="b64357e" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<ul><li style="list-style-type: none;"><ul><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Unlike passwords, passkeys can’t be stolen through phishing attacks. They are bound to a specific website or app, meaning they won’t work on fake login pages. Even if a user visits a phishing site, their passkey won’t be prompted and won’t sign them in, preventing credential theft.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Users don’t have to manage multiple passwords across accounts. Logging in is as simple as using Face ID, Touch ID, or a device PIN.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Passwords can be guessed, reused, or leaked—passkeys can’t. Even some 2FA methods (like SMS codes) are vulnerable to phishing and SIM-swapping, while passkeys are not. Since passkeys use public-key cryptography, they can’t be stolen or intercepted in a data breach.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Passkeys are stored in platform authenticators (e.g., Google Password Manager, Windows Hello). They can be automatically synced across devices, ensuring access without manual transfers.</span></li></ul></li></ul>						</div>
				</div>
				<div class="elementor-element elementor-element-965d082 elementor-widget elementor-widget-heading" data-id="965d082" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Limitations of Passkeys<br>
</h3>		</div>
				</div>
					</div>
				</div>
		<div class="elementor-element elementor-element-dcd18fa e-flex e-con-boxed e-con e-parent" data-id="dcd18fa" data-element_type="container">
					<div class="e-con-inner">
				<div class="elementor-element elementor-element-fba9537 elementor-widget elementor-widget-text-editor" data-id="fba9537" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<ul><li style="list-style-type: none;"><ul><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Not all websites and applications support passkeys yet, meaning users may still need to rely on passwords for some services.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Losing access to a primary device or cloud account could lock users out, requiring recovery options like backup devices.</span></li><li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Many users are still unfamiliar with passkeys, and the transition away from passwords requires education. Since passkeys don’t require manual entry, users may feel a lack of control over their credentials compared to traditional password management.</span></li></ul></li></ul>						</div>
				</div>
				<div class="elementor-element elementor-element-939f8d6 elementor-widget elementor-widget-heading" data-id="939f8d6" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Configuring Passkey for the Realm
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-5d03766 elementor-widget elementor-widget-text-editor" data-id="5d03766" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Keycloak provides flexible authentication options, traditionally relying on passwords and OTP-based multi-factor authentication (MFA). However, with the rise of passwordless security, Keycloak also supports WebAuthn Passwordless (Passkeys). In this setup, we will disable both passwords and OTP authenticators, ensuring that users can only log in using Passkeys. </span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-eefe7a4 elementor-widget elementor-widget-image" data-id="eefe7a4" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7420" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-241/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-241.png" data-orig-size="692,310" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-241" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-241-300x134.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-241.png" tabindex="0" role="button" width="692" height="310" src="https://inero-software.com/wp-content/uploads/2025/02/2025-02-241.png" class="attachment-large size-large wp-image-7420" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/02/2025-02-241.png 692w, https://inero-software.com/wp-content/uploads/2025/02/2025-02-241-300x134.png 300w, https://inero-software.com/wp-content/uploads/2025/02/2025-02-241-670x300.png 670w" sizes="(max-width: 692px) 100vw, 692px" data-attachment-id="7420" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-241/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-241.png" data-orig-size="692,310" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-241" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-241-300x134.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-241.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-7750103 elementor-widget elementor-widget-text-editor" data-id="7750103" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">The order of authenticators determines the login workflow in Keycloak. We keep the cookie authenticator to allow users to maintain active sessions. To support external authentication, we enable the Identity Provider Redirect, allowing users to log in via upstream providers like Google, or another Keycloak instance. Next, we configure the actual login form. By default, Keycloak&#8217;s browser flow includes username, password, and MFA authentication. We can disable everything in this section and replace it with a single step: adding a WebAuthn Passwordless Authenticator, ensuring that users can only log in using Passkeys. The final flow should look something like this:</span></p><p> </p>						</div>
				</div>
				<div class="elementor-element elementor-element-e24f589 elementor-widget elementor-widget-image" data-id="e24f589" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7421" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-242/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-242.png" data-orig-size="777,655" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-242" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-242-300x253.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-242.png" tabindex="0" role="button" width="777" height="655" src="https://inero-software.com/wp-content/uploads/2025/02/2025-02-242.png" class="attachment-large size-large wp-image-7421" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/02/2025-02-242.png 777w, https://inero-software.com/wp-content/uploads/2025/02/2025-02-242-300x253.png 300w, https://inero-software.com/wp-content/uploads/2025/02/2025-02-242-768x647.png 768w, https://inero-software.com/wp-content/uploads/2025/02/2025-02-242-356x300.png 356w" sizes="(max-width: 777px) 100vw, 777px" data-attachment-id="7421" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-242/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-242.png" data-orig-size="777,655" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-242" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-242-300x253.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-242.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-805cc08 elementor-widget elementor-widget-text-editor" data-id="805cc08" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Once the WebAuthn Passwordless Authenticator is set up, the next step is to bind the authenticator to the browser login flow.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-b6799ff elementor-widget elementor-widget-image" data-id="b6799ff" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7422" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-243/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-243.png" data-orig-size="691,219" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-243" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-243-300x95.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-243.png" tabindex="0" role="button" width="691" height="219" src="https://inero-software.com/wp-content/uploads/2025/02/2025-02-243.png" class="attachment-large size-large wp-image-7422" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/02/2025-02-243.png 691w, https://inero-software.com/wp-content/uploads/2025/02/2025-02-243-300x95.png 300w" sizes="(max-width: 691px) 100vw, 691px" data-attachment-id="7422" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-243/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-243.png" data-orig-size="691,219" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-243" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-243-300x95.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-243.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-3dae270 elementor-widget elementor-widget-text-editor" data-id="3dae270" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Now, all that’s left is to force a password reset for our sample user by setting the required action to </span><b>WebAuthn Register Passwordless</b><span style="font-weight: 400;">.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-f474406 elementor-widget elementor-widget-image" data-id="f474406" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7423" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-24-4/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-4.png" data-orig-size="721,298" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-24 4" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-4-300x124.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-4.png" tabindex="0" role="button" width="721" height="298" src="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-4.png" class="attachment-large size-large wp-image-7423" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-4.png 721w, https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-4-300x124.png 300w" sizes="(max-width: 721px) 100vw, 721px" data-attachment-id="7423" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-24-4/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-4.png" data-orig-size="721,298" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-24 4" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-4-300x124.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-4.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-64055b7 elementor-widget elementor-widget-text-editor" data-id="64055b7" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">After clicking the link in the received email, Keycloak will display a dialog instructing the user to </span><b>register their passkey</b><span style="font-weight: 400;">.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-c19dcb2 elementor-widget elementor-widget-image" data-id="c19dcb2" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7424" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-24-5/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-5.png" data-orig-size="677,329" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-24 5" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-5-300x146.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-5.png" tabindex="0" role="button" width="677" height="329" src="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-5.png" class="attachment-large size-large wp-image-7424" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-5.png 677w, https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-5-300x146.png 300w, https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-5-617x300.png 617w" sizes="(max-width: 677px) 100vw, 677px" data-attachment-id="7424" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-24-5/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-5.png" data-orig-size="677,329" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-24 5" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-5-300x146.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-5.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-dd5a7c2 elementor-widget elementor-widget-text-editor" data-id="dd5a7c2" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Just click to register the passkey.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-9ea11f9 elementor-widget elementor-widget-image" data-id="9ea11f9" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7425" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-24-6/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-6.png" data-orig-size="574,231" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-24 6" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-6-300x121.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-6.png" tabindex="0" role="button" width="574" height="231" src="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-6.png" class="attachment-large size-large wp-image-7425" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-6.png 574w, https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-6-300x121.png 300w" sizes="(max-width: 574px) 100vw, 574px" data-attachment-id="7425" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-24-6/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-6.png" data-orig-size="574,231" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-24 6" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-6-300x121.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-6.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-c0e48a0 elementor-widget elementor-widget-text-editor" data-id="c0e48a0" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Your device&#8217;s platform authenticator will appear showing available options for confirming the user&#8217;s identity. Let&#8217;s assume we want to use Windows Hello and confirm identity with a PIN code &#8211; the same that is used when logging into the Windows account.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-2239416 elementor-widget elementor-widget-image" data-id="2239416" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7426" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-24-7/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-7.png" data-orig-size="532,670" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-24 7" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-7-238x300.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-7.png" tabindex="0" role="button" width="532" height="670" src="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-7.png" class="attachment-large size-large wp-image-7426" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-7.png 532w, https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-7-238x300.png 238w" sizes="(max-width: 532px) 100vw, 532px" data-attachment-id="7426" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-24-7/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-7.png" data-orig-size="532,670" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-24 7" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-7-238x300.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-7.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-4a3627a elementor-widget elementor-widget-image" data-id="4a3627a" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7427" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-24-8/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-8.png" data-orig-size="555,359" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-24 8" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-8-300x194.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-8.png" tabindex="0" role="button" width="555" height="359" src="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-8.png" class="attachment-large size-large wp-image-7427" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-8.png 555w, https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-8-300x194.png 300w, https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-8-464x300.png 464w" sizes="(max-width: 555px) 100vw, 555px" data-attachment-id="7427" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-24-8/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-8.png" data-orig-size="555,359" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-24 8" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-8-300x194.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-8.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-af69320 elementor-widget elementor-widget-text-editor" data-id="af69320" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">The passkey should now be visible in the credentials section of the specified user.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-7a17718 elementor-widget elementor-widget-image" data-id="7a17718" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7428" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-24/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24.png" data-orig-size="781,480" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-24" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-300x184.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24.png" tabindex="0" role="button" width="781" height="480" src="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24.png" class="attachment-large size-large wp-image-7428" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24.png 781w, https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-300x184.png 300w, https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-768x472.png 768w, https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-488x300.png 488w" sizes="(max-width: 781px) 100vw, 781px" data-attachment-id="7428" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-24/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24.png" data-orig-size="781,480" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-24" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-300x184.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-a0801c8 elementor-widget elementor-widget-text-editor" data-id="a0801c8" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span id="docs-internal-guid-cd93915a-7fff-644a-0cbb-415915617b42"><span style="font-size: 12pt; font-family: Arial, sans-serif; color: #000000; background-color: transparent; font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-variant-position: normal; font-variant-emoji: normal; vertical-align: baseline; white-space-collapse: preserve;">Now we can go to the realm&#8217;s login page and try using our passkey instead of the standard username and password.</span></span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-5b7fcf8 elementor-widget elementor-widget-image" data-id="5b7fcf8" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7429" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-24-9/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-9.png" data-orig-size="586,201" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-24 9" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-9-300x103.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-9.png" tabindex="0" role="button" width="586" height="201" src="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-9.png" class="attachment-large size-large wp-image-7429" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-9.png 586w, https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-9-300x103.png 300w" sizes="(max-width: 586px) 100vw, 586px" data-attachment-id="7429" data-permalink="https://inero-software.com/an-introduction-to-passkey-with-keycloak/2025-02-24-9/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-9.png" data-orig-size="586,201" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-02-24 9" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-9-300x103.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/2025-02-24-9.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-077cb4b elementor-widget elementor-widget-text-editor" data-id="077cb4b" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Your platform authenticator should appear again, offering to use the registered passkey.</span></p><p> </p><p><span style="font-weight: 400;">Passkeys aren’t perfect, but their benefits outweigh their drawbacks for most users. As adoption increases, many of these limitations will be addressed. However, in the short term, users and organizations need to be aware of potential challenges when integrating passkeys into their authentication workflows. Organizations seeking to integrate passkeys into their authentication systems can leverage tools like Keycloak. By integrating passkeys into Keycloak, organizations can provide users with secure, passwordless access to applications while still benefiting from Keycloak’s major features like Single Sign-On (SSO), multi-factor authentication (MFA), and fine-grained access control.</span></p>						</div>
				</div>
					</div>
				</div>
				</div>
		<p>Artykuł <a href="https://inero-software.com/an-introduction-to-passkey-with-keycloak/">An introduction to Passkey with Keycloak</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7417</post-id>	</item>
		<item>
		<title>Behind the Scenes #2: Implementing email-based MFA in Keycloak</title>
		<link>https://inero-software.com/behind-the-scenes-2-implementing-email-based-mfa-in-keycloak/</link>
		
		<dc:creator><![CDATA[Marceli Formela]]></dc:creator>
		<pubDate>Thu, 13 Feb 2025 09:50:32 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Company]]></category>
		<category><![CDATA[Keycloak]]></category>
		<category><![CDATA[2FA]]></category>
		<category><![CDATA[emial]]></category>
		<category><![CDATA[IAM]]></category>
		<category><![CDATA[keycloak]]></category>
		<category><![CDATA[MFA]]></category>
		<category><![CDATA[Multi-Factor Authentication]]></category>
		<category><![CDATA[OTP]]></category>
		<guid isPermaLink="false">https://inero-software.com/?p=7042</guid>

					<description><![CDATA[<p>In this post, we’ll explore a custom MFA implementation that sends a one-time authentication code to the user’s email.</p>
<p>Artykuł <a href="https://inero-software.com/behind-the-scenes-2-implementing-email-based-mfa-in-keycloak/">Behind the Scenes #2: Implementing email-based MFA in Keycloak</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="7042" class="elementor elementor-7042" data-elementor-post-type="post">
				<div class="elementor-element elementor-element-091b893 e-flex e-con-boxed e-con e-parent" data-id="091b893" data-element_type="container">
					<div class="e-con-inner">
		<div class="elementor-element elementor-element-628ea76 e-con-full e-flex e-con e-child" data-id="628ea76" data-element_type="container">
				</div>
		<div class="elementor-element elementor-element-9ca8a9e e-con-full e-flex e-con e-child" data-id="9ca8a9e" data-element_type="container">
				<div class="elementor-element elementor-element-edd1fd0 elementor-widget elementor-widget-html" data-id="edd1fd0" data-element_type="widget" data-widget_type="html.default">
				<div class="elementor-widget-container">
			 		</div>
				</div>
				<div class="elementor-element elementor-element-3e56066 elementor-widget elementor-widget-text-editor" data-id="3e56066" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<h5><strong>Keycloak natively supports many secure login solutions and comes with built-in one-time password (OTP) mechanisms, such as authentication via mobile apps like Google Authenticator or our solution <a href="https://inero-software.com/introducing-authm8-a-free-cross-platform-2fa-solution-tailored-to-your-brand-for-secure-authentication/">AuthM8</a>. However, if we want to use other advanced authentication methods and for example send OTP codes via email, then similar to SMS multi factor authentication (more details <a href="https://inero-software.com/custom-sms-authenticator-with-keycloak/">HERE</a>), we need to implement this functionality ourselves. In this post, we’ll explore a custom MFA implementation that sends a one-time authentication code to the user’s email. </strong></h5>						</div>
				</div>
				<div class="elementor-element elementor-element-0994f82 elementor-widget elementor-widget-heading" data-id="0994f82" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">How does email-based MFA work?
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-8e8909e elementor-widget elementor-widget-text-editor" data-id="8e8909e" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p>The authentication process consists of two main stages:</p>						</div>
				</div>
				<div class="elementor-element elementor-element-8435873 elementor-widget elementor-widget-text-editor" data-id="8435873" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<ul><li style="list-style-type: none;"><ul><li><b style="color: var( --e-global-color-text ); text-align: var(--text-align);">Generating and sending the MFA code</b></li></ul></li></ul><p><span style="font-weight: 400;">If the user already has an active cookie confirming a previous MFA verification, they should be immediately authenticated. Otherwise, Keycloak creates a new credential for the user and generates a one-time code based on configurable parameters like length or time-to-live.  The code is stored in the user’s credentials and then is emailed using the email provider.</span></p><p> </p><ul><li style="list-style-type: none;"><ul><li aria-level="1"><b>Verifying the entered code</b></li></ul></li></ul><p><span style="font-weight: 400;">When a user submits the code, KC retrieves the stored credential and compares the entered value. If the code is correct and still valid (not expired), authentication is successful, and a cookie is set to remember the verification. If the code is incorrect, the user is prompted to re-enter it and if the code has expired, an error message is shown and the process must be restarted.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-d65460b elementor-widget elementor-widget-image" data-id="d65460b" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7044" data-permalink="https://inero-software.com/behind-the-scenes-2-implementing-email-based-mfa-in-keycloak/email-based-two-factor-authentication-flowchart/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/EMAIL-BASED-TWO-FACTOR-AUTHENTICATION-FLOWCHART.png" data-orig-size="1920,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="EMAIL-BASED TWO-FACTOR AUTHENTICATION FLOWCHART" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/EMAIL-BASED-TWO-FACTOR-AUTHENTICATION-FLOWCHART-300x169.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/EMAIL-BASED-TWO-FACTOR-AUTHENTICATION-FLOWCHART-1030x579.png" tabindex="0" role="button" width="1030" height="579" src="https://inero-software.com/wp-content/uploads/2025/02/EMAIL-BASED-TWO-FACTOR-AUTHENTICATION-FLOWCHART-1030x579.png" class="attachment-large size-large wp-image-7044" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/02/EMAIL-BASED-TWO-FACTOR-AUTHENTICATION-FLOWCHART-1030x579.png 1030w, https://inero-software.com/wp-content/uploads/2025/02/EMAIL-BASED-TWO-FACTOR-AUTHENTICATION-FLOWCHART-300x169.png 300w, https://inero-software.com/wp-content/uploads/2025/02/EMAIL-BASED-TWO-FACTOR-AUTHENTICATION-FLOWCHART-768x432.png 768w, https://inero-software.com/wp-content/uploads/2025/02/EMAIL-BASED-TWO-FACTOR-AUTHENTICATION-FLOWCHART-1536x864.png 1536w, https://inero-software.com/wp-content/uploads/2025/02/EMAIL-BASED-TWO-FACTOR-AUTHENTICATION-FLOWCHART-533x300.png 533w, https://inero-software.com/wp-content/uploads/2025/02/EMAIL-BASED-TWO-FACTOR-AUTHENTICATION-FLOWCHART.png 1920w" sizes="(max-width: 1030px) 100vw, 1030px" data-attachment-id="7044" data-permalink="https://inero-software.com/behind-the-scenes-2-implementing-email-based-mfa-in-keycloak/email-based-two-factor-authentication-flowchart/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/EMAIL-BASED-TWO-FACTOR-AUTHENTICATION-FLOWCHART.png" data-orig-size="1920,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="EMAIL-BASED TWO-FACTOR AUTHENTICATION FLOWCHART" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/EMAIL-BASED-TWO-FACTOR-AUTHENTICATION-FLOWCHART-300x169.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/EMAIL-BASED-TWO-FACTOR-AUTHENTICATION-FLOWCHART-1030x579.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-5925a75 elementor-widget elementor-widget-heading" data-id="5925a75" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default"><strong data-start="157" data-end="185">Email MFA: Pros and Cons</strong> </h3>		</div>
				</div>
				<div class="elementor-element elementor-element-3c6c4e2 elementor-widget elementor-widget-text-editor" data-id="3c6c4e2" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Email-based MFA offers additional security when the primary factor, such as a password, has been compromised. This is particularly helpful in cases where passwords are brute-forced or easily guessed, such as with common combinations like 123456. Similarly, this solution offers protection against credential stuffing, where attackers use leaked passwords from other breaches to attempt logging into account.</span></p><p><span style="font-weight: 400;">There are several other benefits to using email as a MFA:</span></p><ul><li style="list-style-type: none;"><ul><li aria-level="1"><span style="font-weight: 400;">Email MFA does not require users to provide additional sensitive information, such as a phone number, reducing concerns about privacy.</span></li></ul></li></ul><ul><li style="list-style-type: none;"><ul><li aria-level="1"><span style="font-weight: 400;">It does not require users to install a separate app or complete a complicated setup, which simplifies the process.</span></li></ul></li></ul><ul><li style="list-style-type: none;"><ul><li aria-level="1"><span style="font-weight: 400;"> </span><span style="font-weight: 400;">Users are accustomed to providing their email for various purposes, such as receiving important account updates or resetting passwords. This familiarity makes it more accessible.</span></li></ul></li></ul><p><span style="font-weight: 400;">However, email as a delivery channel does have some drawbacks. If an attacker compromises your email (gains access to an email account through stolen credentials or by exploiting an active session.), they could potentially reset other accounts’ passwords as well. For users in vulnerable situations, such as those with access to shared devices, email-based MFA can still leave them exposed. As with any security measure, it’s essential to weigh the benefits against the potential risks and mix email MFA with other safeguards, such as strong passwords policy and secure email practices.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-4fd89fe elementor-widget elementor-widget-heading" data-id="4fd89fe" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Implementing Email MFA</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-cfc16d2 elementor-widget elementor-widget-image" data-id="cfc16d2" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7045" data-permalink="https://inero-software.com/behind-the-scenes-2-implementing-email-based-mfa-in-keycloak/zrzut-ekranu-2025-02-13-102335/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102335.png" data-orig-size="755,508" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Zrzut ekranu 2025-02-13 102335" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102335-300x202.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102335.png" tabindex="0" role="button" width="755" height="508" src="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102335.png" class="attachment-large size-large wp-image-7045" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102335.png 755w, https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102335-300x202.png 300w, https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102335-446x300.png 446w" sizes="(max-width: 755px) 100vw, 755px" data-attachment-id="7045" data-permalink="https://inero-software.com/behind-the-scenes-2-implementing-email-based-mfa-in-keycloak/zrzut-ekranu-2025-02-13-102335/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102335.png" data-orig-size="755,508" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Zrzut ekranu 2025-02-13 102335" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102335-300x202.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102335.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-295f2c1 elementor-widget elementor-widget-text-editor" data-id="295f2c1" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">In this modified Browser Authentication Flow, we integrate our custom MFA as an additional authentication method. There are two new steps:</span></p><ul><li style="list-style-type: none;"><ul><li style="font-weight: 400;" aria-level="1"><b>MFA Email setup</b><span style="font-weight: 400;"> – this step ensures that email is set up and verified for the user before proceeding. If the user does not have a custom MFA Credential (which stores OTP codes as secrets), it will be set as well.</span></li></ul></li></ul>						</div>
				</div>
				<div class="elementor-element elementor-element-1cb9fd2 elementor-widget elementor-widget-text-editor" data-id="1cb9fd2" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<pre><span style="font-weight: 400;">public class MfaEmailSetupAuthenticator implements Authenticator, CredentialValidator&lt;MfaEmailCredentialProvider&gt; {</span><br /><span style="font-weight: 400;">@Override</span><br /><span style="font-weight: 400;">public void authenticate(AuthenticationFlowContext context) {</span><br /><span style="font-weight: 400;">[…]</span><br /><span style="font-weight: 400;">// Require email verification</span><br /><span style="font-weight: 400;">if (!userModel.isEmailVerified()) {</span><br /><span style="font-weight: 400;">userModel.addRequiredAction(UserModel.RequiredAction.VERIFY_EMAIL);</span><br /><span style="font-weight: 400;">}</span><br /><span style="font-weight: 400;">// Add MFA email credential if not present</span><br /><span style="font-weight: 400;">if (!getCredentialProvider(context.getSession()).isConfiguredFor(realmModel, userModel, MfaEmailCredentialModel.TYPE)) {</span><br /><span style="font-weight: 400;">userModel.credentialManager().createStoredCredential(new MfaEmailCredentialModel(new MfaEmailCredentialData()));</span><br /><span style="font-weight: 400;">}</span><br /><span style="font-weight: 400;">[…]</span></pre>						</div>
				</div>
				<div class="elementor-element elementor-element-6908dab elementor-widget__width-initial elementor-widget elementor-widget-image" data-id="6908dab" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7046" data-permalink="https://inero-software.com/behind-the-scenes-2-implementing-email-based-mfa-in-keycloak/zrzut-ekranu-2025-02-13-102520/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102520.png" data-orig-size="635,398" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Zrzut ekranu 2025-02-13 102520" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102520-300x188.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102520.png" tabindex="0" role="button" width="635" height="398" src="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102520.png" class="attachment-large size-large wp-image-7046" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102520.png 635w, https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102520-300x188.png 300w, https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102520-479x300.png 479w" sizes="(max-width: 635px) 100vw, 635px" data-attachment-id="7046" data-permalink="https://inero-software.com/behind-the-scenes-2-implementing-email-based-mfa-in-keycloak/zrzut-ekranu-2025-02-13-102520/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102520.png" data-orig-size="635,398" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Zrzut ekranu 2025-02-13 102520" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102520-300x188.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102520.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-eafd6c8 elementor-widget elementor-widget-text-editor" data-id="eafd6c8" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<ul><li style="list-style-type: none;"><ul><li style="font-weight: 400;" aria-level="1"><b>MFA Email Authentication</b><span style="font-weight: 400;"> – this is the actual authentication step where a one-time code is sent via email. Marked as Alternative, meaning it can be used instead of other MFA methods like mobile app OTP.</span></li></ul></li></ul><p><span style="font-weight: 400;">Here, you can see how the configuration of this authenticator could look like in the Keycloak authentication flow.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-bdcf27f elementor-widget__width-initial elementor-widget elementor-widget-image" data-id="bdcf27f" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7047" data-permalink="https://inero-software.com/behind-the-scenes-2-implementing-email-based-mfa-in-keycloak/zrzut-ekranu-2025-02-13-102652/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102652.png" data-orig-size="473,622" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Zrzut ekranu 2025-02-13 102652" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102652-228x300.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102652.png" tabindex="0" role="button" width="473" height="622" src="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102652.png" class="attachment-large size-large wp-image-7047" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102652.png 473w, https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102652-228x300.png 228w" sizes="(max-width: 473px) 100vw, 473px" data-attachment-id="7047" data-permalink="https://inero-software.com/behind-the-scenes-2-implementing-email-based-mfa-in-keycloak/zrzut-ekranu-2025-02-13-102652/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102652.png" data-orig-size="473,622" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Zrzut ekranu 2025-02-13 102652" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102652-228x300.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-102652.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-10b800d elementor-widget elementor-widget-text-editor" data-id="10b800d" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<ul><li style="list-style-type: none;"><ul><li style="font-weight: 400;" aria-level="1"><b>Max Cookie Age</b><span style="font-weight: 400;"> this setting determines how long the MFA session (cookie) is valid. If the cookie is still valid, the user won&#8217;t be prompted for MFA. </span></li><li style="font-weight: 400;" aria-level="1"><b>Time-to-live</b><span style="font-weight: 400;"> indicates the lifetime of the MFA code.</span></li></ul></li></ul><p> </p><p><span style="font-weight: 400;">Now let’s take a look at the code. </span></p><p> </p><p><span style="font-weight: 400;">The method below handles the MFA process itself. If a valid cookie exists (indicating that the user has already completed MFA), the method immediately returns success, meaning the authentication flow is complete without requiring additional actions.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-89fa524 elementor-widget elementor-widget-text-editor" data-id="89fa524" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<pre><span style="font-weight: 400;">@Override</span><br /><span style="font-weight: 400;">public void authenticate(AuthenticationFlowContext context) {</span><br /><span style="font-weight: 400;">if (hasValidCookie(context)) {</span><br /><span style="font-weight: 400;">context.success();</span><br /><span style="font-weight: 400;">return;</span><br /><span style="font-weight: 400;">}</span><br /><span style="font-weight: 400;">[…]</span></pre>						</div>
				</div>
				<div class="elementor-element elementor-element-55ff859 elementor-widget elementor-widget-text-editor" data-id="55ff859" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">If there is no cookie, we should try to retrieve the user’s existing MFA credential from the credential provider. If the user doesn’t have one, a new instance is created using the MfaEmailCredentialModel which just extends the built-in CredentialModel:</span><span style="font-weight: 400;"><br /></span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-0af0624 elementor-widget elementor-widget-text-editor" data-id="0af0624" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<pre><span style="font-weight: 400;">[…]</span><br /><span style="font-weight: 400;">// get existing credential or create a new one</span><br /><span style="font-weight: 400;">CredentialModel credentialModel = getCredentialProvider(session)</span><br /><span style="font-weight: 400;">.getDefaultCredential(session, context.getRealm(), user);</span><br /><span style="font-weight: 400;">if (credentialModel == null) {</span><br /><span style="font-weight: 400;">credentialModel = user.credentialManager().createStoredCredential(new MfaEmailCredentialModel(new MfaEmailCredentialData()));</span><br /><span style="font-weight: 400;">}</span><br /><span style="font-weight: 400;">[…]</span></pre>						</div>
				</div>
				<div class="elementor-element elementor-element-c7af14a elementor-widget elementor-widget-text-editor" data-id="c7af14a" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Then the authenticate method reads configuration properties like code length and TTL (time-to-live). The code itself can be generated using some utils method and will be stored as the secretData in the credential model.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-6551375 elementor-widget elementor-widget-text-editor" data-id="6551375" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<pre><span style="font-weight: 400;">// generate and store code</span><br /><span style="font-weight: 400;">int length = Integer.parseInt(configMap.get(CONFIG_CODE_LENGTH));</span><br /><span style="font-weight: 400;">int ttl = Integer.parseInt(configMap.get(CONFIG_CODE_TTL));</span><br /><span style="font-weight: 400;">String code = MfaEmailCodesUtils.generateCode(length);</span><br /><span style="font-weight: 400;">credentialModel.setSecretData(code);</span><br /><span style="font-weight: 400;">user.credentialManager().updateStoredCredential(credentialModel);</span><br /><span style="font-weight: 400;">AuthenticationSessionModel authSession = context.getAuthenticationSession();</span><br /><span style="font-weight: 400;">authSession.setAuthNote("ttl", Long.toString(System.currentTimeMillis() + (ttl * 1000L)));</span></pre>						</div>
				</div>
				<div class="elementor-element elementor-element-b7f4d62 elementor-widget elementor-widget-text-editor" data-id="b7f4d62" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">In the end the sendCode method is called to send the generated code to the user’s email. If the email is sent successfully, the method presents the form where the user can enter the MFA code.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-dc63501 elementor-widget elementor-widget-text-editor" data-id="dc63501" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<pre><span style="font-weight: 400;">// send email and show input form</span><br /><span style="font-weight: 400;">try {</span><br /><span style="font-weight: 400;">MfaEmailCodesUtils.sendCode(session, user, ttl, code, configMap);</span><br /><span style="font-weight: 400;">context.challenge(context.form().setAttribute("realm", context.getRealm()).createForm(TPL_CODE));</span><br /><span style="font-weight: 400;">} catch (Exception e) {</span><br /><span style="font-weight: 400;">context.failureChallenge(AuthenticationFlowError.INTERNAL_ERROR,</span><br /><span style="font-weight: 400;">context.form().setError("mfaEmailNotSent", e.getMessage())  .createErrorPage(Response.Status.INTERNAL_SERVER_ERROR));</span><br /><span style="font-weight: 400;">}</span></pre>						</div>
				</div>
				<div class="elementor-element elementor-element-b41ad7b elementor-widget elementor-widget-text-editor" data-id="b41ad7b" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">The second major part of our Authenticator is the action method which handles the validation of the code entered by the user. It is invoked when the user submits the input form after receiving the email.  </span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-9551f9f elementor-widget__width-initial elementor-widget elementor-widget-image" data-id="9551f9f" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="7048" data-permalink="https://inero-software.com/behind-the-scenes-2-implementing-email-based-mfa-in-keycloak/zrzut-ekranu-2025-02-13-103114/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-103114.png" data-orig-size="663,391" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Zrzut ekranu 2025-02-13 103114" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-103114-300x177.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-103114.png" tabindex="0" role="button" width="663" height="391" src="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-103114.png" class="attachment-large size-large wp-image-7048" alt="" srcset="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-103114.png 663w, https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-103114-300x177.png 300w, https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-103114-509x300.png 509w" sizes="(max-width: 663px) 100vw, 663px" data-attachment-id="7048" data-permalink="https://inero-software.com/behind-the-scenes-2-implementing-email-based-mfa-in-keycloak/zrzut-ekranu-2025-02-13-103114/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-103114.png" data-orig-size="663,391" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Zrzut ekranu 2025-02-13 103114" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-103114-300x177.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/02/Zrzut-ekranu-2025-02-13-103114.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-460cfb7 elementor-widget elementor-widget-text-editor" data-id="460cfb7" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">The method retrieves the user’s credential from the provider and then the code is validated by checking it against the stored credential using the custom isValid method.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-ff19a7e elementor-widget elementor-widget-text-editor" data-id="ff19a7e" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<pre><span style="font-weight: 400;">[…]</span><br /><span style="font-weight: 400;">final MfaEmailCredentialModel credentialModel = getCredentialProvider(session)</span><br /><span style="font-weight: 400;">        .getDefaultCredential(session, context.getRealm(), user);</span><br /><span style="font-weight: 400;">boolean isValid = getCredentialProvider(session).isValid(context.getRealm(), user,</span><br /><span style="font-weight: 400;">    </span> <span style="font-weight: 400;">new UserCredentialModel(credentialModel.getId(), getCredentialProvider(context.getSession()).getType(), enteredCode));</span><br /><span style="font-weight: 400;">[…]</span></pre>						</div>
				</div>
				<div class="elementor-element elementor-element-7b502f8 elementor-widget elementor-widget-text-editor" data-id="7b502f8" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">If the code is valid, the next step is to check if it is expired. We can also set a cookie that stores the MFA session to prevent the user from </span><b>being prompted for MFA again</b><span style="font-weight: 400;"> during the cookie’s validity period.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-3db7437 elementor-widget elementor-widget-text-editor" data-id="3db7437" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<pre><span style="font-weight: 400;">[…]</span><br /><span style="font-weight: 400;">// valid</span><br /><span style="font-weight: 400;">HttpResponse response = context.getSession().getContext().getHttpResponse();</span><br /><span style="font-weight: 400;">response.setCookieIfAbsent(createCookie(context));</span><br /><span style="font-weight: 400;">context.success();</span><br /><span style="font-weight: 400;">[…]</span></pre><p><span style="font-weight: 400;"> </span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-83cf638 elementor-widget elementor-widget-text-editor" data-id="83cf638" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Of course, in this post, we will not cover the entire topic, omitting implementation details such as sending the code, generating the code, validation, and creating our custom cookie.</span></p><p><span style="font-weight: 400;"><br></span></p>
<p><span style="font-weight: 400;">However, we have walked through the major steps of implementing 2FA using email-based codes. On the one hand, this approach offers a simple and accessible solution. Although it has its drawbacks, using it in solutions like Keycloak helps mitigate many of these vulnerabilities. Keycloak also provides the flexibility to combine email-based MFA with other security measures, creating a more layered and resilient authentication process that can help protect against evolving cybersecurity threats.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-a27180c elementor-cta--skin-cover elementor-animated-content elementor-bg-transform elementor-bg-transform-zoom-in elementor-widget elementor-widget-call-to-action" data-id="a27180c" data-element_type="widget" data-widget_type="call-to-action.default">
				<div class="elementor-widget-container">
					<div class="elementor-cta">
					<div class="elementor-cta__bg-wrapper">
				<div class="elementor-cta__bg elementor-bg" style="background-image: url(https://inero-software.com/wp-content/uploads/2024/11/tlo-popup-keycloak-1030x731.png);" role="img" aria-label="tło popup keycloak"></div>
				<div class="elementor-cta__bg-overlay"></div>
			</div>
							<div class="elementor-cta__content">
				
									<h3 class="elementor-cta__title elementor-cta__content-item elementor-content-item elementor-animated-item--grow">
						Do you need help configuring multi-factor authentication?					</h3>
				
									<div class="elementor-cta__description elementor-cta__content-item elementor-content-item elementor-animated-item--grow">
						Schedule a meeting to find out how we can help you.					</div>
				
									<div class="elementor-cta__button-wrapper elementor-cta__content-item elementor-content-item elementor-animated-item--grow">
					<a class="elementor-cta__button elementor-button elementor-size-" href="https://calendar.google.com/calendar/u/0/appointments/schedules/AcZssZ3e3C_1YeBkt1uCr_qfOnG_N298UgLFwORcSTXigrPfOk0ls3ok-Uw_dSeGCoLdtYsN13GMm-n-">
						Schedule a meeting					</a>
					</div>
							</div>
						</div>
				</div>
				</div>
				</div>
		<div class="elementor-element elementor-element-6bc7752 e-con-full e-flex e-con e-child" data-id="6bc7752" data-element_type="container">
				</div>
					</div>
				</div>
		<div class="elementor-element elementor-element-091ddaf e-flex e-con-boxed e-con e-parent" data-id="091ddaf" data-element_type="container">
					<div class="e-con-inner">
					</div>
				</div>
				</div>
		<p>Artykuł <a href="https://inero-software.com/behind-the-scenes-2-implementing-email-based-mfa-in-keycloak/">Behind the Scenes #2: Implementing email-based MFA in Keycloak</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">7042</post-id>	</item>
		<item>
		<title>Keycloak Migration Made Easy: Tips and Best Practices</title>
		<link>https://inero-software.com/keycloak-migration-made-easy-tips-and-best-practices/</link>
		
		<dc:creator><![CDATA[Marceli Formela]]></dc:creator>
		<pubDate>Tue, 28 Jan 2025 12:57:28 +0000</pubDate>
				<category><![CDATA[Company]]></category>
		<category><![CDATA[Keycloak]]></category>
		<category><![CDATA[keycloak]]></category>
		<category><![CDATA[Keycloak Migration]]></category>
		<category><![CDATA[Multi-Factor Authentication]]></category>
		<guid isPermaLink="false">https://inero-software.com/?p=6799</guid>

					<description><![CDATA[<p>Here we’ll explore the most significant changes introduced in recent Keycloak releases and how they impact migration efforts. We’ll walk through practical examples to resolve common challenges, ensuring a smooth transition to newer versions. Whether it’s adapting to updated configurations or managing deprecated features, this post should provide additional tips&#8230;</p>
<p>Artykuł <a href="https://inero-software.com/keycloak-migration-made-easy-tips-and-best-practices/">Keycloak Migration Made Easy: Tips and Best Practices</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="6799" class="elementor elementor-6799" data-elementor-post-type="post">
				<div class="elementor-element elementor-element-bc9a077 e-flex e-con-boxed e-con e-parent" data-id="bc9a077" data-element_type="container">
					<div class="e-con-inner">
		<div class="elementor-element elementor-element-bef05bd e-con-full e-flex e-con e-child" data-id="bef05bd" data-element_type="container">
				</div>
		<div class="elementor-element elementor-element-27ad504 e-con-full e-flex e-con e-child" data-id="27ad504" data-element_type="container">
				<div class="elementor-element elementor-element-e3a7faf elementor-widget elementor-widget-html" data-id="e3a7faf" data-element_type="widget" data-widget_type="html.default">
				<div class="elementor-widget-container">
			 		</div>
				</div>
				<div class="elementor-element elementor-element-5d77ce3 elementor-widget elementor-widget-text-editor" data-id="5d77ce3" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<h4><span style="font-weight: 400;">Here we’ll explore the most significant changes introduced in recent Keycloak releases and how they impact migration efforts. We’ll walk through practical examples to resolve common challenges, ensuring a smooth transition to newer versions. Whether it’s adapting to updated configurations or managing deprecated features, this post should provide additional tips to streamline your Keycloak migration process.</span></h4>						</div>
				</div>
				<div class="elementor-element elementor-element-9055b0b elementor-widget elementor-widget-heading" data-id="9055b0b" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Migrating to Quarkus distribution
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-c8c79fe elementor-widget elementor-widget-text-editor" data-id="c8c79fe" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">One of the most challenging migrations for many users has been the upgrade to Keycloak 17, where the underlying architecture shifted from WildFly to the Quarkus framework. This transition marked a significant departure from the traditional application server model, requiring users to adopt a more modern, lightweight approach tailored to Quarkus. The way Keycloak is configured has fundamentally changed &#8211; rather than deploying it on an external application server, it now operates as a standalone application, which simplifies deployment.</span></p><p><span style="font-weight: 400;">For example, custom providers, which were previously packaged dynamically as modules for WildFly, now need to be rebuilt and adapted (as runtime is immutable), involving changes to dependencies, classloading, and packaging methods. This design simplifies deployments in environments like Kubernetes but demands a shift in workflows for teams accustomed to the WildFly solutions. While the move to Quarkus offers performance gains and a more modern development experience, it still requires careful planning and testing to ensure a smooth migration.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-e39fb62 elementor-widget elementor-widget-heading" data-id="e39fb62" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Key changes introduced in new releases
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-9267062 elementor-widget elementor-widget-text-editor" data-id="9267062" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Migration introduces important changes that impact configuration, endpoints, and custom provider implementations:</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-4465d06 elementor-widget elementor-widget-text-editor" data-id="4465d06" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<ul><li><b>HTTPS requirement for production mode </b><span style="font-weight: 400;">&#8211; starting Keycloak with the command [keycloak_quarkus_root]/26.1.0/bin/kc.bat start now requires an HTTPS certificate, as the start option is intended for production use. For local development, the start-dev option should be used instead.</span></li><li><b>removal of /auth from base path</b><span style="font-weight: 400;"> &#8211; the /auth segment has been removed from the default base path. Applications relying on Keycloak endpoints must update their configurations to reflect this change. </span></li><li><b>realm ID changes </b><span style="font-weight: 400;">&#8211; in previous versions, the realm ID was identical to the realm name. Starting from Keycloak 21, the realm ID is now a unique, system-generated value. Applications relying on realm IDs should account for this change during migration.</span></li><li><b>deprecation of userLocalStorage</b><span style="font-weight: 400;"> &#8211; custom providers using the userLocalStorage method of the KeycloakSession interface must switch to the users method, as userLocalStorage was deprecated starting from Keycloak 19.</span></li><li><b>transport jdbc-ping as new default</b><span style="font-weight: 400;"> &#8211; in the latest version of Keycloak (26.1.0), the default method for discovering other nodes within a cluster has shifted to using its database, rather than relying on just multicast. This change eliminates the need for additional network configurations, particularly in cloud environments.</span></li></ul>						</div>
				</div>
				<div class="elementor-element elementor-element-f8db805 elementor-widget elementor-widget-heading" data-id="f8db805" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Issues with major migrations</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-c547a32 elementor-widget elementor-widget-text-editor" data-id="c547a32" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">When migrating Keycloak, it’s highly recommended to upgrade version by version, rather than jumping several releases at once. This incremental approach allows you to identify and resolve issues as they arise, minimizing the risk of unexpected complications. Upgrading across multiple versions—especially if spanning a dozen or more releases—can significantly complicate the process due to accumulated changes, deprecated features, and architectural shifts like the move to Quarkus. By addressing compatibility and configuration adjustments one step at a time, you ensure better control over the migration and reduce downtime or disruptions in production environments.</span></p><p><span style="font-weight: 400;">However, in many cases, a large one-time migration—such as moving from Keycloak 12 directly to Keycloak 26—is unavoidable and becomes a challenge that teams must address effectively. This process often involves significant changes to both the Keycloak server and dependent applications, particularly frontend clients that rely on its APIs. </span></p><p><span style="font-weight: 400;">In this guide, we’ll outline a practical step-by-step approach to such a major migration. </span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-45823ad elementor-widget elementor-widget-heading" data-id="45823ad" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Dockerfile configuration</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-ce32e89 elementor-widget elementor-widget-text-editor" data-id="ce32e89" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">In our example project, all custom themes and SPI (Service Provider Interface) extensions were directly copied into the base Keycloak image without a dedicated build process. So it was done in a standard Wildfly way.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-4796eb9 elementor-widget elementor-widget-text-editor" data-id="4796eb9" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<pre><span style="font-weight: 400;">FROM </span><span style="font-weight: 400;">quay.io</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">keycloak</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">keycloak:</span><span style="font-weight: 400;">12.0.2<br /></span><span style="font-weight: 400;"><br /></span><span style="font-weight: 400;">COPY </span><span style="font-weight: 400;">themes</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">custom-theme </span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">opt</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">jboss</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">keycloak</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">themes/custom-theme</span><span style="font-weight: 400;"><br /></span><span style="font-weight: 400;">COPY </span><span style="font-weight: 400;">api-extensions</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">target</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">spi-resource-0</span><span style="font-weight: 400;">.0.1</span><span style="font-weight: 400;">-</span><span style="font-weight: 400;">SNAPSHOT.jar<br /></span><span style="font-weight: 400;"><br /></span><span style="font-weight: 400;">ENTRYPOINT /</span><span style="font-weight: 400;">opt</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">jboss</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">tools</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">docker-entrypoint.sh </span><span style="font-weight: 400;">-</span><span style="font-weight: 400;">b </span><span style="font-weight: 400;">0.0.0.0</span></pre>						</div>
				</div>
				<div class="elementor-element elementor-element-b1c75ea elementor-widget elementor-widget-text-editor" data-id="b1c75ea" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">The new approach could use a multi-stage process with separate containers like:</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-2f2a2de elementor-widget elementor-widget-text-editor" data-id="2f2a2de" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<pre><span style="font-weight: 400;">FROM </span><span style="font-weight: 400;">eclipse-temurin:17-jdk as </span><i><span style="font-weight: 400;">spi_builder</span></i><br /><i><span style="font-weight: 400;">[…]</span></i><br /><span style="font-weight: 400;">FROM </span><span style="font-weight: 400;">quay.io</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">keycloak</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">keycloak:$</span><i><span style="font-weight: 400;">BASE_IMAGE_TAG </span></i><span style="font-weight: 400;">as </span><i><span style="font-weight: 400;">keycloak_builder</span></i><br /><span style="font-weight: 400;">[…]</span><br /><span style="font-weight: 400;">FROM </span><span style="font-weight: 400;">quay.io</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">keycloak</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">keycloak:$</span><i><span style="font-weight: 400;">BASE_IMAGE_TAG</span></i></pre>						</div>
				</div>
				<div class="elementor-element elementor-element-a527627 elementor-widget elementor-widget-text-editor" data-id="a527627" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">The SPI is built during the container build process using Maven. This approach ensures that the dependencies are fetched and the resulting JAR is optimized for deployment.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-0510f11 elementor-widget elementor-widget-text-editor" data-id="0510f11" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<pre><span style="font-weight: 400;">### Runtime dependencies build container</span><br /><span style="font-weight: 400;">FROM </span><span style="font-weight: 400;">registry.access.redhat.com</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">ubi9 </span><span style="font-weight: 400;">AS </span><i><span style="font-weight: 400;">runtime_dependencies_builder</span></i><br /><span style="font-weight: 400;">RUN </span><span style="font-weight: 400;">mkdir </span><span style="font-weight: 400;">-</span><span style="font-weight: 400;">p </span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">mnt</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">rootfs</span><br /><br /><span style="font-weight: 400;">RUN </span><span style="font-weight: 400;">dnf </span><span style="font-weight: 400;">install </span><span style="font-weight: 400;">--</span><span style="font-weight: 400;">installroot </span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">mnt</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">rootfs curl </span><span style="font-weight: 400;">--</span><span style="font-weight: 400;">releasever </span><span style="font-weight: 400;">9 </span><span style="font-weight: 400;">--</span><span style="font-weight: 400;">setopt install_weak_deps=false </span><span style="font-weight: 400;">--</span><span style="font-weight: 400;">nodocs </span><span style="font-weight: 400;">-</span><span style="font-weight: 400;">y \</span><br /><span style="font-weight: 400;">&amp;&amp; </span><span style="font-weight: 400;">dnf </span><span style="font-weight: 400;">--</span><span style="font-weight: 400;">installroot </span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">mnt</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">rootfs clean all</span><br /><br /><span style="font-weight: 400;">### SPI build container</span><br /><span style="font-weight: 400;">FROM </span><span style="font-weight: 400;">eclipse-temurin:17-jdk as </span><i><span style="font-weight: 400;">spi_builder</span></i><br /><span style="font-weight: 400;">ARG </span><i><span style="font-weight: 400;">BASE_IMAGE_TAG</span></i><br /><span style="font-weight: 400;">WORKDIR /</span><span style="font-weight: 400;">workspace</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">app</span><br /><br /><span style="font-weight: 400;">COPY </span><span style="font-weight: 400;">api-extensions</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">mvnw .</span><br /><span style="font-weight: 400;">COPY </span><span style="font-weight: 400;">api-extensions</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">.mvn .mvn</span><br /><span style="font-weight: 400;">COPY </span><span style="font-weight: 400;">api-extensions</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">pom.xml .</span><br /><br /><span style="font-weight: 400;"># dos2unix:</span><br /><span style="font-weight: 400;">RUN </span><span style="font-weight: 400;">sed </span><span style="font-weight: 400;">-</span><span style="font-weight: 400;">i </span><span style="font-weight: 400;">-</span><span style="font-weight: 400;">e </span><span style="font-weight: 400;">'s/\r//g' </span><span style="font-weight: 400;">mvnw</span><br /><span style="font-weight: 400;">RUN </span><span style="font-weight: 400;">./mvnw </span><span style="font-weight: 400;">dependency:go-offline</span><br /><span style="font-weight: 400;">COPY </span><span style="font-weight: 400;">api-extensions</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">src src</span><br /><span style="font-weight: 400;">RUN </span><span style="font-weight: 400;">./mvnw </span><span style="font-weight: 400;">-</span><span style="font-weight: 400;">o package </span><span style="font-weight: 400;">-</span><span style="font-weight: 400;">DskipTests</span><br /><span style="font-weight: 400;"> </span></pre>						</div>
				</div>
				<div class="elementor-element elementor-element-9851247 elementor-widget elementor-widget-text-editor" data-id="9851247" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">The new process copies multiple custom themes into the Quarkus-based Keycloak during the build stage, ensuring they are included in the final optimized runtime. So this approach improves startup performance and aligns with immutable container philosophy.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-0cd6583 elementor-widget elementor-widget-text-editor" data-id="0cd6583" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<pre><span style="font-weight: 400;">### Build container</span><br /><span style="font-weight: 400;">FROM </span><span style="font-weight: 400;">quay.io</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">keycloak</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">keycloak:$</span><i><span style="font-weight: 400;">BASE_IMAGE_TAG </span></i><span style="font-weight: 400;">as </span><i><span style="font-weight: 400;">keycloak_builder</span></i><br /><span style="font-weight: 400;">COPY --</span><span style="font-weight: 400;">from=</span><i><span style="font-weight: 400;">spi_builder </span></i><span style="font-weight: 400;">/</span><span style="font-weight: 400;">workspace</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">app</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">target</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">spi-resource-0</span><span style="font-weight: 400;">.0.1</span><span style="font-weight: 400;">-</span><span style="font-weight: 400;">SNAPSHOT-jar-with-dependencies.jar </span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">opt</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">keycloak</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">providers</span><span style="font-weight: 400;">/</span><br /><br /><span style="font-weight: 400;">#Copy custom themes</span><br /><span style="font-weight: 400;">COPY </span><span style="font-weight: 400;">themes</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">custom-theme </span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">opt</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">keycloak</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">themes</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">custom-theme</span><br /><br /><span style="font-weight: 400;">#Build an optimized server runtime</span><br /><span style="font-weight: 400;">RUN </span><span style="font-weight: 400;">/opt/keycloak/bin/kc.sh </span><span style="font-weight: 400;">build</span><br /><br /><span style="font-weight: 400;">### Runtime container</span><br /><span style="font-weight: 400;">FROM </span><a href="http://quay.io/keycloak/keycloak:$BASE_IMAGE_TAG"><span style="font-weight: 400;">quay.io/keycloak/keycloak:$</span><i><span style="font-weight: 400;">BASE_IMAGE_TAG</span></i></a><br /><span style="font-weight: 400;">COPY --</span><span style="font-weight: 400;">from=</span><i><span style="font-weight: 400;">keycloak_builder </span></i><span style="font-weight: 400;">/</span><span style="font-weight: 400;">opt</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">keycloak</span><span style="font-weight: 400;">/ /</span><span style="font-weight: 400;">opt</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">keycloak</span><span style="font-weight: 400;">/</span><br /><span style="font-weight: 400;">WORKDIR /</span><span style="font-weight: 400;">opt</span><span style="font-weight: 400;">/</span><span style="font-weight: 400;">keycloak</span><br /><span style="font-weight: 400;">ENTRYPOINT </span><span style="font-weight: 400;">[</span><span style="font-weight: 400;">"/opt/keycloak/bin/kc.sh"</span><span style="font-weight: 400;">]</span></pre>						</div>
				</div>
				<div class="elementor-element elementor-element-1dc220a elementor-widget elementor-widget-text-editor" data-id="1dc220a" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Basically, by leveraging multi-stage builds and lightweight images, the new process aligns with best practices for containerized deployments. You can find more details about these steps here: </span><a href="https://www.keycloak.org/server/containers"><span style="font-weight: 400;">https://www.keycloak.org/server/containers</span></a><span style="font-weight: 400;">.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-15c9000 elementor-widget elementor-widget-heading" data-id="15c9000" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Default /auth context path changed
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-2ff8164 elementor-widget elementor-widget-text-editor" data-id="2ff8164" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">With the transition to the Quarkus-based Keycloak distribution, the default context path has been modified—/auth is no longer part of the URL by default. This change aligns with Quarkus’s goal of providing a more streamlined and minimalistic approach to web applications, reducing unnecessary path prefixes.</span></p><p><span style="font-weight: 400;">For users or applications that still require the /auth context path, it can be reintroduced using the http-relative-path build option. For instance, running Keycloak with the following command restores the /auth context:</span></p><p><b><i>bin/kc.[sh|bat] start-dev &#8211;http-relative-path /auth</i></b></p><p><span style="font-weight: 400;">Or using a docker-compose way:</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-2ee41e2 elementor-widget elementor-widget-text-editor" data-id="2ee41e2" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<pre><span style="font-weight: 400;">KC_HTTP_RELATIVE_PATH</span><span style="font-weight: 400;">: /auth</span></pre>						</div>
				</div>
				<div class="elementor-element elementor-element-27a0144 elementor-widget elementor-widget-text-editor" data-id="27a0144" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">This allows for compatibility with existing clients or configurations that rely on the /auth prefix. With the relative path specified, Keycloak will still automatically redirect requests from the root (e.g., localhost:8080/) to the /auth path (e.g., localhost:8080/auth). This ensures that applications or users accustomed to the previous URL structure continue to function as expected without requiring major changes.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-24a1365 elementor-widget elementor-widget-heading" data-id="24a1365" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Changes within provider management
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-557e06a elementor-widget elementor-widget-text-editor" data-id="557e06a" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">With the shift to the Quarkus-based Keycloak distribution, there are significant changes in how custom providers (SPIs) are deployed and managed. In the WildFly-based distribution, custom providers were deployed by copying them into the </span><b><i>standalone/deployments</i></b><span style="font-weight: 400;"> directory, and dependencies were also placed in specific locations within the WildFly server structure. However, in the new Quarkus distribution, this deployment model has been streamlined. Custom providers should now be copied into the </span><b><i>/providers</i></b><span style="font-weight: 400;"> directory.</span></p><p><span style="font-weight: 400;">Additionally, Quarkus does not support the EAR packaging format or the jboss-deployment-structure.xml files, which were commonly used in the WildFly distribution to configure deployments and manage dependencies. As a result, the packaging process is simplified, but custom configurations previously made through these files must now be handled differently.</span></p><p><span style="font-weight: 400;">Furthermore, if custom providers utilized JavaEE APIs, such as session or stateless beans, these will no longer be supported in the Quarkus distribution.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-7391d60 elementor-widget elementor-widget-heading" data-id="7391d60" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Migrating custom themes
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-c0ccfee elementor-widget elementor-widget-text-editor" data-id="c0ccfee" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Old Keycloak relied on the FreeMarker template engine for rendering dynamic content in themes. This approach is still used in new releases (especially in v1 and v2 themes), but there have been updates to the template syntax and theme structure to align with the new Quarkus architecture. Custom templates may need to be revised to ensure compatibility with newer versions of FreeMarker, as the theme structure may have evolved.</span></p><p><span style="font-weight: 400;">Additionally, certain legacy template functions and macros that were present in, for example Keycloak 12, might have been deprecated or replaced with new, more efficient alternatives.</span></p><p><span style="font-weight: 400;">Custom themes that were previously customized are likely not optimized for dark mode. To avoid complications without having to rewrite them from scratch, the simplest solution is to add the appropriate option </span><b><i>darkMode=false</i></b><span style="font-weight: 400;"> in the </span><b><i>theme.properties</i></b><span style="font-weight: 400;"> file. Additionally, starting from version 26.1.0, the &#8220;Themes&#8221; tab now includes switches that allow for enabling dark mode on a per-realm basis.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-a573147 elementor-widget elementor-widget-heading" data-id="a573147" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Making new Keycloak server work with legacy frontend client
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-21c6dc8 elementor-widget elementor-widget-text-editor" data-id="21c6dc8" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><b>checkLoginIframe related issues</b></p><p><span style="font-weight: 400;">In one of our projects, we had to upgrade Keycloak by 14 versions. However, for various reasons, we couldn&#8217;t migrate the frontend, which was running on a rather old version of Angular and the keycloak-angular library. Therefore, we will now go through the tweaks we had to apply in order to restore the login process functionality.</span></p><p><span style="font-weight: 400;">Keycloak-angular is a wrapper library for keycloak-js that makes using it easier in Angular applications. It extends the original features with additional functionality and adds new methods to make it easier to use within an Angular app. It also provides a basic implementation of AuthGuard, allowing you to customize your logic by using the authentication logic. It’s also possible to use the HttpClient Interceptor, which adds an authorization header to selected HTTP requests.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-43ca3b8 elementor-widget elementor-widget-text-editor" data-id="43ca3b8" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<pre><span style="font-weight: 400;">"keycloak-angular"</span><span style="font-weight: 400;">: </span><span style="font-weight: 400;">"^8.1.0"</span><span style="font-weight: 400;">,</span><br /><span style="font-weight: 400;">"keycloak-js"</span><span style="font-weight: 400;">: </span><span style="font-weight: 400;">"^12.0.4"</span><span style="font-weight: 400;">,</span></pre>						</div>
				</div>
				<div class="elementor-element elementor-element-2699e08 elementor-widget elementor-widget-text-editor" data-id="2699e08" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">After integrating the new version of Keycloak (26.1.0) with the old frontend client, we encountered an issue after logging in, which manifested as follows:</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-81f2826 elementor-widget elementor-widget-image" data-id="81f2826" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="6801" data-permalink="https://inero-software.com/keycloak-migration-made-easy-tips-and-best-practices/2025-01-28/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/01/2025-01-28.png" data-orig-size="538,317" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-01-28" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/01/2025-01-28-300x177.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/01/2025-01-28.png" tabindex="0" role="button" width="480" height="317" src="https://inero-software.com/wp-content/uploads/2025/01/2025-01-28-480x317.png" class="attachment-septera-lpbox-2 size-septera-lpbox-2 wp-image-6801" alt="" data-attachment-id="6801" data-permalink="https://inero-software.com/keycloak-migration-made-easy-tips-and-best-practices/2025-01-28/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/01/2025-01-28.png" data-orig-size="538,317" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-01-28" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/01/2025-01-28-300x177.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/01/2025-01-28.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-91587be elementor-widget elementor-widget-text-editor" data-id="91587be" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">This option specifies whether Keycloak should check the login status using an iframe. It should be used with caution, as improper configuration may lead to issues such as continuous page reloads. Newer versions of Keycloak may have improved or changed session management, particularly around cross-site cookies, authentication flows, or iframe handling (setupCheckLoginIframe, check3pCookiesSupported). These changes could affect how the frontend handles login states, especially if it is using deprecated methods for checking login states or processing callbacks.</span></p><p><span style="font-weight: 400;">Given the significant version gap between the frontend and the server, one useful approach might be to </span><b>disable the setupCheckLoginIframe option</b><span style="font-weight: 400;">, which could also help in situations where infinite redirect loops occur after the upgrade.</span></p><p><span style="font-weight: 400;">Here’s an example of how to disable it in your initialization:</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-f530026 elementor-widget elementor-widget-text-editor" data-id="f530026" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<pre><span style="font-weight: 400;">function </span><span style="font-weight: 400;">initializeKeycloak</span><span style="font-weight: 400;">(keycloak: KeycloakService, permissionsService: PermissionsService) </span><br /><span style="font-weight: 400;">{</span><br /><span style="font-weight: 400;">  </span><span style="font-weight: 400;">return </span><span style="font-weight: 400;">() =&gt;</span><br /><span style="font-weight: 400;">    keycloak.</span><span style="font-weight: 400;">init</span><span style="font-weight: 400;">({</span><br /><br /><span style="font-weight: 400;">  </span> <span style="font-weight: 400;">config</span><span style="font-weight: 400;">: {</span><br /><span style="font-weight: 400;">    </span> <span style="font-weight: 400;">url</span><span style="font-weight: 400;">: </span><i><span style="font-weight: 400;">environment</span></i><span style="font-weight: 400;">.</span><span style="font-weight: 400;">keycloakUrl</span><span style="font-weight: 400;">,</span><br /><span style="font-weight: 400;">    </span> <span style="font-weight: 400;">realm</span><span style="font-weight: 400;">: </span><span style="font-weight: 400;">'test-realm'</span><span style="font-weight: 400;">,</span><br /><span style="font-weight: 400;">    </span> <span style="font-weight: 400;">clientId</span><span style="font-weight: 400;">: </span><span style="font-weight: 400;">'test-realm-web'</span><span style="font-weight: 400;">,</span><br /><span style="font-weight: 400;">  </span> <span style="font-weight: 400;">},</span><br /><span style="font-weight: 400;">  </span> <span style="font-weight: 400;">initOptions</span><span style="font-weight: 400;">: {</span><br /><span style="font-weight: 400;">        </span><span style="font-weight: 400;">checkLoginIframe</span><span style="font-weight: 400;">: </span><span style="font-weight: 400;">false</span><br /><span style="font-weight: 400;">  </span> <span style="font-weight: 400;">}</span><br /><span style="font-weight: 400;">}).</span><span style="font-weight: 400;">then</span><span style="font-weight: 400;">(() =&gt; permissionsService.</span><span style="font-weight: 400;">init</span><span style="font-weight: 400;">());</span><br /><span style="font-weight: 400;">}</span></pre>						</div>
				</div>
				<div class="elementor-element elementor-element-eaf0ada elementor-widget elementor-widget-heading" data-id="eaf0ada" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Missing nonce claim
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-9e105aa elementor-widget elementor-widget-text-editor" data-id="9e105aa" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">In newer versions of Keycloak, in accordance with the OpenID Connect Core 1.0 specification, the nonce claim is now only added to the ID token if the parameter was included in the authorization request. According to the specification, the nonce claim is mandatory in the ID token but should not be included in tokens after a refresh request. Previously, nonce was added to all tokens (Access, Refresh, and ID) in all responses, including refresh responses.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-fc3ca51 elementor-widget elementor-widget-image" data-id="fc3ca51" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="6802" data-permalink="https://inero-software.com/keycloak-migration-made-easy-tips-and-best-practices/2025-01-28-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/01/2025-01-28-2.png" data-orig-size="716,448" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-01-28 -2" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/01/2025-01-28-2-300x188.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/01/2025-01-28-2.png" tabindex="0" role="button" width="512" height="300" src="https://inero-software.com/wp-content/uploads/2025/01/2025-01-28-2-512x300.png" class="attachment-septera-featured-third size-septera-featured-third wp-image-6802" alt="" data-attachment-id="6802" data-permalink="https://inero-software.com/keycloak-migration-made-easy-tips-and-best-practices/2025-01-28-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2025/01/2025-01-28-2.png" data-orig-size="716,448" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2025-01-28 -2" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2025/01/2025-01-28-2-300x188.png" data-large-file="https://inero-software.com/wp-content/uploads/2025/01/2025-01-28-2.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-8016f49 elementor-widget elementor-widget-text-editor" data-id="8016f49" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">As a result, using an older version of the keycloak-js adapter may cause login issues, such as &#8220;Invalid nonce, clearing token&#8221; errors or an infinite redirection loop after login attempts. To resolve this, users can add the predefined &#8220;Nonce backwards compatible&#8221; mapper via the &#8220;By Configuration&#8221; button in the dedicated client scope. More information can be found in the official Keycloak documentation </span><span style="font-weight: 400;">(</span><a href="https://www.keycloak.org/docs/latest/upgrading/index.html#nonce-claim-is-only-added-to-the-id-token"><span style="font-weight: 400;">https://www.keycloak.org/docs/latest/upgrading/index.html#nonce-claim-is-only-added-to-the-id-token</span></a><span style="font-weight: 400;">)</span><span style="font-weight: 400;">.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-5c61c2e elementor-widget elementor-widget-heading" data-id="5c61c2e" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Post-logout redirect URI issues
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-26180df elementor-widget elementor-widget-text-editor" data-id="26180df" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">According to the release notes for version 18, Keycloak no longer supports the redirect_uri parameter for logging out. Instead, you need to use post_logout_redirect_uri along with either the client_id or id_token_hint parameter. In practice, this means when calling the logout function, you must replace redirect_uri with post_logout_redirect_uri. In our case (with legacy keycloak-js), the logout process can be implemented like this:</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-a8f685a elementor-widget elementor-widget-text-editor" data-id="a8f685a" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<pre><i><span style="font-weight: 400;">window</span></i><span style="font-weight: 400;">.</span><span style="font-weight: 400;">location</span><span style="font-weight: 400;">.</span><span style="font-weight: 400;">replace</span><span style="font-weight: 400;">(</span><span style="font-weight: 400;">this</span><span style="font-weight: 400;">.</span><span style="font-weight: 400;">keycloak</span><span style="font-weight: 400;">[</span><span style="font-weight: 400;">'_instance'</span><span style="font-weight: 400;">][</span><span style="font-weight: 400;">'endpoints'</span><span style="font-weight: 400;">].</span><span style="font-weight: 400;">logout</span><span style="font-weight: 400;">() +</span><span style="font-weight: 400;"><br /></span><span style="font-weight: 400;">   </span><span style="font-weight: 400;">'?post_logout_redirect_uri=' </span><span style="font-weight: 400;">+ </span><span style="font-weight: 400;">encodeURIComponent</span><span style="font-weight: 400;">(</span><i><span style="font-weight: 400;">window</span></i><span style="font-weight: 400;">.</span><span style="font-weight: 400;">location</span><span style="font-weight: 400;">.</span><span style="font-weight: 400;">origin</span><span style="font-weight: 400;">) +</span><span style="font-weight: 400;"><br /></span><span style="font-weight: 400;">   </span><span style="font-weight: 400;">'&amp;client_id=test-realm-web'</span><span style="font-weight: 400;">);</span></pre>						</div>
				</div>
				<div class="elementor-element elementor-element-d4ca7eb elementor-widget elementor-widget-text-editor" data-id="d4ca7eb" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">This change should resolve the most common issues with redirects after logging out of the application.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-20e2094 elementor-widget elementor-widget-heading" data-id="20e2094" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Summary
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-5633025 elementor-widget elementor-widget-text-editor" data-id="5633025" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Over the past few years, Keycloak has undergone significant changes, particularly with the breaking changes introduced during the migration from WildFly to Quarkus. These changes were necessary for performance improvements, more efficient resource usage, and better scalability.</span></p><p><span style="font-weight: 400;">While the migration process can appear challenging, it is generally achievable, even when working with older clients. However, the ease of migration largely depends on the specific use case, especially the level of customization involved. For instance, if themes were highly customized in the previous version of Keycloak, adapting them to newer distributions may require more time and effort, as the structure and templating engines have evolved.</span></p><p><span style="font-weight: 400;">Similarly, integrations with legacy systems might need careful planning to ensure compatibility with newer versions of Keycloak. On the other hand, for standard setups with minimal customization, the transition is often smoother and quicker. The process of migration can also be supported by detailed documentation and a strong community, which has grown significantly in recent years.</span></p><p><span style="font-weight: 400;">Overall, while each migration project has its own challenges, with proper planning and testing, transitioning to a newer version of Keycloak is generally not so complicated, and the long-term benefits of the upgrade, such as improved performance and security features, make it worth the effort.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-c667383 elementor-cta--skin-cover elementor-animated-content elementor-bg-transform elementor-bg-transform-zoom-in elementor-widget elementor-widget-call-to-action" data-id="c667383" data-element_type="widget" data-widget_type="call-to-action.default">
				<div class="elementor-widget-container">
					<div class="elementor-cta">
					<div class="elementor-cta__bg-wrapper">
				<div class="elementor-cta__bg elementor-bg" style="background-image: url(https://inero-software.com/wp-content/uploads/2024/12/1-1030x1030.png);" role="img" aria-label="1"></div>
				<div class="elementor-cta__bg-overlay"></div>
			</div>
							<div class="elementor-cta__content">
				
									<h2 class="elementor-cta__title elementor-cta__content-item elementor-content-item elementor-animated-item--grow">
						Are you planning to implement Keycloak in your organization? 					</h2>
				
									<div class="elementor-cta__description elementor-cta__content-item elementor-content-item elementor-animated-item--grow">
						If you're looking for a partner to provide comprehensive support in this process, be sure to contact us.					</div>
				
									<div class="elementor-cta__button-wrapper elementor-cta__content-item elementor-content-item elementor-animated-item--grow">
					<a class="elementor-cta__button elementor-button elementor-size-" href="https://calendar.app.google/CiGcgpfTyvVHDizZ8">
						Schedule a conversation					</a>
					</div>
							</div>
						</div>
				</div>
				</div>
				</div>
		<div class="elementor-element elementor-element-bece524 e-con-full e-flex e-con e-child" data-id="bece524" data-element_type="container">
				</div>
					</div>
				</div>
		<div class="elementor-element elementor-element-54593f6 e-flex e-con-boxed e-con e-parent" data-id="54593f6" data-element_type="container">
					<div class="e-con-inner">
					</div>
				</div>
				</div>
		<p>Artykuł <a href="https://inero-software.com/keycloak-migration-made-easy-tips-and-best-practices/">Keycloak Migration Made Easy: Tips and Best Practices</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6799</post-id>	</item>
		<item>
		<title>Hands-On Keycloak SSO: From Setup to Integration</title>
		<link>https://inero-software.com/hands-on-keycloak-sso-from-setup-to-integration/</link>
		
		<dc:creator><![CDATA[Marceli Formela]]></dc:creator>
		<pubDate>Tue, 17 Dec 2024 08:31:09 +0000</pubDate>
				<category><![CDATA[Company]]></category>
		<category><![CDATA[Keycloak]]></category>
		<guid isPermaLink="false">https://inero-software.com/?p=6504</guid>

					<description><![CDATA[<p>SSO is a protocol that allows users to authenticate and gain access to multiple applications using a single set of credentials.</p>
<p>Artykuł <a href="https://inero-software.com/hands-on-keycloak-sso-from-setup-to-integration/">Hands-On Keycloak SSO: From Setup to Integration</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="6504" class="elementor elementor-6504" data-elementor-post-type="post">
				<div class="elementor-element elementor-element-1493b19 e-flex e-con-boxed e-con e-parent" data-id="1493b19" data-element_type="container">
					<div class="e-con-inner">
		<div class="elementor-element elementor-element-68a6464 e-con-full e-flex e-con e-child" data-id="68a6464" data-element_type="container">
				</div>
		<div class="elementor-element elementor-element-c7adbf7 e-con-full e-flex e-con e-child" data-id="c7adbf7" data-element_type="container">
				<div class="elementor-element elementor-element-3a1b9b4 elementor-widget elementor-widget-html" data-id="3a1b9b4" data-element_type="widget" data-widget_type="html.default">
				<div class="elementor-widget-container">
			 		</div>
				</div>
				<div class="elementor-element elementor-element-e6791c3 elementor-widget elementor-widget-text-editor" data-id="e6791c3" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<h4><strong>One of the biggest benefits Keycloak provides in almost every use case is Single Sign-On (SSO). This greatly enhances user management and simplifies authentication processes within company applications and provides an effective solution to address security challenges. Today, we’ll explore how it works and how to set up an example integration.</strong></h4>						</div>
				</div>
				<div class="elementor-element elementor-element-fe586fe elementor-widget elementor-widget-heading" data-id="fe586fe" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">SSO (Single Sign-On)
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-d084fd9 elementor-widget elementor-widget-text-editor" data-id="d084fd9" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">SSO is a protocol that allows users to authenticate and gain access to multiple applications using a single set of credentials. This approach is highly convenient, as it eliminates the need for users to remember multiple passwords or log in repeatedly. Beyond this, SSO enhances security by reducing risks associated with weak, reused, or lost passwords when properly implemented.</span></p><p><span style="font-weight: 400;">The center of an SSO system is the identity provider (IdP), which works like a central authentication server. When users log into their first application, they are redirected to the IdP, where they provide their credentials. Upon successful authentication, the IdP starts an SSO session and generates an encrypted access token, which the application uses to confirm the user&#8217;s identity.</span></p><p><span style="font-weight: 400;">Once the SSO session is active, the user can access other trusted applications without needing to log in again. When a second application requires authentication, it communicates with the IdP, which verifies the user&#8217;s active session and issues another access token, granting seamless access without re-entering credentials.</span></p><p><span style="font-weight: 400;">Modern IAM solutions facilitate SSO implementation across various applications, often using open standards like OAuth 2.0 and OpenID Connect (OIDC). These standards enable authentication not only for internal applications but also for those relying on external identity providers. Additionally, many SSO systems support social login, allowing users to authenticate with their existing credentials from platforms such as Google, Facebook, or Twitter, further simplifying access across different services.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-5109a8f elementor-widget elementor-widget-heading" data-id="5109a8f" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Types of SSO
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-8c2be01 elementor-widget elementor-widget-text-editor" data-id="8c2be01" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">When implementing and managing Single Sign-On (SSO), it&#8217;s crucial to understand the various protocols and standards that enable its functionality. Among the most widely used are </span><b>Security Assertion Markup Language (SAML)</b><span style="font-weight: 400;"> and </span><b>OpenID Connect (OIDC)</b><span style="font-weight: 400;">. Keycloak supports these two protocols, making them the main point of our discussion. However, it&#8217;s worth noting that other protocols, such as Kerberos, also play a role in certain SSO scenarios.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-1110979 elementor-widget elementor-widget-heading" data-id="1110979" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h4 class="elementor-heading-title elementor-size-default">Security Access Markup Language (SAML)
</h4>		</div>
				</div>
				<div class="elementor-element elementor-element-033ee93 elementor-widget elementor-widget-text-editor" data-id="033ee93" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">SAML is an XML-based standard designed to encode and exchange identity information between applications. It has become a cornerstone for SSO, enabling web applications to validate authentication requests securely. SAML 2.0, the most widely adopted version, is specifically optimized for browser environments, allowing user information to be securely passed through web browsers. It is basically more verbose and less efficient in terms of data processing compared to modern standards. That is why SAML is best suited for legacy and enterprise web applications, especially those within organizations.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-df47e79 elementor-widget elementor-widget-heading" data-id="df47e79" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h4 class="elementor-heading-title elementor-size-default">OpenID Connect (OIDC)
</h4>		</div>
				</div>
				<div class="elementor-element elementor-element-43f4373 elementor-widget elementor-widget-text-editor" data-id="43f4373" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">OIDC is an extension of OAuth 2.0, which adds information about users and enables SSO. It uses JSON and RESTful APIs for data exchange, making it lightweight, fast and easy to integrate, especially for mobile and cloud-native environments. It is particularly useful for scenarios involving social login (e.g., Google, Facebook) and external APIs in general. That would be the best choice in scenarios where applications require flexible, scalable authentication with token-based security.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-dbb4648 elementor-widget elementor-widget-heading" data-id="dbb4648" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Multiple benefits of SSO
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-0582d73 elementor-widget elementor-widget-text-editor" data-id="0582d73" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">The key benefits of single sign-on are:</span></p><ul><li><span style="font-weight: 400;">         SSO helps reduce the need of remembering multiple usernames and password consolidating authentication into a single set of credentials.</span></li><li><span style="font-weight: 400;">         By minimizing the number of password resets and login issues, it reduces the need for IT support, resulting in cost savings.</span></li><li><span style="font-weight: 400;">         It eliminates interruptions caused by multiple logins or password management, allowing users to quickly access the resources they need and remain focused on their tasks. It makes the login process faster and enables one-click logout across multiple applications.</span></li><li><span style="font-weight: 400;">         With all user data in one centralized location, administrators can easily manage and adjust user access permissions across the network, ensuring better control.</span></li><li><span style="font-weight: 400;">         By consolidating login data, SSO reduces the risks associated with poor password management. Admins can disable accounts more easily when necessary, improving overall security.</span></li></ul><p><span style="font-weight: 400;">In general, SSO improves user experience, boosts productivity, strengthens security, and simplifies administrative tasks by centralizing authentication and making access management easier to do.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-759f1f5 elementor-widget elementor-widget-text-editor" data-id="759f1f5" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><b>Potential drawbacks</b></p><ul><li><span style="font-weight: 400;">         </span><b>Single Point of Failure (SPOF)</b></li></ul><p><span style="font-weight: 400;">If the SSO provider experiences downtime or is compromised, users may lose access to multiple applications simultaneously.</span></p><ul><li><span style="font-weight: 400;">         </span><b>Implementation might be complex</b></li></ul><p><span style="font-weight: 400;">Setting up and maintaining an SSO system can be technically challenging, especially in environments with diverse applications and protocols. Not all applications may support SSO out of the box, requiring custom integrations.</span></p><ul><li><span style="font-weight: 400;">         </span><b>Scalability concerns</b></li></ul><p><span style="font-weight: 400;">In high-traffic environments, the SSO system must handle significant loads, which may require additional resources and careful planning for further integrations.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-e1a3472 elementor-widget elementor-widget-heading" data-id="e1a3472" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">SSO with Keycloak and Spring
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-d4bf9a8 elementor-widget elementor-widget-text-editor" data-id="d4bf9a8" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Now we will cover how to set up a simple SSO mechanism using Spring Security, keycloak-angular library and Keycloak as an identity provider. Using Keycloak here is driven by several factors. It uses the well-established OpenID Connect standard, ensuring broad compatibility. It also stands out for its large number of ready-made examples for integrating both front-end and back-end applications. It also offers significant flexibility through Java-based extensions, allowing for easy customization.</span></p><p><span style="font-weight: 400;">To run SSO demo we can go through preparing the authorization server, resource server and two different client applications. When a user attempts to access a resource from one of the client applications, he should be redirected to the authorization server for claiming a token. Keycloak will manage the login process and once the user is logged into the first client app, if he accesses the second client app through the same browser, he won’t need to log in again, as the SSO session remains active. This time we’ll use an OIDC client that supports OAuth2 and Authorization Code Flow to handle the authentication process between the endpoints.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-f0eb4d8 elementor-widget elementor-widget-image" data-id="f0eb4d8" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="6505" data-permalink="https://inero-software.com/hands-on-keycloak-sso-from-setup-to-integration/keyclock7/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/12/KEYCLOCK7.png" data-orig-size="1920,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="KEYCLOCK7" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/12/KEYCLOCK7-300x169.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/12/KEYCLOCK7-1030x579.png" tabindex="0" role="button" width="1030" height="579" src="https://inero-software.com/wp-content/uploads/2024/12/KEYCLOCK7-1030x579.png" class="attachment-large size-large wp-image-6505" alt="" srcset="https://inero-software.com/wp-content/uploads/2024/12/KEYCLOCK7-1030x579.png 1030w, https://inero-software.com/wp-content/uploads/2024/12/KEYCLOCK7-300x169.png 300w, https://inero-software.com/wp-content/uploads/2024/12/KEYCLOCK7-768x432.png 768w, https://inero-software.com/wp-content/uploads/2024/12/KEYCLOCK7-1536x864.png 1536w, https://inero-software.com/wp-content/uploads/2024/12/KEYCLOCK7-533x300.png 533w, https://inero-software.com/wp-content/uploads/2024/12/KEYCLOCK7.png 1920w" sizes="(max-width: 1030px) 100vw, 1030px" data-attachment-id="6505" data-permalink="https://inero-software.com/hands-on-keycloak-sso-from-setup-to-integration/keyclock7/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/12/KEYCLOCK7.png" data-orig-size="1920,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="KEYCLOCK7" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/12/KEYCLOCK7-300x169.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/12/KEYCLOCK7-1030x579.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-a03fa44 elementor-widget elementor-widget-heading" data-id="a03fa44" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Authorization server
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-46bf13a elementor-widget elementor-widget-text-editor" data-id="46bf13a" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">For Identity Provider / Authorization server purposes we can use the docker image that contains the latest release of Keycloak. By deploying KC through a docker-compose file, we can quickly set up and configure the environment (also database) without the overhead of manual installation. This simple docker-compose setup would define two services for Keycloak and a PostgreSQL database.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-b80ac6b elementor-widget elementor-widget-text-editor" data-id="b80ac6b" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">x-keycloak: &amp;keycloak</span></p><p><span style="font-weight: 400;">  build: keycloak</span></p><p><span style="font-weight: 400;">  ports:</span></p><p><span style="font-weight: 400;">&#8211; &#8220;8080:8080&#8221;</span></p><p><span style="font-weight: 400;">  depends_on:</span></p><p><span style="font-weight: 400;">&#8211; db-postgres-keycloak</span></p><p><span style="font-weight: 400;"> </span></p><p><span style="font-weight: 400;">x-common-variables: &amp;common-variables</span></p><p><span style="font-weight: 400;">  KC_BOOTSTRAP_ADMIN_USERNAME: admin</span></p><p><span style="font-weight: 400;">  KC_BOOTSTRAP_ADMIN_PASSWORD: admin</span></p><p><span style="font-weight: 400;">  KC_HOSTNAME_STRICT: &#8220;false&#8221;</span></p><p><span style="font-weight: 400;">  KC_HTTP_RELATIVE_PATH: /auth</span></p><p><span style="font-weight: 400;">  KC_HTTP_ENABLED: &#8216;true&#8217;</span></p><p><span style="font-weight: 400;">  KC_LOG_LEVEL: &#8220;INFO,io.quarkus.http.access-log:DEBUG&#8221;</span></p><p><span style="font-weight: 400;">  KC_DB: postgres</span></p><p><span style="font-weight: 400;">  KC_DB_URL_HOST: db-postgres-keycloak</span></p><p><span style="font-weight: 400;">  KC_DB_USERNAME: keycloak</span></p><p><span style="font-weight: 400;">  KC_DB_PASSWORD: password</span></p><p><span style="font-weight: 400;">  KC_DB_SCHEMA: public</span></p><p><span style="font-weight: 400;">  QUARKUS_HTTP_ACCESS_LOG_ENABLED: &#8216;true&#8217;</span></p><p><span style="font-weight: 400;">services:</span><span style="font-weight: 400;"><br /></span><span style="font-weight: 400;">   keycloak:</span><span style="font-weight: 400;"><br /></span><span style="font-weight: 400;">          &lt;&lt;: *keycloak</span><span style="font-weight: 400;"><br /></span><span style="font-weight: 400;">         environment:</span><span style="font-weight: 400;"><br /></span><span style="font-weight: 400;">        </span> <span style="font-weight: 400;">&lt;&lt;: *common-variables</span><span style="font-weight: 400;"><br /></span><span style="font-weight: 400;">       profiles: [&#8220;example&#8221;]</span><span style="font-weight: 400;"><br /></span><span style="font-weight: 400;">      command: start &#8211;optimized</span></p><p><span style="font-weight: 400;">db-postgres-keycloak:</span><span style="font-weight: 400;"><br /></span><span style="font-weight: 400;">      profiles: [&#8220;example&#8221;]</span><span style="font-weight: 400;"><br /></span><span style="font-weight: 400;">      image: postgres:15</span><span style="font-weight: 400;"><br /></span><span style="font-weight: 400;">      environment:</span><span style="font-weight: 400;"><br /></span><span style="font-weight: 400;">     </span> <span style="font-weight: 400;">POSTGRES_USER: keycloak</span><span style="font-weight: 400;"><br /></span><span style="font-weight: 400;">      </span><span style="font-weight: 400;">POSTGRES_PASSWORD: password</span><span style="font-weight: 400;"><br /></span><span style="font-weight: 400;">     </span> <span style="font-weight: 400;">POSTGRES_DB: keycloak</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-2db7c3a elementor-widget elementor-widget-text-editor" data-id="2db7c3a" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">After starting the containers, we can log in to the admin console (here on</span><a href="http://localhost:8080"> <span style="font-weight: 400;">http://localhost:8080</span></a><span style="font-weight: 400;">). But before we proceed with realm clients configurations, let’s take a moment to explore the </span><b>Realm settings</b><span style="font-weight: 400;"> -&gt; </span><b>Sessions</b><span style="font-weight: 400;"> tab.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-76e1efc elementor-widget elementor-widget-heading" data-id="76e1efc" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h4 class="elementor-heading-title elementor-size-default">SSO session configuration</h4>		</div>
				</div>
				<div class="elementor-element elementor-element-143c327 elementor-widget elementor-widget-image" data-id="143c327" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="6507" data-permalink="https://inero-software.com/hands-on-keycloak-sso-from-setup-to-integration/obraz1-3/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz1.png" data-orig-size="605,351" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Obraz1" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz1-300x174.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz1.png" tabindex="0" role="button" width="605" height="351" src="https://inero-software.com/wp-content/uploads/2024/12/Obraz1.png" class="attachment-large size-large wp-image-6507" alt="" srcset="https://inero-software.com/wp-content/uploads/2024/12/Obraz1.png 605w, https://inero-software.com/wp-content/uploads/2024/12/Obraz1-300x174.png 300w, https://inero-software.com/wp-content/uploads/2024/12/Obraz1-517x300.png 517w" sizes="(max-width: 605px) 100vw, 605px" data-attachment-id="6507" data-permalink="https://inero-software.com/hands-on-keycloak-sso-from-setup-to-integration/obraz1-3/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz1.png" data-orig-size="605,351" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Obraz1" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz1-300x174.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz1.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-21c6e4e elementor-widget elementor-widget-text-editor" data-id="21c6e4e" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">When configuring a new realm, we can also adjust session management settings to balance security and user experience. These settings determine how long users remain authenticated and the conditions under which they must re-authenticate. Below we are describing the most important ones:</span></p><p><b>SSO Session Idle</b><span style="font-weight: 400;"> &#8211; this setting controls how long a user can remain idle before their session is considered expired. If a user is inactive for the specified time, they will need to re-authenticate the next time he interact with the application. It resets when clients send refresh token requests.</span></p><p><b>SSO Session Max</b><span style="font-weight: 400;"> &#8211; this defines the maximum duration for which a session remains valid, regardless of user activity. Once the session exceeds this lifetime, the user will be logged out and prompted to log in again.</span></p><p><b>SSO Session Idle Remember Me </b><span style="font-weight: 400;">and</span><b> SSO Session Max Remember Me</b><span style="font-weight: 400;">  – similar to SSO Session parameters but specific to situations when the user has the Remember Me option enabled.</span></p><p><b>Client Session Idle </b><span style="font-weight: 400;">and</span><b> Client Session Max</b><span style="font-weight: 400;"> – these parameters should specify a shorter timeout than general SSO settings. They describe the maximum validity period for a refresh token and can be overridden for individual clients in client settings.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-67f3943 elementor-widget elementor-widget-heading" data-id="67f3943" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Resource server
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-1ecb54b elementor-widget elementor-widget-text-editor" data-id="1ecb54b" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">One of the realm clients will represent our resource server, which serves a dual role as both a client of Keycloak and the backend for two different applications participating in the described flow. The process of integrating a Spring Boot application with Keycloak is pretty similar to what we described in one of the previous posts. (</span><a href="https://inero-software.com/securing-java-spring-endpoints-with-keycloak/"><span style="font-weight: 400;">https://inero-software.com/securing-java-spring-endpoints-with-keycloak/</span></a><span style="font-weight: 400;">). </span></p><p><span style="font-weight: 400;">Therefore, we won’t focus on the Java application itself here. Resource server configured this way will expose a sample endpoint accessible only to users authenticated within the realm.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-0d382ce elementor-widget elementor-widget-image" data-id="0d382ce" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="6508" data-permalink="https://inero-software.com/hands-on-keycloak-sso-from-setup-to-integration/obraz2-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz2.png" data-orig-size="605,363" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Obraz2" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz2-300x180.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz2.png" tabindex="0" role="button" width="605" height="363" src="https://inero-software.com/wp-content/uploads/2024/12/Obraz2.png" class="attachment-large size-large wp-image-6508" alt="" srcset="https://inero-software.com/wp-content/uploads/2024/12/Obraz2.png 605w, https://inero-software.com/wp-content/uploads/2024/12/Obraz2-300x180.png 300w, https://inero-software.com/wp-content/uploads/2024/12/Obraz2-500x300.png 500w" sizes="(max-width: 605px) 100vw, 605px" data-attachment-id="6508" data-permalink="https://inero-software.com/hands-on-keycloak-sso-from-setup-to-integration/obraz2-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz2.png" data-orig-size="605,363" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Obraz2" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz2-300x180.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz2.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-52acd2b elementor-widget elementor-widget-text-editor" data-id="52acd2b" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">The resource server needs to manage resources within the realm, which is why we enable the Authorization checkbox in Keycloak. Basically, this setting is intended for resource servers that require access to various endpoints such as the Token Endpoint.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-addf1cd elementor-widget elementor-widget-image" data-id="addf1cd" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="6509" data-permalink="https://inero-software.com/hands-on-keycloak-sso-from-setup-to-integration/obraz3/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz3.png" data-orig-size="605,344" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Obraz3" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz3-300x171.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz3.png" tabindex="0" role="button" width="605" height="344" src="https://inero-software.com/wp-content/uploads/2024/12/Obraz3.png" class="attachment-large size-large wp-image-6509" alt="" srcset="https://inero-software.com/wp-content/uploads/2024/12/Obraz3.png 605w, https://inero-software.com/wp-content/uploads/2024/12/Obraz3-300x171.png 300w, https://inero-software.com/wp-content/uploads/2024/12/Obraz3-528x300.png 528w" sizes="(max-width: 605px) 100vw, 605px" data-attachment-id="6509" data-permalink="https://inero-software.com/hands-on-keycloak-sso-from-setup-to-integration/obraz3/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz3.png" data-orig-size="605,344" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Obraz3" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz3-300x171.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz3.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-fe85f67 elementor-widget elementor-widget-text-editor" data-id="fe85f67" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">For this setup, the client is configured as confidential, with a secret, which must be shared between both the Keycloak server and the application itself. You can generate it within the Admin Console, and then include it in the application.properties file of the Spring application for secure communication.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-b86fa97 elementor-widget elementor-widget-image" data-id="b86fa97" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="6510" data-permalink="https://inero-software.com/hands-on-keycloak-sso-from-setup-to-integration/obraz4/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz4.png" data-orig-size="605,367" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Obraz4" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz4-300x182.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz4.png" tabindex="0" role="button" width="605" height="367" src="https://inero-software.com/wp-content/uploads/2024/12/Obraz4.png" class="attachment-large size-large wp-image-6510" alt="" srcset="https://inero-software.com/wp-content/uploads/2024/12/Obraz4.png 605w, https://inero-software.com/wp-content/uploads/2024/12/Obraz4-300x182.png 300w, https://inero-software.com/wp-content/uploads/2024/12/Obraz4-495x300.png 495w" sizes="(max-width: 605px) 100vw, 605px" data-attachment-id="6510" data-permalink="https://inero-software.com/hands-on-keycloak-sso-from-setup-to-integration/obraz4/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz4.png" data-orig-size="605,367" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Obraz4" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz4-300x182.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz4.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-6074115 elementor-widget elementor-widget-text-editor" data-id="6074115" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">You can leave the remaining form fields as default.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-faa8b15 elementor-widget elementor-widget-heading" data-id="faa8b15" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Frontend clients
</h3>		</div>
				</div>
				<div class="elementor-element elementor-element-78fd29c elementor-widget elementor-widget-text-editor" data-id="78fd29c" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">The configuration for frontend clients is pretty similar to the previous one. However, there are some differences to note. For browser based clients, we do not want to set them as confidential. &#8220;Authorization&#8221; option is also not necessary here. A key point to focus on is the proper configuration of redirect URIs and Web Origins. They can typically be the same. This ensures that Keycloak correctly recognizes the allowed origins from which the frontend application can make requests.</span></p><p><span style="font-weight: 400;">However, it is advisable not to get used to relying on wildcards (*) in redirect URIs. The most recent OAuth 2.1 specification requires that URIs must be compared using exact string matching.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-c99d969 elementor-widget elementor-widget-image" data-id="c99d969" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="6511" data-permalink="https://inero-software.com/hands-on-keycloak-sso-from-setup-to-integration/obraz5/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz5.png" data-orig-size="605,292" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Obraz5" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz5-300x145.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz5.png" tabindex="0" role="button" width="605" height="292" src="https://inero-software.com/wp-content/uploads/2024/12/Obraz5.png" class="attachment-large size-large wp-image-6511" alt="" srcset="https://inero-software.com/wp-content/uploads/2024/12/Obraz5.png 605w, https://inero-software.com/wp-content/uploads/2024/12/Obraz5-300x145.png 300w" sizes="(max-width: 605px) 100vw, 605px" data-attachment-id="6511" data-permalink="https://inero-software.com/hands-on-keycloak-sso-from-setup-to-integration/obraz5/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz5.png" data-orig-size="605,292" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Obraz5" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz5-300x145.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz5.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-16b0b05 elementor-widget elementor-widget-image" data-id="16b0b05" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="6512" data-permalink="https://inero-software.com/hands-on-keycloak-sso-from-setup-to-integration/obraz6/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz6.png" data-orig-size="594,311" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Obraz6" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz6-300x157.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz6.png" tabindex="0" role="button" width="594" height="311" src="https://inero-software.com/wp-content/uploads/2024/12/Obraz6.png" class="attachment-large size-large wp-image-6512" alt="" srcset="https://inero-software.com/wp-content/uploads/2024/12/Obraz6.png 594w, https://inero-software.com/wp-content/uploads/2024/12/Obraz6-300x157.png 300w, https://inero-software.com/wp-content/uploads/2024/12/Obraz6-573x300.png 573w" sizes="(max-width: 594px) 100vw, 594px" data-attachment-id="6512" data-permalink="https://inero-software.com/hands-on-keycloak-sso-from-setup-to-integration/obraz6/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz6.png" data-orig-size="594,311" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Obraz6" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz6-300x157.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/12/Obraz6.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-74de000 elementor-widget elementor-widget-text-editor" data-id="74de000" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">To authenticate a user and show Keycloak&#8217;s login page within our Angular project, we will utilize an Injection Token.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-ca70eb2 elementor-widget elementor-widget-text-editor" data-id="ca70eb2" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<pre><span style="font-weight: 400;">function initializeKeycloak(keycloak: KeycloakService) {</span><br /><span style="font-weight: 400;">return () =&gt;</span><br /><span style="font-weight: 400;">    </span> <span style="font-weight: 400;">keycloak.init({</span><br /><span style="font-weight: 400;">        </span> <span style="font-weight: 400;">config: {</span><br /><span style="font-weight: 400;">            </span> <span style="font-weight: 400;">url: </span><i><span style="font-weight: 400;">environment</span></i><span style="font-weight: 400;">.keycloakUrl,</span><br /><span style="font-weight: 400;">          </span> <span style="font-weight: 400;">  realm: 'sso-realm',</span><br /><span style="font-weight: 400;">            </span> <span style="font-weight: 400;">clientId: 'sso-app-1',</span><br /><span style="font-weight: 400;">        </span> <span style="font-weight: 400;">},</span><br /><span style="font-weight: 400;">        </span> <span style="font-weight: 400;">initOptions: {</span><br /><span style="font-weight: 400;">            </span> <span style="font-weight: 400;">checkLoginIframe: false,</span><br /><span style="font-weight: 400;">            </span> <span style="font-weight: 400;">scope: 'sso-resource-server'</span><br /><span style="font-weight: 400;">        </span> <span style="font-weight: 400;">}</span><br /><span style="font-weight: 400;">    </span> <span style="font-weight: 400;">});</span><br /><span style="font-weight: 400;">}</span></pre>						</div>
				</div>
				<div class="elementor-element elementor-element-c885d0e elementor-widget elementor-widget-text-editor" data-id="c885d0e" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Above function takes as an argument a KeycloakService which is an object from keycloak-angular library so that we can use it in the body of a function to configure it by providing URL to the server, realm name and application&#8217;s client id which was created a step before. Next we need to register this function in the app.module.ts file, as a provider:</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-dda523b elementor-widget elementor-widget-text-editor" data-id="dda523b" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<pre><span style="font-weight: 400;">providers: [</span><br /><span style="font-weight: 400;">     {</span><br /><span style="font-weight: 400;">    </span> <span style="font-weight: 400;">provide: </span><i><span style="font-weight: 400;">APP_INITIALIZER</span></i><span style="font-weight: 400;">,</span><br /><span style="font-weight: 400;">    </span> <span style="font-weight: 400;">useFactory: initializeKeycloak,</span><br /><span style="font-weight: 400;">    </span> <span style="font-weight: 400;">multi: true,</span><br /><span style="font-weight: 400;">    </span> <span style="font-weight: 400;">deps: [KeycloakService],</span><br /><span style="font-weight: 400;">     },</span><br /><span style="font-weight: 400;">],</span></pre>						</div>
				</div>
				<div class="elementor-element elementor-element-c73de49 elementor-widget elementor-widget-text-editor" data-id="c73de49" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Next step would be to create a Guard that will protect routes in an application. The library that we’re using is already providing a preconfigured, abstract KeycloakAuthGuard class from which we will extend ours. Then we need to override the isAccessAllowed method.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-79eb23e elementor-widget elementor-widget-text-editor" data-id="79eb23e" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<pre><span style="font-weight: 400;">public async isAccessAllowed(</span><br /><span style="font-weight: 400;">      route: ActivatedRouteSnapshot,</span><br /><span style="font-weight: 400;">      state: RouterStateSnapshot</span><br /><br /><span style="font-weight: 400;">) {</span><br /><br /><span style="font-weight: 400;">     // Force the user to log in if currently unauthenticated.</span><br /><span style="font-weight: 400;">    if (!this.authenticated) {</span><br /><span style="font-weight: 400;">    </span><span style="font-weight: 400;">await this.keycloak.login({</span><br /><span style="font-weight: 400;">   </span> <span style="font-weight: 400;">redirectUri: </span><i><span style="font-weight: 400;">window</span></i><span style="font-weight: 400;">.location.origin + '/#/' + state.url</span><br /><span style="font-weight: 400;">    </span> <span style="font-weight: 400;">});<br /></span><br /><span style="font-weight: 400;">     }</span><br /><span style="font-weight: 400;">    // Get the roles required from the route.</span><br /><span style="font-weight: 400;">    const requiredRoles = route.data['roles'];<br /></span><br /><span style="font-weight: 400;">   // Allow the user to proceed if no additional roles are required to access the route.</span><br /><span style="font-weight: 400;">   if (!(requiredRoles instanceof </span><i><span style="font-weight: 400;">Array</span></i><span style="font-weight: 400;">) || requiredRoles.length === 0) {</span><br /><span style="font-weight: 400;">   </span><span style="font-weight: 400;">return true;<br /></span><span style="font-weight: 400;">   }</span><br /><br /><span style="font-weight: 400;">   // Allow the user to proceed if all the required roles are present.</span><br /><span style="font-weight: 400;">  return requiredRoles.every((role) =&gt; this.roles.includes(role));</span><br /><span style="font-weight: 400;">}</span></pre>						</div>
				</div>
				<div class="elementor-element elementor-element-cd7644e elementor-widget elementor-widget-text-editor" data-id="cd7644e" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">Next, we have to assign the AuthGuard to the specified routes in the routing module. With all these keycloak-angular library components properly configured, we should be able to redirect the user to the Keycloak login page and after successful authentication, the user would be able to access the secured resources.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-b82d617 elementor-widget elementor-widget-heading" data-id="b82d617" data-element_type="widget" data-widget_type="heading.default">
				<div class="elementor-widget-container">
			<h3 class="elementor-heading-title elementor-size-default">Testing and summary
</h3>		</div>
				</div>
				</div>
		<div class="elementor-element elementor-element-bfd0f02 e-con-full e-flex e-con e-child" data-id="bfd0f02" data-element_type="container">
				</div>
					</div>
				</div>
		<div class="elementor-element elementor-element-31ecbdd e-flex e-con-boxed e-con e-parent" data-id="31ecbdd" data-element_type="container">
					<div class="e-con-inner">
				<div class="elementor-element elementor-element-f2e9274 elementor-widget elementor-widget-text-editor" data-id="f2e9274" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span style="font-weight: 400;">To test the SSO functionality, you can run the resource server (Spring application) and both browser-based clients. Once everything is up and running, open a browser and log in to one of the frontend clients. Then, open a new tab or window and navigate to the second Angular application. After clicking the login button, you should be redirected to the app directly and have access to the secured endpoint.</span></p><p><span style="font-weight: 400;">Now you can see how using Keycloak’s built-in features simplified managing access permissions. By leveraging it as an Identity Provider, we can set up a system where users only need to log in once to access various connected applications. By centralizing user credentials we can also enhance both security and user experience, and for example, reduce the risk of password-related vulnerabilities.</span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-3a7057f elementor-cta--skin-classic elementor-animated-content elementor-bg-transform elementor-bg-transform-zoom-in elementor-widget elementor-widget-call-to-action" data-id="3a7057f" data-element_type="widget" data-widget_type="call-to-action.default">
				<div class="elementor-widget-container">
					<div class="elementor-cta">
					<div class="elementor-cta__bg-wrapper">
				<div class="elementor-cta__bg elementor-bg" style="background-image: url(https://inero-software.com/wp-content/uploads/2024/12/tlo-popup-keycloak-2-1030x731.png);" role="img" aria-label="tło popup keycloak (2)"></div>
				<div class="elementor-cta__bg-overlay"></div>
			</div>
							<div class="elementor-cta__content">
				
									<h2 class="elementor-cta__title elementor-cta__content-item elementor-content-item">
						Does your company need help with Keycloak maintenance?					</h2>
				
									<div class="elementor-cta__description elementor-cta__content-item elementor-content-item">
						We’re happy to help! 					</div>
				
									<div class="elementor-cta__button-wrapper elementor-cta__content-item elementor-content-item ">
					<a class="elementor-cta__button elementor-button elementor-size-" href="https://inero-software.com/contact-us/">
						 Contact us					</a>
					</div>
							</div>
						</div>
				</div>
				</div>
					</div>
				</div>
				</div>
		<p>Artykuł <a href="https://inero-software.com/hands-on-keycloak-sso-from-setup-to-integration/">Hands-On Keycloak SSO: From Setup to Integration</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6504</post-id>	</item>
		<item>
		<title>Keycloak: Smart Tips for Monitoring and Protection with Built-in Configuration Tools</title>
		<link>https://inero-software.com/monitoring-and-securing-keycloak-performance-and-phishing-attack-protection/</link>
		
		<dc:creator><![CDATA[Marceli Formela]]></dc:creator>
		<pubDate>Thu, 26 Sep 2024 09:51:23 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Company]]></category>
		<category><![CDATA[Keycloak]]></category>
		<category><![CDATA[Technology]]></category>
		<guid isPermaLink="false">https://inero-software.com/?p=6146</guid>

					<description><![CDATA[<p>Keycloak is not just a powerful identity and access management tool; it&#8217;s also essential for monitoring performance and enhancing security, particularly when defending against phishing attacks. With its built-in monitoring and alerting mechanisms, administrators can detect suspicious user activities and maintain optimal system performance. Andrzej Chybicki CEO Inero Software Keycloak&#8230;</p>
<p>Artykuł <a href="https://inero-software.com/monitoring-and-securing-keycloak-performance-and-phishing-attack-protection/">Keycloak: Smart Tips for Monitoring and Protection with Built-in Configuration Tools</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></description>
										<content:encoded><![CDATA[		<div data-elementor-type="wp-post" data-elementor-id="6146" class="elementor elementor-6146" data-elementor-post-type="post">
				<div class="elementor-element elementor-element-f4346b3 e-flex e-con-boxed e-con e-parent" data-id="f4346b3" data-element_type="container">
					<div class="e-con-inner">
				<div class="elementor-element elementor-element-e560d78 elementor-widget elementor-widget-html" data-id="e560d78" data-element_type="widget" data-widget_type="html.default">
				<div class="elementor-widget-container">
					</div>
				</div>
					</div>
				</div>
		<div class="elementor-element elementor-element-9788065 e-flex e-con-boxed e-con e-parent" data-id="9788065" data-element_type="container">
					<div class="e-con-inner">
		<div class="elementor-element elementor-element-6852513 e-con-full e-flex e-con e-child" data-id="6852513" data-element_type="container">
				</div>
		<div class="elementor-element elementor-element-1457fdd e-con-full e-flex e-con e-child" data-id="1457fdd" data-element_type="container">
				<div class="elementor-element elementor-element-e1ddbe6 elementor-widget elementor-widget-text-editor" data-id="e1ddbe6" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<h4><span class="TextRun SCXW108935395 BCX0" lang="EN-US" xml:lang="EN-US" data-contrast="auto"><span class="NormalTextRun SpellingErrorV2Themed SCXW108935395 BCX0">Keycloak</span><span class="NormalTextRun SCXW108935395 BCX0"> is not just a powerful identity and access management tool; </span><span class="NormalTextRun SCXW108935395 BCX0">it&#8217;s</span><span class="NormalTextRun SCXW108935395 BCX0"> also essential for </span><span class="NormalTextRun SCXW108935395 BCX0">monitoring</span><span class="NormalTextRun SCXW108935395 BCX0"> performance and enhancing security, particularly when defending against phishing attacks. With its built-in monitoring and alerting mechanisms, administrators can detect suspicious user activities and </span><span class="NormalTextRun SCXW108935395 BCX0">maintain</span> <span class="NormalTextRun SCXW108935395 BCX0">optimal</span><span class="NormalTextRun SCXW108935395 BCX0"> system performance.</span></span><span class="EOP SCXW108935395 BCX0" data-ccp-props="{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></h4>						</div>
				</div>
				</div>
					</div>
				</div>
		<div class="elementor-element elementor-element-0bdde1b e-flex e-con-boxed e-con e-parent" data-id="0bdde1b" data-element_type="container">
					<div class="e-con-inner">
		<div class="elementor-element elementor-element-0660a51 e-con-full e-flex e-con e-child" data-id="0660a51" data-element_type="container">
		<div class="elementor-element elementor-element-b9fde1c e-con-full e-flex e-con e-child" data-id="b9fde1c" data-element_type="container">
				</div>
				<div class="elementor-element elementor-element-932c0ac elementor-widget__width-initial elementor-widget elementor-widget-link-in-bio" data-id="932c0ac" data-element_type="widget" data-widget_type="link-in-bio.default">
				<div class="elementor-widget-container">
					<div class="e-link-in-bio e-link-in-bio">
			<div class="e-link-in-bio__content">

						<div class="e-link-in-bio__identity">
									<div class="e-link-in-bio__identity-image e-link-in-bio__identity-image-profile has-style-circle">
							<img loading="lazy" decoding="async" width="300" height="300" src="https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-300x300.png" class="e-link-in-bio__identity-image-element" alt="" srcset="https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-300x300.png 300w, https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-1030x1030.png 1030w, https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-80x80.png 80w, https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-768x768.png 768w, https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-75x75.png 75w, https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-50x50.png 50w, https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-512x512.png 512w, https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-1024x1024.png 1024w, https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1.png 1200w" sizes="(max-width: 300px) 100vw, 300px" data-attachment-id="5903" data-permalink="https://inero-software.com/?attachment_id=5903" data-orig-file="https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1.png" data-orig-size="1200,1200" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Andrzej Chybicki PhD Eng. (1)" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-300x300.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-1030x1030.png" tabindex="0" role="button" />													</div>
							</div>
					<div class="e-link-in-bio__bio">
								<h3 class="e-link-in-bio__title">Andrzej Chybicki </h3>								<p class="e-link-in-bio__description">CEO Inero Software      
</p>			</div>
					<div class="e-link-in-bio__icons has-size-small">
							<div class="e-link-in-bio__icon is-size-small">
					<a href="https://www.linkedin.com/in/andrzej-chybicki/" target="_blank" rel="noopener " aria-label="LinkedIn" class="e-link-in-bio__icon-link">
						<span class="e-link-in-bio__icon-svg">
							<svg aria-hidden="true" class="e-font-icon-svg e-fab-linkedin-in" viewBox="0 0 448 512" xmlns="http://www.w3.org/2000/svg"><path d="M100.28 448H7.4V148.9h92.88zM53.79 108.1C24.09 108.1 0 83.5 0 53.8a53.79 53.79 0 0 1 107.58 0c0 29.7-24.1 54.3-53.79 54.3zM447.9 448h-92.68V302.4c0-34.7-.7-79.2-48.29-79.2-48.29 0-55.69 37.7-55.69 76.7V448h-92.78V148.9h89.08v40.8h1.3c12.4-23.5 42.69-48.3 87.88-48.3 94 0 111.28 61.9 111.28 142.3V448z"></path></svg>						</span>
											</a>
				</div>
					</div>
		
		<div class="e-link-in-bio__ctas has-type-button">
							<a href="https://inero-software.com/keycloak-services/" target="_blank" rel="noopener " class="e-link-in-bio__cta is-type-button has-corners-rounded">
										<span class="e-link-in-bio__cta-text">
						Keycloak services.  Comprehensive implementation, maintenance, and training					</span>
				</a>
					</div>
		
			</div>
			<div class="e-link-in-bio__bg">
				<div class="e-link-in-bio__bg-overlay"></div>
			</div>
		</div>
				</div>
				</div>
				</div>
		<div class="elementor-element elementor-element-966c713 e-con-full e-flex e-con e-child" data-id="966c713" data-element_type="container">
				<div class="elementor-element elementor-element-369c446 elementor-widget elementor-widget-text-editor" data-id="369c446" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<h4><b><span data-contrast="auto">Keycloak Performance: Monitoring with Grafana</span></b><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></h4><p><span data-contrast="auto">Monitoring Keycloak’s performance is crucial, especially in large organizations where the system needs to handle thousands of users simultaneously. Interesting tools to use in this regard if for instance </span><b><span data-contrast="auto">aerogear</span></b><span data-contrast="auto"> (</span><a href="https://github.com/aerogear/keycloak-metrics-spi"><span data-contrast="none">https://github.com/aerogear/keycloak-metrics-spi</span></a><span data-contrast="auto">). Aeorgear allows for easy trackick of critical metrics in real-time, allowing for system optimization and scaling.</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p><p><span data-contrast="auto">Aerogear provides two key functions: </span><b><span data-contrast="auto">MetricsEventListener</span></b><span data-contrast="auto"> and </span><b><span data-contrast="auto">MetricsEndpoint</span></b><span data-contrast="auto">, which enable the forwarding of Keycloak events to Prometheus and integration with visualization tools like Grafana. This allows administrators to monitor important metrics, such as:</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-ffa0c9b elementor-widget elementor-widget-text-editor" data-id="ffa0c9b" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<ul><li style="list-style-type: none;"><ul><li data-leveltext="" data-font="Symbol" data-listid="1" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;multilevel&quot;}" aria-setsize="-1" data-aria-posinset="1" data-aria-level="1"><p><span style="color: #800080;">Memory usage, </span></p></li></ul></li></ul><ul><li style="list-style-type: none;"><ul><li data-leveltext="" data-font="Symbol" data-listid="1" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;multilevel&quot;}" aria-setsize="-1" data-aria-posinset="2" data-aria-level="1"><p><span style="color: #800080;">Number of logged-in users (by realm, client, globally, etc.), </span></p></li></ul></li></ul><ul><li style="list-style-type: none;"><ul><li data-leveltext="" data-font="Symbol" data-listid="1" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;multilevel&quot;}" aria-setsize="-1" data-aria-posinset="3" data-aria-level="1"><p><span style="color: #800080;">Login errors. </span></p></li></ul></li></ul>						</div>
				</div>
				<div class="elementor-element elementor-element-e5f2273 elementor-widget elementor-widget-text-editor" data-id="e5f2273" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<p><span class="TextRun SCXW231539065 BCX0" lang="EN-US" xml:lang="EN-US" data-contrast="auto"><span class="NormalTextRun SCXW231539065 BCX0">Grafana offers </span><span class="NormalTextRun SCXW231539065 BCX0">a high level</span><span class="NormalTextRun SCXW231539065 BCX0"> of customization, allowing the inclusion of custom parameters (e.g., from CSV files or databases) and setting up alerts. These alerts can be triggered by </span><span class="NormalTextRun SCXW231539065 BCX0">various factors</span><span class="NormalTextRun SCXW231539065 BCX0">, such as:</span></span><span class="EOP SCXW231539065 BCX0" data-ccp-props="{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-1e9ba12 elementor-widget elementor-widget-text-editor" data-id="1e9ba12" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<ul><li style="list-style-type: none;"><ul><li data-leveltext="" data-font="Symbol" data-listid="2" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;multilevel&quot;}" aria-setsize="-1" data-aria-posinset="1" data-aria-level="1"><span style="color: #800080;">Exceeding login time limits, </span></li></ul></li></ul><ul><li style="list-style-type: none;"><ul><li data-leveltext="" data-font="Symbol" data-listid="2" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;multilevel&quot;}" aria-setsize="-1" data-aria-posinset="2" data-aria-level="1"><span style="color: #800080;">Logging in from unauthorized locations, </span></li></ul></li></ul><ul><li style="list-style-type: none;"><ul><li data-leveltext="" data-font="Symbol" data-listid="2" data-list-defn-props="{&quot;335552541&quot;:1,&quot;335559685&quot;:720,&quot;335559991&quot;:360,&quot;469769226&quot;:&quot;Symbol&quot;,&quot;469769242&quot;:[8226],&quot;469777803&quot;:&quot;left&quot;,&quot;469777804&quot;:&quot;&quot;,&quot;469777815&quot;:&quot;multilevel&quot;}" aria-setsize="-1" data-aria-posinset="3" data-aria-level="1"><span style="color: #800080;">Unusual numbers of password reset requests. </span></li></ul></li></ul>						</div>
				</div>
				<div class="elementor-element elementor-element-5e9160a elementor-widget elementor-widget-image" data-id="5e9160a" data-element_type="widget" data-widget_type="image.default">
				<div class="elementor-widget-container">
													<img loading="lazy" decoding="async" data-attachment-id="6148" data-permalink="https://inero-software.com/monitoring-and-securing-keycloak-performance-and-phishing-attack-protection/grafana/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/09/grafana.png" data-orig-size="1263,1000" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="grafana" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/09/grafana-300x238.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/09/grafana-1030x816.png" tabindex="0" role="button" width="1030" height="816" src="https://inero-software.com/wp-content/uploads/2024/09/grafana-1030x816.png" class="attachment-large size-large wp-image-6148" alt="" srcset="https://inero-software.com/wp-content/uploads/2024/09/grafana-1030x816.png 1030w, https://inero-software.com/wp-content/uploads/2024/09/grafana-300x238.png 300w, https://inero-software.com/wp-content/uploads/2024/09/grafana-768x608.png 768w, https://inero-software.com/wp-content/uploads/2024/09/grafana-379x300.png 379w, https://inero-software.com/wp-content/uploads/2024/09/grafana-380x300.png 380w, https://inero-software.com/wp-content/uploads/2024/09/grafana.png 1263w" sizes="(max-width: 1030px) 100vw, 1030px" data-attachment-id="6148" data-permalink="https://inero-software.com/monitoring-and-securing-keycloak-performance-and-phishing-attack-protection/grafana/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/09/grafana.png" data-orig-size="1263,1000" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="grafana" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/09/grafana-300x238.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/09/grafana-1030x816.png" role="button" />													</div>
				</div>
				<div class="elementor-element elementor-element-7544641 elementor-widget elementor-widget-text-editor" data-id="7544641" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<h6><span class="TextRun SCXW154526738 BCX0" lang="EN-US" xml:lang="EN-US" data-contrast="auto"><span class="NormalTextRun SCXW154526738 BCX0">Figure 1. Source: grafana.com/</span><span class="NormalTextRun SpellingErrorV2Themed SCXW154526738 BCX0">grafana</span><span class="NormalTextRun SCXW154526738 BCX0">/dashboards/10441-keycloak-metrics-dashboard</span></span><span class="EOP SCXW154526738 BCX0" data-ccp-props="{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></h6>						</div>
				</div>
				<div class="elementor-element elementor-element-8670612 elementor-widget elementor-widget-text-editor" data-id="8670612" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<h4><b><span data-contrast="auto">Phishing Attack Protection: Adaptive Authentication Mechanisms</span></b><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></h4><p><span data-contrast="auto">In addition to performance monitoring, Keycloak’s advanced built-in security features help protect against phishing attacks by analyzing event patterns. Keycloak events allow administrators to define custom responses to specific user actions, such as password resets following failed login attempts—often an indicator of phishing activity.</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p><p><span data-contrast="auto">An example of a security feature is </span><b><span data-contrast="auto">adaptive authentication</span></b><span data-contrast="auto">, which modifies the user login flow based on previous behavior. For instance, if a user requests a password reset without recent failed login attempts, the system could trigger an additional authentication step, like two-factor authentication (2FA).</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>						</div>
				</div>
				<div class="elementor-element elementor-element-72d0a10 elementor-widget elementor-widget-text-editor" data-id="72d0a10" data-element_type="widget" data-widget_type="text-editor.default">
				<div class="elementor-widget-container">
							<h4><b><span data-contrast="auto">Creating and adapting Security Policy</span></b><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></h4><p><span data-contrast="auto">When implementing these features, it’s essential to determine when user actions should raise suspicion. For example, a password reset without failed login attempts might signal phishing, while a reset after multiple failed logins is more routine. A custom security policy could be defined to say: </span><i><span data-contrast="auto">“If a user requests a password reset without failed logins in the last 3 minutes, require 2FA.”</span></i><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p><p><span data-contrast="auto">These adaptive authentication mechanisms reduce the burden of MFA (multi-factor authentication) while maintaining high security levels. By configuring Keycloak’s event and alert system, organizations can more effectively detect unusual behavior and respond to potential threats more swiftly.</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p><p><span data-contrast="auto">Keycloak is a versatile tool that supports both performance monitoring and enhanced security. Integration with tools like Grafana allows administrators to keep track of essential system parameters, while advanced event-based mechanisms and adaptive authentication enhance security by protecting against phishing and other threats. Proper configuration of these features can significantly boost security and improve incident response times.</span><span data-ccp-props="{&quot;201341983&quot;:0,&quot;335559739&quot;:160,&quot;335559740&quot;:259}"> </span></p>						</div>
				</div>
				</div>
					</div>
				</div>
				</div>
		<p>Artykuł <a href="https://inero-software.com/monitoring-and-securing-keycloak-performance-and-phishing-attack-protection/">Keycloak: Smart Tips for Monitoring and Protection with Built-in Configuration Tools</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6146</post-id>	</item>
		<item>
		<title>Keycloak Integration Guide: Enabling Social Login with Multiple Platforms like Google</title>
		<link>https://inero-software.com/keycloak-integration-guide-enabling-social-login-with-multiple-platforms-like-google/</link>
		
		<dc:creator><![CDATA[Marceli Formela]]></dc:creator>
		<pubDate>Wed, 11 Sep 2024 12:52:22 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Company]]></category>
		<category><![CDATA[Keycloak]]></category>
		<category><![CDATA[keycloak]]></category>
		<category><![CDATA[login]]></category>
		<category><![CDATA[social]]></category>
		<guid isPermaLink="false">https://inero-software.com/?p=6089</guid>

					<description><![CDATA[<p>&#160;</p>
<p>Artykuł <a href="https://inero-software.com/keycloak-integration-guide-enabling-social-login-with-multiple-platforms-like-google/">Keycloak Integration Guide: Enabling Social Login with Multiple Platforms like Google</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>&nbsp;</p>
<div class="row"><div class="col-sm-1"></div><div class="col-sm-10">
<h4><strong>Last time we saw how to implement custom Keycloak themes and i.e. how it helps to prevent phishing attacks. In this guide, we’ll focus on how to enable social login using Keycloak, with a step-by-step approach to integrating platforms such as Google. Whether you&#8217;re looking to simplify authentication or enhance security, this guide will walk you through the essential steps to configure and manage social login in your application.</strong></h4>
<p>&nbsp;</p>
<h3><b>How does it work</b></h3>
<p><span style="font-weight: 400;">The general idea of social login works is pretty straightforward as a concept: when users access our application, they can choose a social network provider, such as Google or Facebook, for authentication instead of manually defining login and passwords. Then the application sends a login request to the selected platform and once the social network confirms the user&#8217;s identity, the user is granted access to the application and is logged in immediately. </span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6097" data-permalink="https://inero-software.com/keycloak-integration-guide-enabling-social-login-with-multiple-platforms-like-google/8-3/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/09/8.png" data-orig-size="1920,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="8" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/09/8-300x169.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/09/8-1030x579.png" tabindex="0" role="button" class="aligncenter wp-image-6097 size-full" src="https://inero-software.com/wp-content/uploads/2024/09/8.png" alt="" width="1920" height="1080" srcset="https://inero-software.com/wp-content/uploads/2024/09/8.png 1920w, https://inero-software.com/wp-content/uploads/2024/09/8-300x169.png 300w, https://inero-software.com/wp-content/uploads/2024/09/8-1030x579.png 1030w, https://inero-software.com/wp-content/uploads/2024/09/8-768x432.png 768w, https://inero-software.com/wp-content/uploads/2024/09/8-1536x864.png 1536w, https://inero-software.com/wp-content/uploads/2024/09/8-533x300.png 533w" sizes="(max-width: 1920px) 100vw, 1920px" /></p>
<ol>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">The user, who is not yet authenticated, tries to access a protected resource in a client application. Application redirects the browser to Keycloak which acts as the Identity Broker. and then redirects again to one of the Identity Providers.</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">A login page is presented with a list of available identity providers (such as Google, Facebook, etc.) based on the realm’s configuration.</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">The user selects an identity provider and then is redirected to the login page of the selected one, where they can provide their credentials. The identity provider’s setup, including connection properties, has already been configured by the admin via the admin console.</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Upon successful authentication, the user is redirected back to Keycloak with an authentication response which eventually leads to retrieval of the access token.</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Keycloak verifies the identity and creates a new user or skips this step if the user already exists.</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Once Keycloak successfully authenticates the user, it issues its own token to allow access to the protected resource and redirects the user back to the client application.</span></li>
</ol>
<h3></h3>
<p>&nbsp;</p>
<h3><b>Key benefits</b></h3>
<p><img loading="lazy" decoding="async" data-attachment-id="6106" data-permalink="https://inero-software.com/keycloak-integration-guide-enabling-social-login-with-multiple-platforms-like-google/7a/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/09/7A.png" data-orig-size="637,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="7A" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/09/7A-177x300.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/09/7A-608x1030.png" tabindex="0" role="button" class=" wp-image-6106 alignleft" src="https://inero-software.com/wp-content/uploads/2024/09/7A-177x300.png" alt="" width="302" height="512" srcset="https://inero-software.com/wp-content/uploads/2024/09/7A-177x300.png 177w, https://inero-software.com/wp-content/uploads/2024/09/7A-608x1030.png 608w, https://inero-software.com/wp-content/uploads/2024/09/7A.png 637w" sizes="(max-width: 302px) 100vw, 302px" /></p>
<ul>
<li aria-level="1">Users can sign up and access your application in just a few clicks. Applications could use the profile data instead of having users manually enter this information into forms. This can potentially speed up and streamline the registration process.</li>
<li style="font-weight: 400;" aria-level="1">Social login reduces the risk of weak password and offers enhanced security features like multi-factor authentication (MFA).</li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">In many applications, users often don’t keep their profiles up-to-date. However, they typically ensure their information is current on their social network. So after implementing social login, we can assume that the user data we collected is reliable, as it pulls information directly from their frequently updated social profiles.</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Social network providers often offer additional user data, such as location, interests and other beyond just basic profile information. By using this we can deliver personalized content to users more effectively. This allows for more targeted interactions and content recommendations.</span></li>
<li><span style="font-weight: 400;">The social network provider is often responsible for verifying the user’s email address. If the provider shares this information, you receive a valid email address rather than potentially fake ones that users might use when registering on web applications. Furthermore, the provider also manages the password recovery process, reducing the need for your application to handle these aspects, which simplifies user management.</span></li>
</ul>
<p><span style="font-weight: 400;">The numbers generally show an improvement in conversion, and in some cases, very significant increases. I<a href="http://*https://auth0.com/blog/how-to-use-social-login-to-drive-your-apps-growth/">n an article prepared by the Auth0 marketing team, it is stated that social login can increase registration rates by up to 50%*</a>.</span></p>
<p><strong>Our experience with the development of <a href="https://inero-software.com/docsquality/">DocsQuality</a> allows us to believe in the validity of these assumptions. After implementing social media login, we observed a several-fold increase in the number of new users.</strong></p>
<p>&nbsp;</p>
<h3><b>Potential drawbacks</b></h3>
<p><span style="font-weight: 400;">When considering social login methods in Keycloak, it’s important to weigh their potential drawbacks, which have led to a noticeable decline in their use recently. Here are some key concerns:</span></p>
<ul>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;"> </span><span style="font-weight: 400;">Although relatively rare, there&#8217;s a risk that a social login could become a single point of failure. If a user&#8217;s social media credentials are compromised, it could potentially give hackers access to your platform and any associated accounts.</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Users often worry about how social media platforms handle their data. This concern can make them reluctant to grant additional apps access to their information, leading to decreased adoption of social login features.</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Social login protocols like OpenID Connect are open and interoperable but can be challenging to implement. Even experienced developers may find integrating these standards into their applications time-consuming and complex.</span><span style="font-weight: 400;">  </span></li>
</ul>
<p><span style="font-weight: 400;">To address security concerns, it’s important to promote good social media security practices among users. Encouraging strong, unique passwords and two-factor authentication for social media accounts can help mitigate these risks and enhance the security of social login methods. Fortunately, this last one is largely addressed by Keycloak, which simplifies the implementation of these protocols. Therefore, in our example, we&#8217;ll focus on utilizing Keycloak to streamline the social login process.</span></p>
<p>&nbsp;</p>
<h3><b>Adding social login</b></h3>
<p><span style="font-weight: 400;">For this example, we will use the application we prepared in the previous blog post where we customize the themes. The initial view looks like this:</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6094" data-permalink="https://inero-software.com/keycloak-integration-guide-enabling-social-login-with-multiple-platforms-like-google/5-5/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/09/5-1.png" data-orig-size="1479,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="5" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/09/5-1-300x219.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/09/5-1-1030x752.png" tabindex="0" role="button" class="wp-image-6094 aligncenter" src="https://inero-software.com/wp-content/uploads/2024/09/5-1-300x219.png" alt="" width="653" height="477" srcset="https://inero-software.com/wp-content/uploads/2024/09/5-1-300x219.png 300w, https://inero-software.com/wp-content/uploads/2024/09/5-1-1030x752.png 1030w, https://inero-software.com/wp-content/uploads/2024/09/5-1-768x561.png 768w, https://inero-software.com/wp-content/uploads/2024/09/5-1-411x300.png 411w, https://inero-software.com/wp-content/uploads/2024/09/5-1.png 1479w" sizes="(max-width: 653px) 100vw, 653px" /></p>
<p><span style="font-weight: 400;">Now you can log in to one of the identity provider consoles, like GitHub in this case. </span></p>
<p><span style="font-weight: 400;">Navigate to </span><b>Settings -&gt; Developer settings -&gt; OAuth Apps</b><span style="font-weight: 400;">. Click </span><b>New OAuth App</b><span style="font-weight: 400;"> and fill out the necessary information:</span></p>
<ul>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Application Name</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Homepage URL</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Authorization callback URL</span></li>
</ul>
<p><span style="font-weight: 400;">The last one should be in the format </span><b>&lt;your-keycloak-domain&gt;/auth/realms/&lt;your-realm&gt;/broker/github/endpoint</b><span style="font-weight: 400;">. For testing purposes, we will try to do just local setup using 4200 and 8080 ports. Once the form is completed, click </span><b>Register Application</b><span style="font-weight: 400;">. GitHub will generate a </span><b>Client ID</b><span style="font-weight: 400;"> and </span><b>Client Secret.</b></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6093" data-permalink="https://inero-software.com/keycloak-integration-guide-enabling-social-login-with-multiple-platforms-like-google/4-8/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/09/4.png" data-orig-size="1920,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="4" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/09/4-300x169.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/09/4-1030x579.png" tabindex="0" role="button" class=" wp-image-6093 aligncenter" src="https://inero-software.com/wp-content/uploads/2024/09/4-300x169.png" alt="" width="744" height="419" srcset="https://inero-software.com/wp-content/uploads/2024/09/4-300x169.png 300w, https://inero-software.com/wp-content/uploads/2024/09/4-1030x579.png 1030w, https://inero-software.com/wp-content/uploads/2024/09/4-768x432.png 768w, https://inero-software.com/wp-content/uploads/2024/09/4-1536x864.png 1536w, https://inero-software.com/wp-content/uploads/2024/09/4-533x300.png 533w, https://inero-software.com/wp-content/uploads/2024/09/4.png 1920w" sizes="(max-width: 744px) 100vw, 744px" /></p>
<p><span style="font-weight: 400;">Now go to the Keycloak admin console. In the realm, navigate to </span><b>Identity Providers</b><span style="font-weight: 400;"> from the left menu. From the </span><b>Add provider</b><span style="font-weight: 400;"> dropdown, select </span><b>GitHub</b><span style="font-weight: 400;">.</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6092" data-permalink="https://inero-software.com/keycloak-integration-guide-enabling-social-login-with-multiple-platforms-like-google/3-10/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/09/3.png" data-orig-size="1305,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="3" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/09/3-300x248.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/09/3-1030x852.png" tabindex="0" role="button" class=" wp-image-6092 aligncenter" src="https://inero-software.com/wp-content/uploads/2024/09/3-300x248.png" alt="" width="709" height="586" srcset="https://inero-software.com/wp-content/uploads/2024/09/3-300x248.png 300w, https://inero-software.com/wp-content/uploads/2024/09/3-1030x852.png 1030w, https://inero-software.com/wp-content/uploads/2024/09/3-768x636.png 768w, https://inero-software.com/wp-content/uploads/2024/09/3-363x300.png 363w, https://inero-software.com/wp-content/uploads/2024/09/3.png 1305w" sizes="(max-width: 709px) 100vw, 709px" /></p>
<p><span style="font-weight: 400;">Paste the </span><b>Client ID and Client Secret</b><span style="font-weight: 400;"> you received from GitHub. If needed, select additional options, such as storing the tokens issued by the provider (for example, for making further calls to resources that accept this token), automatically verifying email addresses, or initiating a specific authentication flow after successful login. After enabling the social provider in the console, the login page should look like this:</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6095" data-permalink="https://inero-software.com/keycloak-integration-guide-enabling-social-login-with-multiple-platforms-like-google/6-4/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/09/6.png" data-orig-size="1147,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="6" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/09/6-300x282.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/09/6-1030x970.png" tabindex="0" role="button" class="alignnone wp-image-6095 aligncenter" src="https://inero-software.com/wp-content/uploads/2024/09/6-300x282.png" alt="" width="586" height="551" srcset="https://inero-software.com/wp-content/uploads/2024/09/6-300x282.png 300w, https://inero-software.com/wp-content/uploads/2024/09/6-1030x970.png 1030w, https://inero-software.com/wp-content/uploads/2024/09/6-768x723.png 768w, https://inero-software.com/wp-content/uploads/2024/09/6-319x300.png 319w, https://inero-software.com/wp-content/uploads/2024/09/6.png 1147w" sizes="(max-width: 586px) 100vw, 586px" /></p>
<p><span style="font-weight: 400;">After clicking the GitHub button we should see a standard OAuth authorization request (this way social providers like GitHub can mark this app as a verified one and automatically allow your further login attempts).</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6091" data-permalink="https://inero-software.com/keycloak-integration-guide-enabling-social-login-with-multiple-platforms-like-google/2-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/09/2.png" data-orig-size="1297,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/09/2-300x250.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/09/2-1030x858.png" tabindex="0" role="button" class="wp-image-6091 aligncenter" src="https://inero-software.com/wp-content/uploads/2024/09/2-300x250.png" alt="" width="691" height="576" srcset="https://inero-software.com/wp-content/uploads/2024/09/2-300x250.png 300w, https://inero-software.com/wp-content/uploads/2024/09/2-1030x858.png 1030w, https://inero-software.com/wp-content/uploads/2024/09/2-768x640.png 768w, https://inero-software.com/wp-content/uploads/2024/09/2-360x300.png 360w, https://inero-software.com/wp-content/uploads/2024/09/2-480x400.png 480w, https://inero-software.com/wp-content/uploads/2024/09/2.png 1297w" sizes="(max-width: 691px) 100vw, 691px" /></p>
<p><span style="font-weight: 400;">After approving the authorization, we should be redirected to the application.</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6090" data-permalink="https://inero-software.com/keycloak-integration-guide-enabling-social-login-with-multiple-platforms-like-google/1-11/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/09/1.png" data-orig-size="1473,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="1" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/09/1-300x220.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/09/1-1030x755.png" tabindex="0" role="button" class="wp-image-6090 aligncenter" src="https://inero-software.com/wp-content/uploads/2024/09/1-300x220.png" alt="" width="633" height="464" srcset="https://inero-software.com/wp-content/uploads/2024/09/1-300x220.png 300w, https://inero-software.com/wp-content/uploads/2024/09/1-1030x755.png 1030w, https://inero-software.com/wp-content/uploads/2024/09/1-768x563.png 768w, https://inero-software.com/wp-content/uploads/2024/09/1-409x300.png 409w, https://inero-software.com/wp-content/uploads/2024/09/1.png 1473w" sizes="(max-width: 633px) 100vw, 633px" /></p>
<h3><b>Conclusion</b></h3>
<p><span style="font-weight: 400;">We walked through the entire process of registering an identity provider in Keycloak, and as you can see, it is quite simple. It’s also a great starting point for further learning OAuth protocol features, handling custom identity providers or providing Single Sign-On (SSO) solutions, which we will possibly explore in the next posts.</span></p>
<p><span style="font-weight: 400;">This approach not only simplifies the registration process and enhances security but also provides a consistent and manageable way to connect with various platforms. Although each provider may have specific configuration nuances, the overall setup process remains straightforward and largely similar across different websites. By reducing the barriers to entry for users and handling authentication efficiently and in a modern way, Keycloak enables a smoother and more secure user experience.</span></p>
<p><a href="https://inero-software.com/contact-us/"><img loading="lazy" decoding="async" data-attachment-id="6110" data-permalink="https://inero-software.com/keycloak-integration-guide-enabling-social-login-with-multiple-platforms-like-google/banery-11092024/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/09/banery-11092024.png" data-orig-size="1200,100" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="banery 11092024" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/09/banery-11092024-300x25.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/09/banery-11092024-1030x86.png" tabindex="0" role="button" class="alignnone wp-image-6110 size-full" src="https://inero-software.com/wp-content/uploads/2024/09/banery-11092024.png" alt="" width="1200" height="100" srcset="https://inero-software.com/wp-content/uploads/2024/09/banery-11092024.png 1200w, https://inero-software.com/wp-content/uploads/2024/09/banery-11092024-300x25.png 300w, https://inero-software.com/wp-content/uploads/2024/09/banery-11092024-1030x86.png 1030w, https://inero-software.com/wp-content/uploads/2024/09/banery-11092024-768x64.png 768w" sizes="(max-width: 1200px) 100vw, 1200px" /></a></p>
<p></p></div><div class="col-sm-1"></div></div>
<p>Artykuł <a href="https://inero-software.com/keycloak-integration-guide-enabling-social-login-with-multiple-platforms-like-google/">Keycloak Integration Guide: Enabling Social Login with Multiple Platforms like Google</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6089</post-id>	</item>
		<item>
		<title>Customizing Your User Experience. How to Create and Apply Custom Themes in Keycloak</title>
		<link>https://inero-software.com/how-to-create-and-apply-custom-themes-in-keycloak/</link>
		
		<dc:creator><![CDATA[Marceli Formela]]></dc:creator>
		<pubDate>Mon, 02 Sep 2024 10:02:40 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Company]]></category>
		<category><![CDATA[Keycloak]]></category>
		<category><![CDATA[Custom]]></category>
		<category><![CDATA[keycloak]]></category>
		<category><![CDATA[Themes]]></category>
		<guid isPermaLink="false">https://inero-software.com/?p=6059</guid>

					<description><![CDATA[<p>&#160;</p>
<p>Artykuł <a href="https://inero-software.com/how-to-create-and-apply-custom-themes-in-keycloak/">Customizing Your User Experience. How to Create and Apply Custom Themes in Keycloak</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>&nbsp;</p>
<div class="row"><div class="col-sm-1"></div><div class="col-sm-10">
<h4><span style="font-weight: 400;">In our last post (</span><a href="https://inero-software.com/exporting-accounts-to-federated-realms/"><span style="font-weight: 400;">Exporting accounts to federated realms: A guide to Keycloak and LDAP Integration</span></a><span style="font-weight: 400;">), we explored how to easily import users into our Keycloak server from another system using the LDAP protocol. This time, we’ll take a closer look at the visual aspect of this solution by customizing the stylesheet for our application and allowing the end-user to get a unique feeling when visiting our site. </span></h4>
<p>&nbsp;</p>
<h3><b>Built-in themes</b></h3>
<p><span style="font-weight: 400;">Keycloak offers extensive customization options for the user interface and appearance through its &#8220;themes.&#8221; Customizing themes allows us to tailor the look and feel of their applications to meet specific needs, not only reinforcing the brand&#8217;s visual identity. </span></p>
<p><span style="font-weight: 400;">Keycloak comes with several pre-built themes bundled within its distribution. The available themes include the base theme, which provides HTML templates and message bundles that all other themes, including custom ones, typically inherit from. The </span><b>keycloak</b><span style="font-weight: 400;"> theme contains images and stylesheets for enhancing page CSS and is used by default if no custom theme is provided. Additionally, the </span><b>keycloak.v2</b><span style="font-weight: 400;"> theme is a React-based theme designed for the new Admin Console, with the older console set for deprecation. Modifying existing themes is not recommended, instead creating a new theme that extends one of them is the preferred approach.</span></p>
<p><span style="font-weight: 400;">For a complete customization, copying the contents from the </span><b>base</b><span style="font-weight: 400;"> folder is ideal, but for partial modification, it&#8217;s more practical to start with the contents from the keycloak directory. As we&#8217;ve already said, only the parts of the theme that need to be overridden should be included in the new custom folder.</span></p>
<p>&nbsp;</p>
<h3><b>FreeMarker Template </b></h3>
<p><span style="font-weight: 400;">FTL themes in Keycloak refer to templates written in Freemarker Template Language that define the look and feel of various pages and emails in Keycloak. These themes allow you to customize everything from login pages to error messages and account management interfaces.</span></p>
<p><span style="font-weight: 400;">Keycloak themes are typically organized into four main categories:</span></p>
<ol>
<li><b>Login</b><span style="font-weight: 400;">: Customizes the appearance of login, registration, and password reset pages.</span></li>
<li><b>Account</b><span style="font-weight: 400;">: Modifies the user account management interface.</span></li>
<li><b>Email</b><span style="font-weight: 400;">: Tailors the content and appearance of emails sent by Keycloak (e.g., verification emails, password reset emails).</span></li>
<li><b>Admin</b><span style="font-weight: 400;">: Allows customization of the Keycloak Admin Console.</span></li>
</ol>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">Let’s take a look at a few quite relevant templates:</span></p>
<ul>
<li style="font-weight: 400;" aria-level="1"><b>login.ftl</b><span style="font-weight: 400;"> &#8211; the most commonly customized template in Keycloak. It is responsible for rendering the login page where users enter their credentials (username/email and password) to access your application.</span></li>
</ul>
<ul>
<li aria-level="1"><b>register.ftl </b><span style="font-weight: 400;">&#8211; used for the registration page where new users can create an account.</span></li>
</ul>
<ul>
<li aria-level="1"><b>login-reset-password.ftl </b><span style="font-weight: 400;">&#8211; used when a user initiates the password reset process.</span></li>
</ul>
<ul>
<li aria-level="1"><b>login-update-password.ftl </b><span style="font-weight: 400;">&#8211;</span><span style="font-weight: 400;"> used when a user is required to update their password, either after a successful password reset or due to a policy requirement (e.g., periodic password changes).</span></li>
</ul>
<h3></h3>
<h3><b>Theme properties</b></h3>
<p><span style="font-weight: 400;">In addition to the HTML templates, message bundles, images and stylesheets, a Keycloak theme includes a few more elements like theme properties. Each theme type has its own configuration file. For instance, consider the theme.properties file from the login theme:</span></p>
<pre><i><span style="font-weight: 400;">parent=keycloak</span></i>
<i><span style="font-weight: 400;">import=common/keycloak</span></i>

<i><span style="font-weight: 400;">styles=css/login.css css/tile.css</span></i>
<i><span style="font-weight: 400;">stylesCommon=web_modules/@fortawesome/fontawesome-free/css/icons/all.css 
web_modules/@patternfly/react-core/dist/styles/base.css 
web_modules/@patternfly/react-core/dist/styles/app.css 
node_modules/patternfly/dist/css/patternfly.min.css 
node_modules/patternfly/dist/css/patternfly-additions.min.css lib/pficon/pficon.css</span></i></pre>
<p><span style="font-weight: 400;">This file shows that the theme inherits from the base theme to utilize its HTML templates and message bundles. It also imports the common theme to include additional styles. Beyond that, the theme specifies its own stylesheet, css/login.css.</span></p>
<p>&nbsp;</p>
<h3><b>Messages and i18n</b></h3>
<p><span style="font-weight: 400;">Keycloak supports internationalization in themes by allowing you to create language-specific properties files, which store translations for text used in templates. These files, named </span><b>messages_&lt;locale&gt;.properties</b><span style="font-weight: 400;"> contain key-value pairs where the key represents a text element, and the value is its translation in the target language. In our FTL templates, we reference these keys using the </span><b>${msg()}</b><span style="font-weight: 400;"> directive, allowing our application to automatically display the appropriate translation.</span></p>
<p><span style="font-weight: 400;">It should refer to the language currently selected by the user. Keycloak determines the language based on browser settings, provided that the language is configured in the system.</span></p>
<p><span style="font-weight: 400;">For example, on the login page, you can provide a translation for the header &#8220;Sign in to your account,&#8221; which may not be translated by default in languages like Dutch or Spanish. To do this, you can edit the </span><b>loginAccountTitle</b><span style="font-weight: 400;"> field in the messages file, adding the appropriate translation for each language. This way, when users select their language, they will see the translated version in the login interface.</span></p>
<pre><i><span style="font-weight: 400;">messages.nl</span></i>
<i><span style="font-weight: 400;">loginAccountTitle=Inloggen</span></i>

<i><span style="font-weight: 400;">messages.es</span></i>
<i><span style="font-weight: 400;">loginAccountTitle=Iniciar sesi\u00F3n</span></i>

<i><span style="font-weight: 400;">messages.en</span></i>
<i><span style="font-weight: 400;">loginAccountTitle=Sign In</span></i></pre>
<p><span style="font-weight: 400;">The final step is to configure the internationalization settings for your realm according to the provided screenshot. This ensures that the translations you added, such as for the loginAccountTitle field, are correctly applied based on the user&#8217;s selected language.</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6061" data-permalink="https://inero-software.com/how-to-create-and-apply-custom-themes-in-keycloak/1-10/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/08/1.png" data-orig-size="1920,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="1" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/08/1-300x169.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/08/1-1030x579.png" tabindex="0" role="button" class="alignnone wp-image-6061 aligncenter" src="https://inero-software.com/wp-content/uploads/2024/08/1-300x169.png" alt="" width="604" height="340" srcset="https://inero-software.com/wp-content/uploads/2024/08/1-300x169.png 300w, https://inero-software.com/wp-content/uploads/2024/08/1-1030x579.png 1030w, https://inero-software.com/wp-content/uploads/2024/08/1-768x432.png 768w, https://inero-software.com/wp-content/uploads/2024/08/1-1536x864.png 1536w, https://inero-software.com/wp-content/uploads/2024/08/1-533x300.png 533w, https://inero-software.com/wp-content/uploads/2024/08/1.png 1920w" sizes="(max-width: 604px) 100vw, 604px" /></p>
<p><span style="font-weight: 400;">The original English version and the final result for the Spanish and Dutch versions is shown below.</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6068" data-permalink="https://inero-software.com/how-to-create-and-apply-custom-themes-in-keycloak/8-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/08/8.png" data-orig-size="1037,569" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="8" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/08/8-300x165.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/08/8-1030x565.png" tabindex="0" role="button" class="alignnone wp-image-6068 aligncenter" src="https://inero-software.com/wp-content/uploads/2024/08/8-300x165.png" alt="" width="478" height="263" srcset="https://inero-software.com/wp-content/uploads/2024/08/8-300x165.png 300w, https://inero-software.com/wp-content/uploads/2024/08/8-1030x565.png 1030w, https://inero-software.com/wp-content/uploads/2024/08/8-768x421.png 768w, https://inero-software.com/wp-content/uploads/2024/08/8-547x300.png 547w, https://inero-software.com/wp-content/uploads/2024/08/8.png 1037w" sizes="(max-width: 478px) 100vw, 478px" /></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6069" data-permalink="https://inero-software.com/how-to-create-and-apply-custom-themes-in-keycloak/9-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/08/9.png" data-orig-size="1053,558" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="9" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/08/9-300x159.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/08/9-1030x546.png" tabindex="0" role="button" class=" wp-image-6069 aligncenter" src="https://inero-software.com/wp-content/uploads/2024/08/9-300x159.png" alt="" width="525" height="278" srcset="https://inero-software.com/wp-content/uploads/2024/08/9-300x159.png 300w, https://inero-software.com/wp-content/uploads/2024/08/9-1030x546.png 1030w, https://inero-software.com/wp-content/uploads/2024/08/9-768x407.png 768w, https://inero-software.com/wp-content/uploads/2024/08/9-566x300.png 566w, https://inero-software.com/wp-content/uploads/2024/08/9.png 1053w" sizes="(max-width: 525px) 100vw, 525px" /></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6070" data-permalink="https://inero-software.com/how-to-create-and-apply-custom-themes-in-keycloak/5-4/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/09/5.png" data-orig-size="997,948" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="5" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/09/5-300x285.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/09/5.png" tabindex="0" role="button" class="alignnone wp-image-6070 aligncenter" src="https://inero-software.com/wp-content/uploads/2024/09/5-300x285.png" alt="" width="524" height="497" srcset="https://inero-software.com/wp-content/uploads/2024/09/5-300x285.png 300w, https://inero-software.com/wp-content/uploads/2024/09/5-768x730.png 768w, https://inero-software.com/wp-content/uploads/2024/09/5-316x300.png 316w, https://inero-software.com/wp-content/uploads/2024/09/5.png 997w" sizes="(max-width: 524px) 100vw, 524px" /></p>
<h3><b>Customizing our theme</b></h3>
<p><span style="font-weight: 400;">Before diving into theme customization, ensure you have a working Keycloak instance. You&#8217;ll need access to the Keycloak server files and administrative privileges to apply the theme. If you&#8217;re running Keycloak in a Docker container, you can use a volume mount to access the theme files on your local machine.</span></p>
<p><span style="font-weight: 400;">Create a directory structure for your custom theme by following the example below. The default theme files are located in the Keycloak server distribution under </span><b><i>themes/keycloak/login</i></b><span style="font-weight: 400;">. To get started, copy these default theme files from the Keycloak distribution to your custom theme directory.</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6066" data-permalink="https://inero-software.com/how-to-create-and-apply-custom-themes-in-keycloak/6-3/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/08/6.png" data-orig-size="966,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="6" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/08/6-268x300.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/08/6-921x1030.png" tabindex="0" role="button" class="alignnone wp-image-6066 aligncenter" src="https://inero-software.com/wp-content/uploads/2024/08/6-268x300.png" alt="" width="375" height="420" srcset="https://inero-software.com/wp-content/uploads/2024/08/6-268x300.png 268w, https://inero-software.com/wp-content/uploads/2024/08/6-921x1030.png 921w, https://inero-software.com/wp-content/uploads/2024/08/6-768x859.png 768w, https://inero-software.com/wp-content/uploads/2024/08/6.png 966w" sizes="(max-width: 375px) 100vw, 375px" /></p>
<p><span style="font-weight: 400;">We’ll start with the basic login page, as shown below:</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6063" data-permalink="https://inero-software.com/how-to-create-and-apply-custom-themes-in-keycloak/3-9/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/08/3.png" data-orig-size="1920,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="3" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/08/3-300x169.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/08/3-1030x579.png" tabindex="0" role="button" class="wp-image-6063 aligncenter" src="https://inero-software.com/wp-content/uploads/2024/08/3-300x169.png" alt="" width="737" height="415" srcset="https://inero-software.com/wp-content/uploads/2024/08/3-300x169.png 300w, https://inero-software.com/wp-content/uploads/2024/08/3-1030x579.png 1030w, https://inero-software.com/wp-content/uploads/2024/08/3-768x432.png 768w, https://inero-software.com/wp-content/uploads/2024/08/3-1536x864.png 1536w, https://inero-software.com/wp-content/uploads/2024/08/3-533x300.png 533w, https://inero-software.com/wp-content/uploads/2024/08/3.png 1920w" sizes="(max-width: 737px) 100vw, 737px" /></p>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">Locate and edit the CSS file that controls the styling of the login page. This is typically named </span><b>login.css</b><span style="font-weight: 400;"> and is found in the </span><b>resources/css</b><span style="font-weight: 400;"> directory of your custom theme. Now we can change background property and provide a custom .png file.</span></p>
<pre><i><span style="font-weight: 400;">.login-pf-page::before {</span></i>
<i><span style="font-weight: 400;">content: "";</span></i>
<i><span style="font-weight: 400;">position: absolute;</span></i>
<i><span style="font-weight: 400;">top: 0;</span></i>
<i><span style="font-weight: 400;">left: 0;</span></i>
<i><span style="font-weight: 400;">width: 100%;</span></i>
<i><span style="font-weight: 400;">height: 100%;  </span></i>
<i><span style="font-weight: 400;">opacity: 1;</span></i>
<b><i>background: rgba(255, 255, 255, 0.4) url("../img/fb-background.png") no-repeat;</i></b>
<i><span style="font-weight: 400;">background-size: cover;</span></i>
<i><span style="font-weight: 400;">    </span></i> <i><span style="font-weight: 400;">z-index: -1;</span></i>
<i><span style="font-weight: 400;">}</span></i></pre>
<p><span style="font-weight: 400;">In addition to changing the background, we can also modify the color of the top border of the login screen and the color of the login button. Then we can add a custom logo. This can be done by modifying the following classes:</span><i></i></p>
<pre><i><span style="font-weight: 400;">pf-m-primary {</span></i>
<i><span style="font-weight: 400;">color: black !important;</span></i>
<b><i>background-color: #B646AE !important;</i></b>
<i><span style="font-weight: 400;">}
</span></i>
<i><span style="font-weight: 400;">.card-pf {</span></i>
<i><span style="font-weight: 400;">margin: 0 auto;</span></i>
<i><span style="font-weight: 400;">box-shadow: var(--pf-global--BoxShadow--lg);</span></i>
<i><span style="font-weight: 400;">padding: 0 20px;</span></i>
<i><span style="font-weight: 400;">max-width: 500px;</span></i>
<i><span style="font-weight: 400;">border-top: 4px solid;</span></i>
<b><i>border-color: #B646AE;</i></b>
<i><span style="font-weight: 400;">background-color: #fff;</span></i>
<i><span style="font-weight: 400;">}</span></i>

<i><span style="font-weight: 400;">#kc-header-wrapper::before {</span></i>
<i><span style="font-weight: 400;">content: "";</span></i>
<i><span style="font-weight: 400;">position: relative;</span></i>
<i><span style="font-weight: 400;">margin: auto;</span></i>
<i><span style="font-weight: 400;">display: block;</span></i>
<i><span style="font-weight: 400;">width: 200px;</span></i>
<b><i>background: url("../img/fb-logo.png") no-repeat;</i></b>
<i><span style="font-weight: 400;">background-size: auto;</span></i>
<i><span style="font-weight: 400;">}</span></i></pre>
<p><span style="font-weight: 400;">The last step will be to activate the custom theme in the administrator console for a specific realm.</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6062" data-permalink="https://inero-software.com/how-to-create-and-apply-custom-themes-in-keycloak/2-10/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/08/2.png" data-orig-size="1920,955" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/08/2-300x149.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/08/2-1030x512.png" tabindex="0" role="button" class="alignnone wp-image-6062 aligncenter" src="https://inero-software.com/wp-content/uploads/2024/08/2-300x149.png" alt="" width="587" height="292" srcset="https://inero-software.com/wp-content/uploads/2024/08/2-300x149.png 300w, https://inero-software.com/wp-content/uploads/2024/08/2-1030x512.png 1030w, https://inero-software.com/wp-content/uploads/2024/08/2-768x382.png 768w, https://inero-software.com/wp-content/uploads/2024/08/2-1536x764.png 1536w, https://inero-software.com/wp-content/uploads/2024/08/2-603x300.png 603w, https://inero-software.com/wp-content/uploads/2024/08/2.png 1920w" sizes="(max-width: 587px) 100vw, 587px" /></p>
<p><span style="font-weight: 400;">After the above changes, the final effect should look like this:</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6067" data-permalink="https://inero-software.com/how-to-create-and-apply-custom-themes-in-keycloak/7-3/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/08/7.png" data-orig-size="1920,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="7" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/08/7-300x169.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/08/7-1030x579.png" tabindex="0" role="button" class="aligncenter wp-image-6067 size-full" src="https://inero-software.com/wp-content/uploads/2024/08/7.png" alt="" width="1920" height="1080" srcset="https://inero-software.com/wp-content/uploads/2024/08/7.png 1920w, https://inero-software.com/wp-content/uploads/2024/08/7-300x169.png 300w, https://inero-software.com/wp-content/uploads/2024/08/7-1030x579.png 1030w, https://inero-software.com/wp-content/uploads/2024/08/7-768x432.png 768w, https://inero-software.com/wp-content/uploads/2024/08/7-1536x864.png 1536w, https://inero-software.com/wp-content/uploads/2024/08/7-533x300.png 533w" sizes="(max-width: 1920px) 100vw, 1920px" /></p>
<p><span style="font-weight: 400;">However, the final result can vary depending on the use of different image files and color definitions. By customizing these elements, you can easily achieve a unique appearance that aligns with your branding and design preferences. Just with different resources it can look like this:</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6064" data-permalink="https://inero-software.com/how-to-create-and-apply-custom-themes-in-keycloak/4-7/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/08/4.png" data-orig-size="1920,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="4" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/08/4-300x169.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/08/4-1030x579.png" tabindex="0" role="button" class="alignnone wp-image-6064 size-full" src="https://inero-software.com/wp-content/uploads/2024/08/4.png" alt="" width="1920" height="1080" srcset="https://inero-software.com/wp-content/uploads/2024/08/4.png 1920w, https://inero-software.com/wp-content/uploads/2024/08/4-300x169.png 300w, https://inero-software.com/wp-content/uploads/2024/08/4-1030x579.png 1030w, https://inero-software.com/wp-content/uploads/2024/08/4-768x432.png 768w, https://inero-software.com/wp-content/uploads/2024/08/4-1536x864.png 1536w, https://inero-software.com/wp-content/uploads/2024/08/4-533x300.png 533w" sizes="(max-width: 1920px) 100vw, 1920px" /></p>
<p><span style="font-weight: 400;">As you can see now, customizing the Keycloak theme is pretty straightforward.</span></p>
<p>&nbsp;</p>
<p><span style="font-weight: 400;">So far, we discussed how to customize Keycloak themes by adjusting visual elements. We covered the basics of Keycloak&#8217;s built-in themes, which include options for customizing the login page. In most cases, the process involves copying default theme files, modifying CSS for styling changes like background images and button colors, and editing FreeMarker templates for layout adjustments. Additionally, we explored how to use the theme.properties file to configure your custom theme. Now we have some basic tools to modify Keycloak&#8217;s appearance to better fit the brand and user needs.</span></p>
<p>&nbsp;</p>
<h3><strong>Summary</strong></h3>
<ul>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">You can fully customize the login page to ensure it doesn&#8217;t resemble a Keycloak default theme. This not only improves the user experience but also helps users easily distinguish the legitimate login page from potential phishing attempts.</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Keycloak also allows you to customize the content and layout of email (i.e. password reset templates). By making unique, branded content you can help users recognize legitimate password reset requests, reducing the risk of falling victim to phishing attacks that mimic these emails.</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Beyond visual customization, themes support internationalization, enabling you to provide users with a familiar experience in their native language. This can include translating all text on login pages and in emails to the appropriate language. It enhances usability for global users.</span></li>
</ul>
<p><span style="font-weight: 400;">Overall, customizing themes offers a range of possibilities to enhance the user experience and security of your IAM system.</span></p>
<h3>Do you need assistance with Keycloak implementation, updates, or training? Contact me</h3>
<p><span style="font-size: 8.0pt; font-family: 'Calibri',sans-serif; color: black;">             <img loading="lazy" decoding="async" data-attachment-id="5903" data-permalink="https://inero-software.com/?attachment_id=5903" data-orig-file="https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1.png" data-orig-size="1200,1200" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="Andrzej Chybicki PhD Eng. (1)" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-300x300.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-1030x1030.png" tabindex="0" role="button" class="size-medium wp-image-5903 alignleft" src="https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-300x300.png" alt="" width="300" height="300" srcset="https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-300x300.png 300w, https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-1030x1030.png 1030w, https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-80x80.png 80w, https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-768x768.png 768w, https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-75x75.png 75w, https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-50x50.png 50w, https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-512x512.png 512w, https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1-1024x1024.png 1024w, https://inero-software.com/wp-content/uploads/2024/06/Andrzej-Chybicki-PhD-Eng.-1.png 1200w" sizes="(max-width: 300px) 100vw, 300px" /></span></p>
<p><strong>Andrzej Chybicki </strong></p>
<p>CEO, Inero Software Sp. z o. o.<br />
andy@inero-software.com<br />
Phone: +48 695 875 588</p>
<p><a href="https://www.linkedin.com/in/andrzej-chybicki/"><img loading="lazy" decoding="async" data-attachment-id="5897" data-permalink="https://inero-software.com/?attachment_id=5897" data-orig-file="https://inero-software.com/wp-content/uploads/2024/06/logo-linkedin.png" data-orig-size="100,100" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="logo linkedin" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/06/logo-linkedin.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/06/logo-linkedin.png" tabindex="0" role="button" class="alignnone size-full wp-image-5897" src="https://inero-software.com/wp-content/uploads/2024/06/logo-linkedin.png" alt="" width="100" height="100" srcset="https://inero-software.com/wp-content/uploads/2024/06/logo-linkedin.png 100w, https://inero-software.com/wp-content/uploads/2024/06/logo-linkedin-80x80.png 80w, https://inero-software.com/wp-content/uploads/2024/06/logo-linkedin-75x75.png 75w, https://inero-software.com/wp-content/uploads/2024/06/logo-linkedin-50x50.png 50w" sizes="(max-width: 100px) 100vw, 100px" /></a></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p></p></div><div class="col-sm-1"></div></div>
<p>Artykuł <a href="https://inero-software.com/how-to-create-and-apply-custom-themes-in-keycloak/">Customizing Your User Experience. How to Create and Apply Custom Themes in Keycloak</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6059</post-id>	</item>
		<item>
		<title>Exporting accounts to federated realms: A guide to Keycloak and LDAP Integration</title>
		<link>https://inero-software.com/exporting-accounts-to-federated-realms/</link>
		
		<dc:creator><![CDATA[Marceli Formela]]></dc:creator>
		<pubDate>Fri, 26 Jul 2024 08:27:48 +0000</pubDate>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Company]]></category>
		<category><![CDATA[Keycloak]]></category>
		<category><![CDATA[Directory Information Tree]]></category>
		<category><![CDATA[DIT]]></category>
		<category><![CDATA[features]]></category>
		<category><![CDATA[identity provider]]></category>
		<category><![CDATA[keycloak]]></category>
		<category><![CDATA[LDAP]]></category>
		<category><![CDATA[Lightweight Directory Access Protocol]]></category>
		<category><![CDATA[Protocol variations]]></category>
		<guid isPermaLink="false">https://inero-software.com/?p=6022</guid>

					<description><![CDATA[<p>Artykuł <a href="https://inero-software.com/exporting-accounts-to-federated-realms/">Exporting accounts to federated realms: A guide to Keycloak and LDAP Integration</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="row"><div class="col-sm-1"></div><div class="col-sm-10">
<h4></h4>
<h4><strong>We know from the previous posts that Keycloak as an identity provider gives us a platform for managing user identities, securing applications, and integrating with different providers. Therefore, one powerful feature of Keycloak is its ability to integrate with Lightweight Directory Access Protocol (LDAP) directories. This article provides a quick guide for account export to federated realms through migrating users with their credentials and importing groups by custom mappers.</strong></h4>
<p>&nbsp;</p>
<h3><b>Understanding directory services</b></h3>
<p><span style="font-weight: 400;">A directory service is built to manage and store data in a format of key-value pairs. This structure is optimized for read-heavy operations, making it particularly well-suited for information that is frequently accessed but infrequently updated. The data within such a directory is often descriptive, serving to detail various attributes of entities.</span></p>
<p><span style="font-weight: 400;">For example, imagine using a directory service to manage an address book. Each entry in this address book represents an individual person, with key-value pairs capturing their contact details, place of employment, and other relevant information. This method of data organization is especially beneficial when dealing with qualitative and descriptive information that needs to be easily retrievable.</span></p>
<p><span style="font-weight: 400;">LDAP operates using a hierarchical directory structure, which enables it to store and access data efficiently. This protocol is widely used to keep track of organizational details, including information about users, assets, and various entities. Its hierarchical model supports a flexible approach to defining and managing these entities and their attributes, ensuring that the directory service remains adaptable to different organizational needs and scalable as data grows.</span></p>
<h3><b>Key features of LDAP</b></h3>
<ul>
<li style="font-weight: 400;" aria-level="1"><b>Standardized Protocol</b><span style="font-weight: 400;">: LDAP is a widely recognized protocol supported by numerous directory services, including Microsoft Active Directory, OpenLDAP, and Apache Directory Server.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Hierarchical Structure</b><span style="font-weight: 400;">: LDAP directories are structured hierarchically, similar to a tree, facilitating the efficient organization and retrieval of information.</span></li>
<li style="font-weight: 400;" aria-level="1"><b>Scalability</b><span style="font-weight: 400;">: LDAP is optimized to manage a high volume of read and search operations efficiently, making it ideal for large-scale enterprise environments with extensive user bases.</span></li>
</ul>
<p>&nbsp;</p>
<h3><b>LDAP architecture</b></h3>
<p><span style="font-weight: 400;">Understanding the architecture of LDAP is crucial for maximizing its utility. The primary components include:</span></p>
<p>&nbsp;</p>
<h4><b>Directory Information Tree (DIT)</b></h4>
<p><span style="font-weight: 400;">The directory&#8217;s hierarchical structure consists of entries, each representing an object like a user, group, or device, and uniquely identified by a Distinguished Name (DN). The DIT is organized hierarchically, with the root of the tree at the top. Below the root are various levels of nodes, each representing different types of entities such as organizations, departments, and individual users. This hierarchical setup allows for an efficient and logical way of managing and accessing directory data.</span></p>
<h4><b>Attributes / Entries</b></h4>
<p><span style="font-weight: 400;">Attributes are grouped within entities called objectClasses, which are collections of related attributes useful for describing specific entities. When creating an entry, you can utilize the attributes defined by an objectClass by assigning the desired objectClass to the entry. In fact, the objectClass attribute is the only attribute you can set without specifying further objectClasses.</span></p>
<p><span style="font-weight: 400;">For instance, when creating an entry to represent a person, including the objectClass—or any derived objectClasses—enables the use of all the attributes associated with that specific objectClass. In such an entry, you might set attributes like cn for the common name, description for a brief overview of the entry, and sn for the surname.</span></p>
<h4><b>Schema</b></h4>
<p><span style="font-weight: 400;">Attribute and object classes are grouped together as something we call a schema. This mechanism takes care of consistency and integrity in the directory tree we use. Unlike relational databases, these schemas are simply collections of related objects and attributes. A single Directory Information Tree (DIT) can utilize multiple schemas to create the necessary entries and attributes.</span></p>
<p><span style="font-weight: 400;">Schemas typically include extra attribute specifications and may require attributes outlined in other schemas. For instance, the person objectClass requires the inclusion of the surname (sn) attribute for any related entries. In cases where these attributes are absent from the LDAP server, a schema including these definitions can be integrated into the server’s tree structure.</span></p>
<p>&nbsp;</p>
<h2><b>Protocol variations</b></h2>
<p><span style="font-weight: 400;">LDAP is essentially a protocol that defines a communication interface for working with directory services, often referred to as LDAP or ldap. There are several variants of the LDAP protocol format worth noting:</span></p>
<ul>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">ldaps://: This variation stands for LDAP secured by SSL/TLS. Although standard LDAP traffic is unencrypted, most LDAP implementations support encryption. However, using SSL/TLS for LDAP encryption is deprecated, and the recommended way to secure LDAP connections is STARTTLS.</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">ldap://: This is a standard LDAP protocol that provides structured access to a directory service.</span></li>
<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">ldapi://: This variation stands for LDAP over IPC (Inter-Process Communication). Typically used for secure local connections to an LDAP system for administrative purposes, for example using internal sockets.</span></li>
</ul>
<p><span style="font-weight: 400;">While all three formats use the LDAP protocol, the two of them provide just additional context on the method of communication.</span></p>
<p>&nbsp;</p>
<h3><b>Returning to the realm and configuring LDAP</b></h3>
<p>After familiarizing yourself with the theory of LDAP operation, we can return to the realm, whose configuration we mentioned in the previous post (<a href="https://inero-software.com/enhancing-identity-management-with-keycloak-user-federations/">you can find it here</a>), and go to the User Federation tab, where we can enter the necessary data to connect to the LDAP server provided by the sample provider.</p>
<p><img loading="lazy" decoding="async" data-attachment-id="6023" data-permalink="https://inero-software.com/exporting-accounts-to-federated-realms/4-6/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/07/4.jpg" data-orig-size="1920,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="4" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/07/4-300x169.jpg" data-large-file="https://inero-software.com/wp-content/uploads/2024/07/4-1030x579.jpg" tabindex="0" role="button" class="wp-image-6023 aligncenter" src="https://inero-software.com/wp-content/uploads/2024/07/4.jpg" alt="" width="714" height="402" srcset="https://inero-software.com/wp-content/uploads/2024/07/4.jpg 1920w, https://inero-software.com/wp-content/uploads/2024/07/4-300x169.jpg 300w, https://inero-software.com/wp-content/uploads/2024/07/4-1030x579.jpg 1030w, https://inero-software.com/wp-content/uploads/2024/07/4-768x432.jpg 768w, https://inero-software.com/wp-content/uploads/2024/07/4-1536x864.jpg 1536w, https://inero-software.com/wp-content/uploads/2024/07/4-533x300.jpg 533w" sizes="(max-width: 714px) 100vw, 714px" /></p>
<p><span style="font-weight: 400;">The essential information we need includes the connection URL, the distinguished name of the LDAP admin (bind DN), and the distinguished name of the users (users DN), which is the parent of all users in the LDAP tree. Most attributes, such as the LDAP username, LDAP UUID, or user object classes, can be left at their default values as they align with our LDAP server provider requirements.</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6024" data-permalink="https://inero-software.com/exporting-accounts-to-federated-realms/7-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/07/7.jpg" data-orig-size="1920,710" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="7" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/07/7-300x111.jpg" data-large-file="https://inero-software.com/wp-content/uploads/2024/07/7-1030x381.jpg" tabindex="0" role="button" class="wp-image-6024 aligncenter" src="https://inero-software.com/wp-content/uploads/2024/07/7.jpg" alt="" width="715" height="264" srcset="https://inero-software.com/wp-content/uploads/2024/07/7.jpg 1920w, https://inero-software.com/wp-content/uploads/2024/07/7-300x111.jpg 300w, https://inero-software.com/wp-content/uploads/2024/07/7-1030x381.jpg 1030w, https://inero-software.com/wp-content/uploads/2024/07/7-768x284.jpg 768w, https://inero-software.com/wp-content/uploads/2024/07/7-1536x568.jpg 1536w, https://inero-software.com/wp-content/uploads/2024/07/7-811x300.jpg 811w" sizes="(max-width: 715px) 100vw, 715px" /></p>
<p><span style="font-weight: 400;">After synchronizing users, we see that two new entries have appeared in the </span><b>Users</b><span style="font-weight: 400;"> tab. Synchronization with LDAP offers more possibilities than just simple user account import. Let&#8217;s check out how mappers work.</span></p>
<h4><b>Example 1: hardcoded-attribute-mapper</b></h4>
<p><span style="font-weight: 400;">For instance, we can mark imported users by assigning them a custom attribute. This can be done using a hardcoded-attribute-mapper, which assigns a new attribute, authenticationMethod, to each new user and gives it the value &#8220;ldap&#8221;. </span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6025" data-permalink="https://inero-software.com/exporting-accounts-to-federated-realms/6-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/07/6.jpg" data-orig-size="1920,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="6" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/07/6-300x169.jpg" data-large-file="https://inero-software.com/wp-content/uploads/2024/07/6-1030x579.jpg" tabindex="0" role="button" class="wp-image-6025 aligncenter" src="https://inero-software.com/wp-content/uploads/2024/07/6.jpg" alt="" width="597" height="336" srcset="https://inero-software.com/wp-content/uploads/2024/07/6.jpg 1920w, https://inero-software.com/wp-content/uploads/2024/07/6-300x169.jpg 300w, https://inero-software.com/wp-content/uploads/2024/07/6-1030x579.jpg 1030w, https://inero-software.com/wp-content/uploads/2024/07/6-768x432.jpg 768w, https://inero-software.com/wp-content/uploads/2024/07/6-1536x864.jpg 1536w, https://inero-software.com/wp-content/uploads/2024/07/6-533x300.jpg 533w" sizes="(max-width: 597px) 100vw, 597px" /></p>
<p><span style="font-weight: 400;">In the </span><b>Users</b><span style="font-weight: 400;"> -&gt; </span><b>User Details</b><span style="font-weight: 400;"> -&gt; </span><b>Attributes</b><span style="font-weight: 400;"> tab, we can then see that users originating from LDAP indeed have this attribute. It can, for example, be included in access tokens.</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6026" data-permalink="https://inero-software.com/exporting-accounts-to-federated-realms/3-8/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/07/3.jpg" data-orig-size="1920,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="3" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/07/3-300x169.jpg" data-large-file="https://inero-software.com/wp-content/uploads/2024/07/3-1030x579.jpg" tabindex="0" role="button" class="wp-image-6026 aligncenter" src="https://inero-software.com/wp-content/uploads/2024/07/3.jpg" alt="" width="608" height="342" srcset="https://inero-software.com/wp-content/uploads/2024/07/3.jpg 1920w, https://inero-software.com/wp-content/uploads/2024/07/3-300x169.jpg 300w, https://inero-software.com/wp-content/uploads/2024/07/3-1030x579.jpg 1030w, https://inero-software.com/wp-content/uploads/2024/07/3-768x432.jpg 768w, https://inero-software.com/wp-content/uploads/2024/07/3-1536x864.jpg 1536w, https://inero-software.com/wp-content/uploads/2024/07/3-533x300.jpg 533w" sizes="(max-width: 608px) 100vw, 608px" /></p>
<h4><b>Example 2: group-ldap-mapper</b></h4>
<p><span style="font-weight: 400;">Often, LDAP defines a system of roles or groups that imported users belong to. Keycloak can also import groups and automatically assign the aforementioned users to them. To do this, we can configure another mapper, this time of the group-ldap-mapper type, as shown in the image below:</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6027" data-permalink="https://inero-software.com/exporting-accounts-to-federated-realms/5-2/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/07/5.jpg" data-orig-size="1920,1080" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="5" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/07/5-300x169.jpg" data-large-file="https://inero-software.com/wp-content/uploads/2024/07/5-1030x579.jpg" tabindex="0" role="button" class="alignnone wp-image-6027 size-full" src="https://inero-software.com/wp-content/uploads/2024/07/5.jpg" alt="" width="1920" height="1080" srcset="https://inero-software.com/wp-content/uploads/2024/07/5.jpg 1920w, https://inero-software.com/wp-content/uploads/2024/07/5-300x169.jpg 300w, https://inero-software.com/wp-content/uploads/2024/07/5-1030x579.jpg 1030w, https://inero-software.com/wp-content/uploads/2024/07/5-768x432.jpg 768w, https://inero-software.com/wp-content/uploads/2024/07/5-1536x864.jpg 1536w, https://inero-software.com/wp-content/uploads/2024/07/5-533x300.jpg 533w" sizes="(max-width: 1920px) 100vw, 1920px" /></p>
<p><span style="font-weight: 400;">In this case, the distinguished name for groups will be the same as the DN for all users, i.e.</span></p>
<p style="padding-left: 80px;"><span style="font-weight: 400; color: #0000ff;">ou=Users,o=66a20b93d2f2fc6db2e89ff3,dc=jumpcloud,dc=com</span></p>
<p><span style="font-weight: 400;">The groups stored in LDAP are defined by an object class named groupOfNames, which means that the attribute representing membership on the LDAP side will typically be member. Now, let&#8217;s try synchronizing our groups.</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6028" data-permalink="https://inero-software.com/exporting-accounts-to-federated-realms/image_15/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/07/image_15.jpg" data-orig-size="595,82" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="image_15" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/07/image_15-300x41.jpg" data-large-file="https://inero-software.com/wp-content/uploads/2024/07/image_15.jpg" tabindex="0" role="button" class="wp-image-6028 aligncenter" src="https://inero-software.com/wp-content/uploads/2024/07/image_15-300x41.jpg" alt="" width="622" height="85" srcset="https://inero-software.com/wp-content/uploads/2024/07/image_15-300x41.jpg 300w, https://inero-software.com/wp-content/uploads/2024/07/image_15.jpg 595w" sizes="(max-width: 622px) 100vw, 622px" /></p>
<p><span style="font-weight: 400;">As we can see, three groups were correctly imported, along with the relationships between a group and its users. Therefore, LDAP administrators can easily receive the corresponding permissions on our realm side. Subsequently, we could link specific roles to a given group to manage resource access even more conveniently.</span></p>
<p><img loading="lazy" decoding="async" data-attachment-id="6031" data-permalink="https://inero-software.com/exporting-accounts-to-federated-realms/2-9/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/07/2.jpg" data-orig-size="1920,959" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="2" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/07/2-300x150.jpg" data-large-file="https://inero-software.com/wp-content/uploads/2024/07/2-1030x514.jpg" tabindex="0" role="button" class="alignnone wp-image-6031 size-full" src="https://inero-software.com/wp-content/uploads/2024/07/2.jpg" alt="" width="1920" height="959" srcset="https://inero-software.com/wp-content/uploads/2024/07/2.jpg 1920w, https://inero-software.com/wp-content/uploads/2024/07/2-300x150.jpg 300w, https://inero-software.com/wp-content/uploads/2024/07/2-1030x514.jpg 1030w, https://inero-software.com/wp-content/uploads/2024/07/2-768x384.jpg 768w, https://inero-software.com/wp-content/uploads/2024/07/2-1536x767.jpg 1536w, https://inero-software.com/wp-content/uploads/2024/07/2-601x300.jpg 601w" sizes="(max-width: 1920px) 100vw, 1920px" /><img loading="lazy" decoding="async" data-attachment-id="6030" data-permalink="https://inero-software.com/exporting-accounts-to-federated-realms/1-9/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/07/1.jpg" data-orig-size="1920,881" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="1" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/07/1-300x138.jpg" data-large-file="https://inero-software.com/wp-content/uploads/2024/07/1-1030x473.jpg" tabindex="0" role="button" class="alignnone wp-image-6030 size-full" src="https://inero-software.com/wp-content/uploads/2024/07/1.jpg" alt="" width="1920" height="881" srcset="https://inero-software.com/wp-content/uploads/2024/07/1.jpg 1920w, https://inero-software.com/wp-content/uploads/2024/07/1-300x138.jpg 300w, https://inero-software.com/wp-content/uploads/2024/07/1-1030x473.jpg 1030w, https://inero-software.com/wp-content/uploads/2024/07/1-768x352.jpg 768w, https://inero-software.com/wp-content/uploads/2024/07/1-1536x705.jpg 1536w, https://inero-software.com/wp-content/uploads/2024/07/1-654x300.jpg 654w" sizes="(max-width: 1920px) 100vw, 1920px" /></p>
<h3><b>Summary</b></h3>
<p><span style="font-weight: 400;">Integrating Keycloak with LDAP is a powerful tool for managing identities and security within an organization. This integration allows for efficient synchronization of users and groups from LDAP, enabling centralized management of permissions and resource access. Key steps include configuring the LDAP connection, synchronizing data, and using mappers to customize imported information, such as attributes and user groups. It’s important to understand LDAP&#8217;s architecture and operations to fully leverage its capabilities. Implementing LDAP with Keycloak not only streamlines account management but also enhances security and simplifies integration with existing systems. By utilizing mappers, we can further tailor how information is imported and used in our system, leading to better organization and control over access within the organization.</span></p>
<p><a href="https://inero-software.com/keycloak-services/"><img loading="lazy" decoding="async" data-attachment-id="6008" data-permalink="https://inero-software.com/challenges-and-benefits-of-integrating-keycloak-compliance-with-the-nis-2-directive-and-practical-implementation-advice/banery-16072024en-inero/" data-orig-file="https://inero-software.com/wp-content/uploads/2024/07/banery-16072024en-inero.png" data-orig-size="1200,100" data-comments-opened="0" data-image-meta="{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}" data-image-title="banery 16072024en inero" data-image-description="" data-image-caption="" data-medium-file="https://inero-software.com/wp-content/uploads/2024/07/banery-16072024en-inero-300x25.png" data-large-file="https://inero-software.com/wp-content/uploads/2024/07/banery-16072024en-inero-1030x86.png" tabindex="0" role="button" class="alignnone wp-image-6008 size-full" src="https://inero-software.com/wp-content/uploads/2024/07/banery-16072024en-inero.png" alt="" width="1200" height="100" srcset="https://inero-software.com/wp-content/uploads/2024/07/banery-16072024en-inero.png 1200w, https://inero-software.com/wp-content/uploads/2024/07/banery-16072024en-inero-300x25.png 300w, https://inero-software.com/wp-content/uploads/2024/07/banery-16072024en-inero-1030x86.png 1030w, https://inero-software.com/wp-content/uploads/2024/07/banery-16072024en-inero-768x64.png 768w" sizes="(max-width: 1200px) 100vw, 1200px" /></a></p>
<p></p></div><div class="col-sm-1"></div></div>
<p>Artykuł <a href="https://inero-software.com/exporting-accounts-to-federated-realms/">Exporting accounts to federated realms: A guide to Keycloak and LDAP Integration</a> pochodzi z serwisu <a href="https://inero-software.com">Inero Software - Software Consulting</a>.</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">6022</post-id>	</item>
	</channel>
</rss>
